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

Side by Side Diff: src/objects.cc

Issue 10444055: Promoting elements transitions to their own field. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: full patch Created 8 years, 6 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
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 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 610 matching lines...) Expand 10 before | Expand all | Expand 10 after
621 return result->holder()->GetPropertyWithCallback( 621 return result->holder()->GetPropertyWithCallback(
622 receiver, result->GetCallbackObject(), name); 622 receiver, result->GetCallbackObject(), name);
623 case HANDLER: 623 case HANDLER:
624 return result->proxy()->GetPropertyWithHandler(receiver, name); 624 return result->proxy()->GetPropertyWithHandler(receiver, name);
625 case INTERCEPTOR: { 625 case INTERCEPTOR: {
626 JSObject* recvr = JSObject::cast(receiver); 626 JSObject* recvr = JSObject::cast(receiver);
627 return result->holder()->GetPropertyWithInterceptor( 627 return result->holder()->GetPropertyWithInterceptor(
628 recvr, name, attributes); 628 recvr, name, attributes);
629 } 629 }
630 case MAP_TRANSITION: 630 case MAP_TRANSITION:
631 case ELEMENTS_TRANSITION:
632 case CONSTANT_TRANSITION: 631 case CONSTANT_TRANSITION:
633 case NULL_DESCRIPTOR: 632 case NULL_DESCRIPTOR:
634 break; 633 break;
635 } 634 }
636 UNREACHABLE(); 635 UNREACHABLE();
637 return NULL; 636 return NULL;
638 } 637 }
639 638
640 639
641 MaybeObject* Object::GetElementWithReceiver(Object* receiver, uint32_t index) { 640 MaybeObject* Object::GetElementWithReceiver(Object* receiver, uint32_t index) {
(...skipping 902 matching lines...) Expand 10 before | Expand all | Expand 10 after
1544 } 1543 }
1545 } 1544 }
1546 1545
1547 // Only allow map transition if the object isn't the global object and there 1546 // Only allow map transition if the object isn't the global object and there
1548 // is not a transition for the name, or there's a transition for the name but 1547 // is not a transition for the name, or there's a transition for the name but
1549 // it's unrelated to properties. 1548 // it's unrelated to properties.
1550 int descriptor_index = old_descriptors->Search(name); 1549 int descriptor_index = old_descriptors->Search(name);
1551 1550
1552 // Element transitions are stored in the descriptor for property "", which is 1551 // Element transitions are stored in the descriptor for property "", which is
1553 // not a identifier and should have forced a switch to slow properties above. 1552 // not a identifier and should have forced a switch to slow properties above.
1554 ASSERT(descriptor_index == DescriptorArray::kNotFound || 1553 bool can_insert_transition = descriptor_index == DescriptorArray::kNotFound;
1555 old_descriptors->GetType(descriptor_index) != ELEMENTS_TRANSITION);
1556 bool can_insert_transition = descriptor_index == DescriptorArray::kNotFound ||
1557 old_descriptors->GetType(descriptor_index) == ELEMENTS_TRANSITION;
1558 bool allow_map_transition = 1554 bool allow_map_transition =
1559 can_insert_transition && 1555 can_insert_transition &&
1560 (isolate->context()->global_context()->object_function()->map() != map()); 1556 (isolate->context()->global_context()->object_function()->map() != map());
1561 1557
1562 ASSERT(index < map()->inobject_properties() || 1558 ASSERT(index < map()->inobject_properties() ||
1563 (index - map()->inobject_properties()) < properties()->length() || 1559 (index - map()->inobject_properties()) < properties()->length() ||
1564 map()->unused_property_fields() == 0); 1560 map()->unused_property_fields() == 0);
1565 // Allocate a new map for the object. 1561 // Allocate a new map for the object.
1566 Object* r; 1562 Object* r;
1567 { MaybeObject* maybe_r = map()->CopyDropDescriptors(); 1563 { MaybeObject* maybe_r = map()->CopyDropDescriptors();
1568 if (!maybe_r->ToObject(&r)) return maybe_r; 1564 if (!maybe_r->ToObject(&r)) return maybe_r;
1569 } 1565 }
1570 Map* new_map = Map::cast(r); 1566 Map* new_map = Map::cast(r);
1571 if (allow_map_transition) { 1567 if (allow_map_transition) {
1572 // Allocate new instance descriptors for the old map with map transition. 1568 // Allocate new instance descriptors for the old map with map transition.
1573 MapTransitionDescriptor d(name, Map::cast(new_map), attributes); 1569 MapTransitionDescriptor d(name, Map::cast(new_map), attributes);
1574 Object* r; 1570 Object* r;
1575 { MaybeObject* maybe_r = old_descriptors->CopyInsert(&d, KEEP_TRANSITIONS); 1571 {
danno 2012/06/01 13:49:55 nit: No need for this whitespace change.
Toon Verwaest 2012/06/04 09:17:48 Done.
1572 MaybeObject* maybe_r = old_descriptors->CopyInsert(&d, KEEP_TRANSITIONS);
1576 if (!maybe_r->ToObject(&r)) return maybe_r; 1573 if (!maybe_r->ToObject(&r)) return maybe_r;
1577 } 1574 }
1578 old_descriptors = DescriptorArray::cast(r); 1575 old_descriptors = DescriptorArray::cast(r);
1579 } 1576 }
1580 1577
1581 if (map()->unused_property_fields() == 0) { 1578 if (map()->unused_property_fields() == 0) {
1582 if (properties()->length() > MaxFastProperties()) { 1579 if (properties()->length() > MaxFastProperties()) {
1583 Object* obj; 1580 Object* obj;
1584 { MaybeObject* maybe_obj = 1581 { MaybeObject* maybe_obj =
1585 NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); 1582 NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0);
1586 if (!maybe_obj->ToObject(&obj)) return maybe_obj; 1583 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
1587 } 1584 }
1588 return AddSlowProperty(name, value, attributes); 1585 return AddSlowProperty(name, value, attributes);
1589 } 1586 }
1590 // Make room for the new value 1587 // Make room for the new value
1591 Object* values; 1588 Object* values;
1592 { MaybeObject* maybe_values = 1589 { MaybeObject* maybe_values =
1593 properties()->CopySize(properties()->length() + kFieldsAdded); 1590 properties()->CopySize(properties()->length() + kFieldsAdded);
1594 if (!maybe_values->ToObject(&values)) return maybe_values; 1591 if (!maybe_values->ToObject(&values)) return maybe_values;
1595 } 1592 }
1596 set_properties(FixedArray::cast(values)); 1593 set_properties(FixedArray::cast(values));
1597 new_map->set_unused_property_fields(kFieldsAdded - 1); 1594 new_map->set_unused_property_fields(kFieldsAdded - 1);
1598 } else { 1595 } else {
1599 new_map->set_unused_property_fields(map()->unused_property_fields() - 1); 1596 new_map->set_unused_property_fields(map()->unused_property_fields() - 1);
1600 } 1597 }
1601 // We have now allocated all the necessary objects. 1598 // We have now allocated all the necessary objects.
1602 // All the changes can be applied at once, so they are atomic. 1599 // All the changes can be applied at once, so they are atomic.
1603 map()->set_instance_descriptors(old_descriptors); 1600 if (allow_map_transition) {
1601 map()->set_instance_descriptors(old_descriptors);
1602 }
1604 new_map->SetBackPointer(map()); 1603 new_map->SetBackPointer(map());
1605 new_map->set_instance_descriptors(DescriptorArray::cast(new_descriptors)); 1604 new_map->set_instance_descriptors(DescriptorArray::cast(new_descriptors));
1606 set_map(new_map); 1605 set_map(new_map);
1607 return FastPropertyAtPut(index, value); 1606 return FastPropertyAtPut(index, value);
1608 } 1607 }
1609 1608
1610 1609
1611 MaybeObject* JSObject::AddConstantFunctionProperty( 1610 MaybeObject* JSObject::AddConstantFunctionProperty(
1612 String* name, 1611 String* name,
1613 JSFunction* function, 1612 JSFunction* function,
(...skipping 585 matching lines...) Expand 10 before | Expand all | Expand 10 after
2199 2198
2200 2199
2201 Handle<Map> Map::FindTransitionedMap(MapHandleList* candidates) { 2200 Handle<Map> Map::FindTransitionedMap(MapHandleList* candidates) {
2202 ElementsKind kind = elements_kind(); 2201 ElementsKind kind = elements_kind();
2203 Handle<Map> transitioned_map = Handle<Map>::null(); 2202 Handle<Map> transitioned_map = Handle<Map>::null();
2204 Handle<Map> current_map(this); 2203 Handle<Map> current_map(this);
2205 bool packed = IsFastPackedElementsKind(kind); 2204 bool packed = IsFastPackedElementsKind(kind);
2206 if (IsTransitionableFastElementsKind(kind)) { 2205 if (IsTransitionableFastElementsKind(kind)) {
2207 while (CanTransitionToMoreGeneralFastElementsKind(kind, false)) { 2206 while (CanTransitionToMoreGeneralFastElementsKind(kind, false)) {
2208 kind = GetNextMoreGeneralFastElementsKind(kind, false); 2207 kind = GetNextMoreGeneralFastElementsKind(kind, false);
2209 bool dummy = true;
2210 Handle<Map> maybe_transitioned_map = 2208 Handle<Map> maybe_transitioned_map =
2211 MaybeNull(current_map->LookupElementsTransitionMap(kind, &dummy)); 2209 MaybeNull(current_map->LookupElementsTransitionMap(kind));
2212 if (maybe_transitioned_map.is_null()) break; 2210 if (maybe_transitioned_map.is_null()) break;
2213 if (ContainsMap(candidates, maybe_transitioned_map) && 2211 if (ContainsMap(candidates, maybe_transitioned_map) &&
2214 (packed || !IsFastPackedElementsKind(kind))) { 2212 (packed || !IsFastPackedElementsKind(kind))) {
2215 transitioned_map = maybe_transitioned_map; 2213 transitioned_map = maybe_transitioned_map;
2216 if (!IsFastPackedElementsKind(kind)) packed = false; 2214 if (!IsFastPackedElementsKind(kind)) packed = false;
2217 } 2215 }
2218 current_map = maybe_transitioned_map; 2216 current_map = maybe_transitioned_map;
2219 } 2217 }
2220 } 2218 }
2221 return transitioned_map; 2219 return transitioned_map;
2222 } 2220 }
2223 2221
2224 2222
2225 static Map* GetElementsTransitionMapFromDescriptor(Object* descriptor_contents, 2223 static Map* FindClosestElementsTransition(Map* map, ElementsKind to_kind) {
2226 ElementsKind elements_kind) { 2224 Map* current_map = map;
2227 if (descriptor_contents->IsMap()) { 2225 int index = GetSequenceIndexFromFastElementsKind(map->elements_kind());
2228 Map* map = Map::cast(descriptor_contents); 2226 int to_index = GetSequenceIndexFromFastElementsKind(to_kind);
2229 if (map->elements_kind() == elements_kind) { 2227 for (; index < to_index; ++index) {
2230 return map; 2228 Map* next_map = current_map->elements_transition();
2229 if (next_map == NULL) {
2230 return current_map;
2231 } 2231 }
2232 return NULL; 2232 current_map = next_map;
2233 } 2233 }
2234 2234 ASSERT(current_map->elements_kind() == to_kind);
2235 FixedArray* map_array = FixedArray::cast(descriptor_contents); 2235 return current_map;
2236 for (int i = 0; i < map_array->length(); ++i) {
2237 Object* current = map_array->get(i);
2238 // Skip undefined slots, they are sentinels for reclaimed maps.
2239 if (!current->IsUndefined()) {
2240 Map* current_map = Map::cast(map_array->get(i));
2241 if (current_map->elements_kind() == elements_kind) {
2242 return current_map;
2243 }
2244 }
2245 }
2246
2247 return NULL;
2248 } 2236 }
2249 2237
2250 2238
2251 static MaybeObject* AddElementsTransitionMapToDescriptor( 2239 Map* Map::LookupElementsTransitionMap(ElementsKind to_kind) {
2252 Object* descriptor_contents, 2240 if (this->instance_descriptors()->MayContainTransitions() &&
2253 Map* new_map) { 2241 IsMoreGeneralElementsKindTransition(this->elements_kind(), to_kind)) {
2254 // Nothing was in the descriptor for an ELEMENTS_TRANSITION, 2242 Map* to_map = FindClosestElementsTransition(this, to_kind);
2255 // simply add the map. 2243 if (to_map->elements_kind() == to_kind) {
2256 if (descriptor_contents == NULL) { 2244 return to_map;
2257 return new_map;
2258 }
2259
2260 // There was already a map in the descriptor, create a 2-element FixedArray
2261 // to contain the existing map plus the new one.
2262 FixedArray* new_array;
2263 Heap* heap = new_map->GetHeap();
2264 if (descriptor_contents->IsMap()) {
2265 // Must tenure, DescriptorArray expects no new-space objects.
2266 MaybeObject* maybe_new_array = heap->AllocateFixedArray(2, TENURED);
2267 if (!maybe_new_array->To<FixedArray>(&new_array)) {
2268 return maybe_new_array;
2269 }
2270 new_array->set(0, descriptor_contents);
2271 new_array->set(1, new_map);
2272 return new_array;
2273 }
2274
2275 // The descriptor already contained a list of maps for different ElementKinds
2276 // of ELEMENTS_TRANSITION, first check the existing array for an undefined
2277 // slot, and if that's not available, create a FixedArray to hold the existing
2278 // maps plus the new one and fill it in.
2279 FixedArray* array = FixedArray::cast(descriptor_contents);
2280 for (int i = 0; i < array->length(); ++i) {
2281 if (array->get(i)->IsUndefined()) {
2282 array->set(i, new_map);
2283 return array;
2284 }
2285 }
2286
2287 // Must tenure, DescriptorArray expects no new-space objects.
2288 MaybeObject* maybe_new_array =
2289 heap->AllocateFixedArray(array->length() + 1, TENURED);
2290 if (!maybe_new_array->To<FixedArray>(&new_array)) {
2291 return maybe_new_array;
2292 }
2293 int i = 0;
2294 while (i < array->length()) {
2295 new_array->set(i, array->get(i));
2296 ++i;
2297 }
2298 new_array->set(i, new_map);
2299 return new_array;
2300 }
2301
2302
2303 String* Map::elements_transition_sentinel_name() {
2304 return GetHeap()->empty_symbol();
2305 }
2306
2307
2308 Object* Map::GetDescriptorContents(String* sentinel_name,
2309 bool* safe_to_add_transition) {
2310 // Get the cached index for the descriptors lookup, or find and cache it.
2311 DescriptorArray* descriptors = instance_descriptors();
2312 DescriptorLookupCache* cache = GetIsolate()->descriptor_lookup_cache();
2313 int index = cache->Lookup(descriptors, sentinel_name);
2314 if (index == DescriptorLookupCache::kAbsent) {
2315 index = descriptors->Search(sentinel_name);
2316 cache->Update(descriptors, sentinel_name, index);
2317 }
2318 // If the transition already exists, return its descriptor.
2319 if (index != DescriptorArray::kNotFound) {
2320 PropertyDetails details = descriptors->GetDetails(index);
2321 if (details.type() == ELEMENTS_TRANSITION) {
2322 return descriptors->GetValue(index);
2323 } else {
2324 if (safe_to_add_transition != NULL) {
2325 *safe_to_add_transition = false;
2326 }
2327 } 2245 }
2328 } 2246 }
2329 return NULL; 2247 return NULL;
2330 } 2248 }
2331 2249
2332 2250
2333 Map* Map::LookupElementsTransitionMap(ElementsKind to_kind, 2251 MaybeObject* Map::CreateNextElementsTransition(ElementsKind next_kind) {
2334 bool* safe_to_add_transition) { 2252 ASSERT(elements_transition() == NULL);
2335 ElementsKind from_kind = elements_kind(); 2253 ASSERT(GetSequenceIndexFromFastElementsKind(elements_kind()) ==
2336 if (IsFastElementsKind(from_kind) && IsFastElementsKind(to_kind)) { 2254 (GetSequenceIndexFromFastElementsKind(next_kind) - 1));
2337 if (!IsMoreGeneralElementsKindTransition(from_kind, to_kind)) {
2338 if (safe_to_add_transition) *safe_to_add_transition = false;
2339 return NULL;
2340 }
2341 ElementsKind transitioned_from_kind =
2342 GetNextMoreGeneralFastElementsKind(from_kind, false);
2343 2255
2256 Map* next_map;
2257 MaybeObject* maybe_next_map = this->CopyDropTransitions(true);
2258 if (!maybe_next_map->To(&next_map)) return maybe_next_map;
2344 2259
2345 // If the transition is a single step in the transition sequence, fall 2260 next_map->set_elements_kind(next_kind);
2346 // through to looking it up and returning it. If it requires several steps, 2261 next_map->SetBackPointer(this);
2347 // divide and conquer. 2262 this->set_elements_transition(next_map);
2348 if (transitioned_from_kind != to_kind) { 2263 return next_map;
2349 // If the transition is several steps in the lattice, divide and conquer.
2350 Map* from_map = LookupElementsTransitionMap(transitioned_from_kind,
2351 safe_to_add_transition);
2352 if (from_map == NULL) return NULL;
2353 return from_map->LookupElementsTransitionMap(to_kind,
2354 safe_to_add_transition);
2355 }
2356 }
2357 Object* descriptor_contents = GetDescriptorContents(
2358 elements_transition_sentinel_name(), safe_to_add_transition);
2359 if (descriptor_contents != NULL) {
2360 Map* maybe_transition_map =
2361 GetElementsTransitionMapFromDescriptor(descriptor_contents,
2362 to_kind);
2363 ASSERT(maybe_transition_map == NULL || maybe_transition_map->IsMap());
2364 return maybe_transition_map;
2365 }
2366 return NULL;
2367 } 2264 }
2368 2265
2369 2266
2370 MaybeObject* Map::AddElementsTransition(ElementsKind to_kind, 2267 static MaybeObject* AddMissingElementsTransitions(Map* map,
2371 Map* transitioned_map) { 2268 ElementsKind to_kind) {
2372 ElementsKind from_kind = elements_kind(); 2269 int index = GetSequenceIndexFromFastElementsKind(map->elements_kind()) + 1;
2373 if (IsFastElementsKind(from_kind) && IsFastElementsKind(to_kind)) { 2270 int to_index = GetSequenceIndexFromFastElementsKind(to_kind);
2374 ASSERT(IsMoreGeneralElementsKindTransition(from_kind, to_kind)); 2271 ASSERT(index <= to_index);
2375 ElementsKind transitioned_from_kind =
2376 GetNextMoreGeneralFastElementsKind(from_kind, false);
2377 // The map transitions graph should be a tree, therefore transitions to
2378 // ElementsKind that are not adjacent in the ElementsKind sequence are not
2379 // done directly, but instead by going through intermediate ElementsKinds
2380 // first.
2381 if (to_kind != transitioned_from_kind) {
2382 bool safe_to_add = true;
2383 Map* intermediate_map = LookupElementsTransitionMap(
2384 transitioned_from_kind, &safe_to_add);
2385 // This method is only called when safe_to_add has been found to be true
2386 // earlier.
2387 ASSERT(safe_to_add);
2388 2272
2389 if (intermediate_map == NULL) { 2273 Map* current_map = map;
2390 MaybeObject* maybe_map = CopyDropTransitions(); 2274
2391 if (!maybe_map->To(&intermediate_map)) return maybe_map; 2275 for (; index <= to_index; ++index) {
2392 intermediate_map->set_elements_kind(transitioned_from_kind); 2276 ElementsKind next_kind = GetFastElementsKindFromSequenceIndex(index);
2393 MaybeObject* maybe_transition = AddElementsTransition( 2277 MaybeObject* maybe_next_map =
2394 transitioned_from_kind, intermediate_map); 2278 current_map->CreateNextElementsTransition(next_kind);
2395 if (maybe_transition->IsFailure()) return maybe_transition; 2279 if (!maybe_next_map->To(&current_map)) return maybe_next_map;
2396 }
2397 return intermediate_map->AddElementsTransition(to_kind, transitioned_map);
2398 }
2399 } 2280 }
2400 2281
2401 bool safe_to_add_transition = true; 2282 ASSERT(current_map->elements_kind() == to_kind);
2402 Object* descriptor_contents = GetDescriptorContents( 2283 return current_map;
2403 elements_transition_sentinel_name(), &safe_to_add_transition);
2404 // This method is only called when safe_to_add_transition has been found
2405 // to be true earlier.
2406 ASSERT(safe_to_add_transition);
2407 MaybeObject* maybe_new_contents =
2408 AddElementsTransitionMapToDescriptor(descriptor_contents,
2409 transitioned_map);
2410 Object* new_contents;
2411 if (!maybe_new_contents->ToObject(&new_contents)) {
2412 return maybe_new_contents;
2413 }
2414
2415 ElementsTransitionDescriptor desc(elements_transition_sentinel_name(),
2416 new_contents);
2417 Object* new_descriptors;
2418 MaybeObject* maybe_new_descriptors =
2419 instance_descriptors()->CopyInsert(&desc, KEEP_TRANSITIONS);
2420 if (!maybe_new_descriptors->ToObject(&new_descriptors)) {
2421 return maybe_new_descriptors;
2422 }
2423 set_instance_descriptors(DescriptorArray::cast(new_descriptors));
2424 transitioned_map->SetBackPointer(this);
2425 return this;
2426 } 2284 }
2427 2285
2428 2286
2429 Handle<Map> JSObject::GetElementsTransitionMap(Handle<JSObject> object, 2287 Handle<Map> JSObject::GetElementsTransitionMap(Handle<JSObject> object,
2430 ElementsKind to_kind) { 2288 ElementsKind to_kind) {
2431 Isolate* isolate = object->GetIsolate(); 2289 Isolate* isolate = object->GetIsolate();
2432 CALL_HEAP_FUNCTION(isolate, 2290 CALL_HEAP_FUNCTION(isolate,
2433 object->GetElementsTransitionMap(isolate, to_kind), 2291 object->GetElementsTransitionMap(isolate, to_kind),
2434 Map); 2292 Map);
2435 } 2293 }
2436 2294
2437 2295
2296 // If the map is using the empty descriptor array, install a new empty
2297 // descriptor array that will contain an element transition.
2298 // TODO(verwaest) Goes away once the descriptor array is immutable.
2299 static MaybeObject* EnsureMayContainTransitions(Map* map) {
2300 if (map->instance_descriptors()->MayContainTransitions()) return map;
2301 DescriptorArray* descriptor_array;
2302 MaybeObject* maybe_descriptor_array = DescriptorArray::Allocate(0, true);
2303 if (!maybe_descriptor_array->To(&descriptor_array)) {
2304 return maybe_descriptor_array;
2305 }
2306 map->set_instance_descriptors(descriptor_array);
2307 return map;
2308 }
2309
2310
2438 MaybeObject* JSObject::GetElementsTransitionMapSlow(ElementsKind to_kind) { 2311 MaybeObject* JSObject::GetElementsTransitionMapSlow(ElementsKind to_kind) {
2439 Map* current_map = map(); 2312 Map* start_map = map();
2440 ElementsKind from_kind = current_map->elements_kind(); 2313 ElementsKind from_kind = start_map->elements_kind();
2441 2314
2442 if (from_kind == to_kind) return current_map; 2315 if (from_kind == to_kind) {
2443 2316 return start_map;
2444 // Only objects with FastProperties can have DescriptorArrays and can track
2445 // element-related maps. Also don't add descriptors to maps that are shared.
2446 bool safe_to_add_transition = HasFastProperties() &&
2447 !current_map->IsUndefined() &&
2448 !current_map->is_shared();
2449
2450 // Prevent long chains of DICTIONARY -> FAST_*_ELEMENTS maps caused by objects
2451 // with elements that switch back and forth between dictionary and fast
2452 // element modes.
2453 if (from_kind == DICTIONARY_ELEMENTS &&
2454 IsFastElementsKind(to_kind)) {
2455 safe_to_add_transition = false;
2456 } 2317 }
2457 2318
2458 if (safe_to_add_transition) { 2319 Context* global_context = GetIsolate()->context()->global_context();
2459 // It's only safe to manipulate the descriptor array if it would be 2320 bool allow_store_transition =
2460 // safe to add a transition. 2321 // Only remember the map transition if the object's map is NOT equal to
danno 2012/06/01 13:49:55 nit: indentation
Toon Verwaest 2012/06/04 09:17:48 Done.
2461 Map* maybe_transition_map = current_map->LookupElementsTransitionMap( 2322 // the global object_function's map and there is not an already existing
2462 to_kind, &safe_to_add_transition); 2323 // non-matching element transition.
2463 if (maybe_transition_map != NULL) { 2324 (global_context->object_function()->map() != map()) &&
2464 return maybe_transition_map; 2325 !start_map->IsUndefined() && !start_map->is_shared() &&
2465 } 2326 // Only store fast element maps in ascending generality.
2327 IsTransitionableFastElementsKind(from_kind) &&
2328 IsFastElementsKind(to_kind) &&
2329 IsMoreGeneralElementsKindTransition(from_kind, to_kind);
2330
2331 if (!allow_store_transition) {
2332 // Create a new free-floating map only if we are not allowed to store it.
2333 Map* new_map = NULL;
2334 MaybeObject* maybe_new_map = start_map->CopyDropTransitions(false);
2335 if (!maybe_new_map->To(&new_map)) return maybe_new_map;
2336 new_map->set_elements_kind(to_kind);
2337 return new_map;
2466 } 2338 }
2467 2339
2468 Map* new_map = NULL; 2340 EnsureMayContainTransitions(start_map);
2341 Map* closest_map = FindClosestElementsTransition(start_map, to_kind);
2469 2342
2470 // No transition to an existing map for the given ElementsKind. Make a new 2343 if (closest_map->elements_kind() == to_kind) {
2471 // one. 2344 return closest_map;
2472 { MaybeObject* maybe_map = current_map->CopyDropTransitions();
2473 if (!maybe_map->To(&new_map)) return maybe_map;
2474 } 2345 }
2475 2346
2476 new_map->set_elements_kind(to_kind); 2347 return AddMissingElementsTransitions(closest_map, to_kind);
2477
2478 // Only remember the map transition if the object's map is NOT equal to the
2479 // global object_function's map and there is not an already existing
2480 // non-matching element transition.
2481 Context* global_context = GetIsolate()->context()->global_context();
2482 bool allow_map_transition = safe_to_add_transition &&
2483 (global_context->object_function()->map() != map());
2484 if (allow_map_transition) {
2485 MaybeObject* maybe_transition =
2486 current_map->AddElementsTransition(to_kind, new_map);
2487 if (maybe_transition->IsFailure()) return maybe_transition;
2488 }
2489 return new_map;
2490 } 2348 }
2491 2349
2492 2350
2493 void JSObject::LocalLookupRealNamedProperty(String* name, 2351 void JSObject::LocalLookupRealNamedProperty(String* name,
2494 LookupResult* result) { 2352 LookupResult* result) {
2495 if (IsJSGlobalProxy()) { 2353 if (IsJSGlobalProxy()) {
2496 Object* proto = GetPrototype(); 2354 Object* proto = GetPrototype();
2497 if (proto->IsNull()) return result->NotFound(); 2355 if (proto->IsNull()) return result->NotFound();
2498 ASSERT(proto->IsJSGlobalObject()); 2356 ASSERT(proto->IsJSGlobalObject());
2499 // A GlobalProxy's prototype should always be a proper JSObject. 2357 // A GlobalProxy's prototype should always be a proper JSObject.
(...skipping 498 matching lines...) Expand 10 before | Expand all | Expand 10 after
2998 JSFunction::cast(target_descriptors->GetValue(number)); 2856 JSFunction::cast(target_descriptors->GetValue(number));
2999 if (value == function) { 2857 if (value == function) {
3000 set_map(target_map); 2858 set_map(target_map);
3001 return value; 2859 return value;
3002 } 2860 }
3003 // Otherwise, replace with a MAP_TRANSITION to a new map with a 2861 // Otherwise, replace with a MAP_TRANSITION to a new map with a
3004 // FIELD, even if the value is a constant function. 2862 // FIELD, even if the value is a constant function.
3005 return ConvertDescriptorToFieldAndMapTransition(name, value, attributes); 2863 return ConvertDescriptorToFieldAndMapTransition(name, value, attributes);
3006 } 2864 }
3007 case NULL_DESCRIPTOR: 2865 case NULL_DESCRIPTOR:
3008 case ELEMENTS_TRANSITION:
3009 return ConvertDescriptorToFieldAndMapTransition(name, value, attributes); 2866 return ConvertDescriptorToFieldAndMapTransition(name, value, attributes);
3010 case HANDLER: 2867 case HANDLER:
3011 UNREACHABLE(); 2868 UNREACHABLE();
3012 return value; 2869 return value;
3013 } 2870 }
3014 UNREACHABLE(); // keep the compiler happy 2871 UNREACHABLE(); // keep the compiler happy
3015 return value; 2872 return value;
3016 } 2873 }
3017 2874
3018 2875
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
3096 // Preserve the attributes of this existing property. 2953 // Preserve the attributes of this existing property.
3097 attributes = result.GetAttributes(); 2954 attributes = result.GetAttributes();
3098 return ConvertDescriptorToField(name, value, attributes); 2955 return ConvertDescriptorToField(name, value, attributes);
3099 case CALLBACKS: 2956 case CALLBACKS:
3100 case INTERCEPTOR: 2957 case INTERCEPTOR:
3101 // Override callback in clone 2958 // Override callback in clone
3102 return ConvertDescriptorToField(name, value, attributes); 2959 return ConvertDescriptorToField(name, value, attributes);
3103 case CONSTANT_TRANSITION: 2960 case CONSTANT_TRANSITION:
3104 // Replace with a MAP_TRANSITION to a new map with a FIELD, even 2961 // Replace with a MAP_TRANSITION to a new map with a FIELD, even
3105 // if the value is a function. 2962 // if the value is a function.
3106 return ConvertDescriptorToFieldAndMapTransition(name, value, attributes);
3107 case NULL_DESCRIPTOR: 2963 case NULL_DESCRIPTOR:
3108 case ELEMENTS_TRANSITION:
3109 return ConvertDescriptorToFieldAndMapTransition(name, value, attributes); 2964 return ConvertDescriptorToFieldAndMapTransition(name, value, attributes);
3110 case HANDLER: 2965 case HANDLER:
3111 UNREACHABLE(); 2966 UNREACHABLE();
3112 } 2967 }
3113 UNREACHABLE(); // keep the compiler happy 2968 UNREACHABLE(); // keep the compiler happy
3114 return value; 2969 return value;
3115 } 2970 }
3116 2971
3117 2972
3118 PropertyAttributes JSObject::GetPropertyAttributePostInterceptor( 2973 PropertyAttributes JSObject::GetPropertyAttributePostInterceptor(
(...skipping 270 matching lines...) Expand 10 before | Expand all | Expand 10 after
3389 } 3244 }
3390 MaybeObject* maybe_dictionary = 3245 MaybeObject* maybe_dictionary =
3391 dictionary->Add(descs->GetKey(i), value, details); 3246 dictionary->Add(descs->GetKey(i), value, details);
3392 if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary; 3247 if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary;
3393 break; 3248 break;
3394 } 3249 }
3395 case MAP_TRANSITION: 3250 case MAP_TRANSITION:
3396 case CONSTANT_TRANSITION: 3251 case CONSTANT_TRANSITION:
3397 case NULL_DESCRIPTOR: 3252 case NULL_DESCRIPTOR:
3398 case INTERCEPTOR: 3253 case INTERCEPTOR:
3399 case ELEMENTS_TRANSITION:
3400 break; 3254 break;
3401 case HANDLER: 3255 case HANDLER:
3402 case NORMAL: 3256 case NORMAL:
3403 UNREACHABLE(); 3257 UNREACHABLE();
3404 break; 3258 break;
3405 } 3259 }
3406 } 3260 }
3407 3261
3408 Heap* current_heap = GetHeap(); 3262 Heap* current_heap = GetHeap();
3409 3263
(...skipping 765 matching lines...) Expand 10 before | Expand all | Expand 10 after
4175 { MaybeObject* maybe = NormalizeElements(); 4029 { MaybeObject* maybe = NormalizeElements();
4176 if (!maybe->To<SeededNumberDictionary>(&dictionary)) return maybe; 4030 if (!maybe->To<SeededNumberDictionary>(&dictionary)) return maybe;
4177 } 4031 }
4178 ASSERT(HasDictionaryElements() || HasDictionaryArgumentsElements()); 4032 ASSERT(HasDictionaryElements() || HasDictionaryArgumentsElements());
4179 // Make sure that we never go back to fast case. 4033 // Make sure that we never go back to fast case.
4180 dictionary->set_requires_slow_elements(); 4034 dictionary->set_requires_slow_elements();
4181 4035
4182 // Do a map transition, other objects with this map may still 4036 // Do a map transition, other objects with this map may still
4183 // be extensible. 4037 // be extensible.
4184 Map* new_map; 4038 Map* new_map;
4185 { MaybeObject* maybe = map()->CopyDropTransitions(); 4039 { MaybeObject* maybe = map()->CopyDropTransitions(false);
danno 2012/06/01 13:49:55 This should be an enum rather than a bool, it's re
Toon Verwaest 2012/06/04 09:17:48 Done.
4186 if (!maybe->To<Map>(&new_map)) return maybe; 4040 if (!maybe->To<Map>(&new_map)) return maybe;
4187 } 4041 }
4188 new_map->set_is_extensible(false); 4042 new_map->set_is_extensible(false);
4189 set_map(new_map); 4043 set_map(new_map);
4190 ASSERT(!map()->is_extensible()); 4044 ASSERT(!map()->is_extensible());
4191 return new_map; 4045 return new_map;
4192 } 4046 }
4193 4047
4194 4048
4195 // Tests for the fast common case for property enumeration: 4049 // Tests for the fast common case for property enumeration:
(...skipping 759 matching lines...) Expand 10 before | Expand all | Expand 10 after
4955 Map::cast(result)->set_inobject_properties(inobject_properties()); 4809 Map::cast(result)->set_inobject_properties(inobject_properties());
4956 Map::cast(result)->set_unused_property_fields(unused_property_fields()); 4810 Map::cast(result)->set_unused_property_fields(unused_property_fields());
4957 4811
4958 // If the map has pre-allocated properties always start out with a descriptor 4812 // If the map has pre-allocated properties always start out with a descriptor
4959 // array describing these properties. 4813 // array describing these properties.
4960 if (pre_allocated_property_fields() > 0) { 4814 if (pre_allocated_property_fields() > 0) {
4961 ASSERT(constructor()->IsJSFunction()); 4815 ASSERT(constructor()->IsJSFunction());
4962 JSFunction* ctor = JSFunction::cast(constructor()); 4816 JSFunction* ctor = JSFunction::cast(constructor());
4963 Object* descriptors; 4817 Object* descriptors;
4964 { MaybeObject* maybe_descriptors = 4818 { MaybeObject* maybe_descriptors =
4965 ctor->initial_map()->instance_descriptors()->RemoveTransitions(); 4819 ctor->initial_map()->instance_descriptors()->RemoveTransitions(false);
4966 if (!maybe_descriptors->ToObject(&descriptors)) return maybe_descriptors; 4820 if (!maybe_descriptors->ToObject(&descriptors)) return maybe_descriptors;
4967 } 4821 }
4968 Map::cast(result)->set_instance_descriptors( 4822 Map::cast(result)->set_instance_descriptors(
4969 DescriptorArray::cast(descriptors)); 4823 DescriptorArray::cast(descriptors));
4970 Map::cast(result)->set_pre_allocated_property_fields( 4824 Map::cast(result)->set_pre_allocated_property_fields(
4971 pre_allocated_property_fields()); 4825 pre_allocated_property_fields());
4972 } 4826 }
4973 Map::cast(result)->set_bit_field(bit_field()); 4827 Map::cast(result)->set_bit_field(bit_field());
4974 Map::cast(result)->set_bit_field2(bit_field2()); 4828 Map::cast(result)->set_bit_field2(bit_field2());
4975 Map::cast(result)->set_bit_field3(bit_field3()); 4829 Map::cast(result)->set_bit_field3(bit_field3());
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
5008 #ifdef DEBUG 4862 #ifdef DEBUG
5009 if (FLAG_verify_heap && Map::cast(result)->is_shared()) { 4863 if (FLAG_verify_heap && Map::cast(result)->is_shared()) {
5010 Map::cast(result)->SharedMapVerify(); 4864 Map::cast(result)->SharedMapVerify();
5011 } 4865 }
5012 #endif 4866 #endif
5013 4867
5014 return result; 4868 return result;
5015 } 4869 }
5016 4870
5017 4871
5018 MaybeObject* Map::CopyDropTransitions() { 4872 MaybeObject* Map::CopyDropTransitions(bool mutable_transitions) {
5019 Object* new_map; 4873 Object* new_map;
5020 { MaybeObject* maybe_new_map = CopyDropDescriptors(); 4874 { MaybeObject* maybe_new_map = CopyDropDescriptors();
5021 if (!maybe_new_map->ToObject(&new_map)) return maybe_new_map; 4875 if (!maybe_new_map->ToObject(&new_map)) return maybe_new_map;
5022 } 4876 }
5023 Object* descriptors; 4877 Object* descriptors;
5024 { MaybeObject* maybe_descriptors = 4878 { MaybeObject* maybe_descriptors =
5025 instance_descriptors()->RemoveTransitions(); 4879 instance_descriptors()->RemoveTransitions(mutable_transitions);
5026 if (!maybe_descriptors->ToObject(&descriptors)) return maybe_descriptors; 4880 if (!maybe_descriptors->ToObject(&descriptors)) return maybe_descriptors;
5027 } 4881 }
5028 cast(new_map)->set_instance_descriptors(DescriptorArray::cast(descriptors)); 4882 cast(new_map)->set_instance_descriptors(DescriptorArray::cast(descriptors));
5029 return new_map; 4883 return new_map;
5030 } 4884 }
5031 4885
5032 void Map::UpdateCodeCache(Handle<Map> map, 4886 void Map::UpdateCodeCache(Handle<Map> map,
5033 Handle<String> name, 4887 Handle<String> name,
5034 Handle<Code> code) { 4888 Handle<Code> code) {
5035 Isolate* isolate = map->GetIsolate(); 4889 Isolate* isolate = map->GetIsolate();
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
5081 4935
5082 // An iterator over all map transitions in an descriptor array, reusing the map 4936 // An iterator over all map transitions in an descriptor array, reusing the map
5083 // field of the contens array while it is running. 4937 // field of the contens array while it is running.
5084 class IntrusiveMapTransitionIterator { 4938 class IntrusiveMapTransitionIterator {
5085 public: 4939 public:
5086 explicit IntrusiveMapTransitionIterator(DescriptorArray* descriptor_array) 4940 explicit IntrusiveMapTransitionIterator(DescriptorArray* descriptor_array)
5087 : descriptor_array_(descriptor_array) { } 4941 : descriptor_array_(descriptor_array) { }
5088 4942
5089 void Start() { 4943 void Start() {
5090 ASSERT(!IsIterating()); 4944 ASSERT(!IsIterating());
5091 if (HasDescriptors()) *DescriptorArrayHeader() = Smi::FromInt(0); 4945 if (descriptor_array_->MayContainTransitions())
danno 2012/06/01 13:49:55 This is confusing. What does descriptor iteration
Toon Verwaest 2012/06/04 09:17:48 As discussed offline, won't change since it is act
4946 *DescriptorArrayHeader() = Smi::FromInt(0);
5092 } 4947 }
5093 4948
5094 bool IsIterating() { 4949 bool IsIterating() {
5095 return HasDescriptors() && (*DescriptorArrayHeader())->IsSmi(); 4950 return descriptor_array_->MayContainTransitions() &&
4951 (*DescriptorArrayHeader())->IsSmi();
5096 } 4952 }
5097 4953
5098 Map* Next() { 4954 Map* Next() {
5099 ASSERT(IsIterating()); 4955 ASSERT(IsIterating());
5100 // Attention, tricky index manipulation ahead: Two consecutive indices are 4956 // Attention, tricky index manipulation ahead: Two consecutive indices are
5101 // assigned to each descriptor. Most descriptors directly advance to the 4957 // assigned to each descriptor. Most descriptors directly advance to the
5102 // next descriptor by adding 2 to the index. The exceptions are the 4958 // next descriptor by adding 2 to the index. The exceptions are the
5103 // CALLBACKS entries: An even index means we look at its getter, and an odd 4959 // CALLBACKS entries: An even index means we look at its getter, and an odd
5104 // index means we look at its setter. 4960 // index means we look at its setter.
5105 int raw_index = Smi::cast(*DescriptorArrayHeader())->value(); 4961 int raw_index = Smi::cast(*DescriptorArrayHeader())->value();
5106 int index = raw_index / 2; 4962 int index = raw_index / 2;
5107 int number_of_descriptors = descriptor_array_->number_of_descriptors(); 4963 int number_of_descriptors = descriptor_array_->number_of_descriptors();
5108 while (index < number_of_descriptors) { 4964 while (index < number_of_descriptors) {
5109 PropertyDetails details(descriptor_array_->GetDetails(index)); 4965 PropertyDetails details(descriptor_array_->GetDetails(index));
5110 switch (details.type()) { 4966 switch (details.type()) {
5111 case MAP_TRANSITION: 4967 case MAP_TRANSITION:
5112 case CONSTANT_TRANSITION: 4968 case CONSTANT_TRANSITION:
5113 case ELEMENTS_TRANSITION:
5114 // We definitely have a map transition. 4969 // We definitely have a map transition.
5115 *DescriptorArrayHeader() = Smi::FromInt(raw_index + 2); 4970 *DescriptorArrayHeader() = Smi::FromInt(raw_index + 2);
5116 return static_cast<Map*>(descriptor_array_->GetValue(index)); 4971 return static_cast<Map*>(descriptor_array_->GetValue(index));
5117 case CALLBACKS: { 4972 case CALLBACKS: {
5118 // We might have a map transition in a getter or in a setter. 4973 // We might have a map transition in a getter or in a setter.
5119 AccessorPair* accessors = 4974 AccessorPair* accessors =
5120 static_cast<AccessorPair*>(descriptor_array_->GetValue(index)); 4975 static_cast<AccessorPair*>(descriptor_array_->GetValue(index));
5121 Object* accessor; 4976 Object* accessor;
5122 if ((raw_index & 1) == 0) { 4977 if ((raw_index & 1) == 0) {
5123 accessor = accessors->setter(); 4978 accessor = accessors->setter();
(...skipping 13 matching lines...) Expand all
5137 case CONSTANT_FUNCTION: 4992 case CONSTANT_FUNCTION:
5138 case HANDLER: 4993 case HANDLER:
5139 case INTERCEPTOR: 4994 case INTERCEPTOR:
5140 case NULL_DESCRIPTOR: 4995 case NULL_DESCRIPTOR:
5141 // We definitely have no map transition. 4996 // We definitely have no map transition.
5142 raw_index += 2; 4997 raw_index += 2;
5143 ++index; 4998 ++index;
5144 break; 4999 break;
5145 } 5000 }
5146 } 5001 }
5002 if (index == descriptor_array_->number_of_descriptors()) {
5003 Map* elements_transition = descriptor_array_->elements_transition();
5004 if (elements_transition != NULL) {
5005 *DescriptorArrayHeader() = Smi::FromInt(index + 1);
5006 return elements_transition;
5007 }
5008 }
5147 *DescriptorArrayHeader() = descriptor_array_->GetHeap()->fixed_array_map(); 5009 *DescriptorArrayHeader() = descriptor_array_->GetHeap()->fixed_array_map();
5148 return NULL; 5010 return NULL;
5149 } 5011 }
5150 5012
5151 private: 5013 private:
5152 bool HasDescriptors() {
5153 return descriptor_array_->length() > DescriptorArray::kFirstIndex;
5154 }
5155
5156 Object** DescriptorArrayHeader() { 5014 Object** DescriptorArrayHeader() {
5157 return HeapObject::RawField(descriptor_array_, DescriptorArray::kMapOffset); 5015 return HeapObject::RawField(descriptor_array_, DescriptorArray::kMapOffset);
5158 } 5016 }
5159 5017
5160 DescriptorArray* descriptor_array_; 5018 DescriptorArray* descriptor_array_;
5161 }; 5019 };
5162 5020
5163 5021
5164 // An iterator over all prototype transitions, reusing the map field of the 5022 // An iterator over all prototype transitions, reusing the map field of the
5165 // underlying array while it is running. 5023 // underlying array while it is running.
(...skipping 668 matching lines...) Expand 10 before | Expand all | Expand 10 after
5834 bool FixedArray::IsEqualTo(FixedArray* other) { 5692 bool FixedArray::IsEqualTo(FixedArray* other) {
5835 if (length() != other->length()) return false; 5693 if (length() != other->length()) return false;
5836 for (int i = 0 ; i < length(); ++i) { 5694 for (int i = 0 ; i < length(); ++i) {
5837 if (get(i) != other->get(i)) return false; 5695 if (get(i) != other->get(i)) return false;
5838 } 5696 }
5839 return true; 5697 return true;
5840 } 5698 }
5841 #endif 5699 #endif
5842 5700
5843 5701
5844 MaybeObject* DescriptorArray::Allocate(int number_of_descriptors) { 5702 MaybeObject* DescriptorArray::Allocate(int number_of_descriptors,
5703 bool mutable_transition) {
5845 Heap* heap = Isolate::Current()->heap(); 5704 Heap* heap = Isolate::Current()->heap();
5846 if (number_of_descriptors == 0) { 5705 if (number_of_descriptors == 0 && !mutable_transition) {
5847 return heap->empty_descriptor_array(); 5706 return heap->empty_descriptor_array();
5848 } 5707 }
5849 // Allocate the array of keys. 5708 // Allocate the array of keys.
5850 Object* array; 5709 Object* array;
5851 { MaybeObject* maybe_array = 5710 { MaybeObject* maybe_array =
5852 heap->AllocateFixedArray(ToKeyIndex(number_of_descriptors)); 5711 heap->AllocateFixedArray(ToKeyIndex(number_of_descriptors));
5853 if (!maybe_array->ToObject(&array)) return maybe_array; 5712 if (!maybe_array->ToObject(&array)) return maybe_array;
5854 } 5713 }
5855 // Do not use DescriptorArray::cast on incomplete object. 5714 // Do not use DescriptorArray::cast on incomplete object.
5856 FixedArray* result = FixedArray::cast(array); 5715 FixedArray* result = FixedArray::cast(array);
5857 5716
5858 result->set(kBitField3StorageIndex, Smi::FromInt(0)); 5717 result->set(kBitField3StorageIndex, Smi::FromInt(0));
5718 result->set(kTransitionsIndex, Smi::FromInt(0));
5859 result->set(kEnumerationIndexIndex, 5719 result->set(kEnumerationIndexIndex,
5860 Smi::FromInt(PropertyDetails::kInitialIndex)); 5720 Smi::FromInt(PropertyDetails::kInitialIndex));
5861 return result; 5721 return result;
5862 } 5722 }
5863 5723
5864 5724
5865 void DescriptorArray::SetEnumCache(FixedArray* bridge_storage, 5725 void DescriptorArray::SetEnumCache(FixedArray* bridge_storage,
5866 FixedArray* new_cache, 5726 FixedArray* new_cache,
5867 Object* new_index_cache) { 5727 Object* new_index_cache) {
5868 ASSERT(bridge_storage->length() >= kEnumCacheBridgeLength); 5728 ASSERT(bridge_storage->length() >= kEnumCacheBridgeLength);
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
5952 // We are replacing an existing descriptor. We keep the enumeration index 5812 // We are replacing an existing descriptor. We keep the enumeration index
5953 // of a visible property. 5813 // of a visible property.
5954 keep_enumeration_index = true; 5814 keep_enumeration_index = true;
5955 } else if (remove_transitions) { 5815 } else if (remove_transitions) {
5956 // Replaced descriptor has been counted as removed if it is a transition 5816 // Replaced descriptor has been counted as removed if it is a transition
5957 // that will be replaced. Adjust count in this case. 5817 // that will be replaced. Adjust count in this case.
5958 ++new_size; 5818 ++new_size;
5959 } 5819 }
5960 5820
5961 DescriptorArray* new_descriptors; 5821 DescriptorArray* new_descriptors;
5962 { MaybeObject* maybe_result = Allocate(new_size); 5822 { MaybeObject* maybe_result = Allocate(new_size, !remove_transitions);
5963 if (!maybe_result->To(&new_descriptors)) return maybe_result; 5823 if (!maybe_result->To(&new_descriptors)) return maybe_result;
5964 } 5824 }
5965 5825
5966 DescriptorArray::WhitenessWitness witness(new_descriptors); 5826 DescriptorArray::WhitenessWitness witness(new_descriptors);
5967 5827
5968 // Set the enumeration index in the descriptors and set the enumeration index 5828 // Set the enumeration index in the descriptors and set the enumeration index
5969 // in the result. 5829 // in the result.
5970 int enumeration_index = NextEnumerationIndex(); 5830 int enumeration_index = NextEnumerationIndex();
5971 if (!descriptor->ContainsTransition()) { 5831 if (!descriptor->ContainsTransition()) {
5972 if (keep_enumeration_index) { 5832 if (keep_enumeration_index) {
5973 descriptor->SetEnumerationIndex(GetDetails(index).index()); 5833 descriptor->SetEnumerationIndex(GetDetails(index).index());
5974 } else { 5834 } else {
5975 descriptor->SetEnumerationIndex(enumeration_index); 5835 descriptor->SetEnumerationIndex(enumeration_index);
5976 ++enumeration_index; 5836 ++enumeration_index;
5977 } 5837 }
5978 } 5838 }
5839 Map* old_elements_transition = elements_transition();
5840 if ((!remove_transitions) && (old_elements_transition != NULL)) {
5841 new_descriptors->set_elements_transition(old_elements_transition);
5842 }
5979 new_descriptors->SetNextEnumerationIndex(enumeration_index); 5843 new_descriptors->SetNextEnumerationIndex(enumeration_index);
5980 5844
5981 // Copy the descriptors, filtering out transitions and null descriptors, 5845 // Copy the descriptors, filtering out transitions and null descriptors,
5982 // and inserting or replacing a descriptor. 5846 // and inserting or replacing a descriptor.
5983 int to_index = 0; 5847 int to_index = 0;
5984 int insertion_index = -1; 5848 int insertion_index = -1;
5985 int from_index = 0; 5849 int from_index = 0;
5986 while (from_index < number_of_descriptors()) { 5850 while (from_index < number_of_descriptors()) {
5987 if (insertion_index < 0 && 5851 if (insertion_index < 0 &&
5988 InsertionPointFound(GetKey(from_index), descriptor->GetKey())) { 5852 InsertionPointFound(GetKey(from_index), descriptor->GetKey())) {
5989 insertion_index = to_index++; 5853 insertion_index = to_index++;
5990 if (replacing) from_index++; 5854 if (replacing) from_index++;
5991 } else { 5855 } else {
5992 if (!(IsNullDescriptor(from_index) || 5856 if (!(IsNullDescriptor(from_index) ||
5993 (remove_transitions && IsTransitionOnly(from_index)))) { 5857 (remove_transitions && IsTransitionOnly(from_index)))) {
5994 MaybeObject* copy_result = 5858 MaybeObject* copy_result =
5995 new_descriptors->CopyFrom(to_index++, this, from_index, witness); 5859 new_descriptors->CopyFrom(to_index++, this, from_index, witness);
5996 if (copy_result->IsFailure()) return copy_result; 5860 if (copy_result->IsFailure()) return copy_result;
5997 } 5861 }
5998 from_index++; 5862 from_index++;
5999 } 5863 }
6000 } 5864 }
6001 if (insertion_index < 0) insertion_index = to_index++; 5865 if (insertion_index < 0) insertion_index = to_index++;
5866
5867 ASSERT(insertion_index < new_descriptors->number_of_descriptors());
6002 new_descriptors->Set(insertion_index, descriptor, witness); 5868 new_descriptors->Set(insertion_index, descriptor, witness);
6003 5869
6004 ASSERT(to_index == new_descriptors->number_of_descriptors()); 5870 ASSERT(to_index == new_descriptors->number_of_descriptors());
6005 SLOW_ASSERT(new_descriptors->IsSortedNoDuplicates()); 5871 SLOW_ASSERT(new_descriptors->IsSortedNoDuplicates());
6006 5872
6007 return new_descriptors; 5873 return new_descriptors;
6008 } 5874 }
6009 5875
6010 5876
6011 MaybeObject* DescriptorArray::RemoveTransitions() { 5877 MaybeObject* DescriptorArray::RemoveTransitions(bool mutable_transitions) {
6012 // Allocate the new descriptor array. 5878 // Allocate the new descriptor array.
6013 int new_number_of_descriptors = 0; 5879 int new_number_of_descriptors = 0;
6014 for (int i = 0; i < number_of_descriptors(); i++) { 5880 for (int i = 0; i < number_of_descriptors(); i++) {
6015 if (IsProperty(i)) new_number_of_descriptors++; 5881 if (IsProperty(i)) new_number_of_descriptors++;
6016 } 5882 }
6017 DescriptorArray* new_descriptors; 5883 DescriptorArray* new_descriptors;
6018 { MaybeObject* maybe_result = Allocate(new_number_of_descriptors); 5884 { MaybeObject* maybe_result = Allocate(new_number_of_descriptors,
5885 mutable_transitions);
6019 if (!maybe_result->To(&new_descriptors)) return maybe_result; 5886 if (!maybe_result->To(&new_descriptors)) return maybe_result;
6020 } 5887 }
6021 5888
6022 // Copy the content. 5889 // Copy the content.
6023 DescriptorArray::WhitenessWitness witness(new_descriptors); 5890 DescriptorArray::WhitenessWitness witness(new_descriptors);
6024 int next_descriptor = 0; 5891 int next_descriptor = 0;
6025 for (int i = 0; i < number_of_descriptors(); i++) { 5892 for (int i = 0; i < number_of_descriptors(); i++) {
6026 if (IsProperty(i)) { 5893 if (IsProperty(i)) {
6027 MaybeObject* copy_result = 5894 MaybeObject* copy_result =
6028 new_descriptors->CopyFrom(next_descriptor++, this, i, witness); 5895 new_descriptors->CopyFrom(next_descriptor++, this, i, witness);
6029 if (copy_result->IsFailure()) return copy_result; 5896 if (copy_result->IsFailure()) return copy_result;
6030 } 5897 }
6031 } 5898 }
6032 ASSERT(next_descriptor == new_descriptors->number_of_descriptors()); 5899 ASSERT(next_descriptor == new_descriptors->number_of_descriptors());
6033 5900
6034 return new_descriptors; 5901 return new_descriptors;
6035 } 5902 }
6036 5903
5904
6037 // The whiteness witness is needed since sort will reshuffle the entries in the 5905 // The whiteness witness is needed since sort will reshuffle the entries in the
6038 // descriptor array. If the descriptor array were to be were to be black, the 5906 // descriptor array. If the descriptor array were to be were to be black, the
6039 // shuffling would move a slot that was already recorded as pointing into an 5907 // shuffling would move a slot that was already recorded as pointing into an
6040 // evacuation candidate. This would result in missing updates upon evacuation. 5908 // evacuation candidate. This would result in missing updates upon evacuation.
6041 void DescriptorArray::SortUnchecked(const WhitenessWitness& witness) { 5909 void DescriptorArray::SortUnchecked(const WhitenessWitness& witness) {
6042 // In-place heap sort. 5910 // In-place heap sort.
6043 int len = number_of_descriptors(); 5911 int len = number_of_descriptors();
6044 5912
6045 // Bottom-up max-heap construction. 5913 // Bottom-up max-heap construction.
6046 // Index of the last node with children 5914 // Index of the last node with children
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
6092 5960
6093 5961
6094 void DescriptorArray::Sort(const WhitenessWitness& witness) { 5962 void DescriptorArray::Sort(const WhitenessWitness& witness) {
6095 SortUnchecked(witness); 5963 SortUnchecked(witness);
6096 SLOW_ASSERT(IsSortedNoDuplicates()); 5964 SLOW_ASSERT(IsSortedNoDuplicates());
6097 } 5965 }
6098 5966
6099 5967
6100 int DescriptorArray::BinarySearch(String* name, int low, int high) { 5968 int DescriptorArray::BinarySearch(String* name, int low, int high) {
6101 uint32_t hash = name->Hash(); 5969 uint32_t hash = name->Hash();
5970 int limit = high;
6102 5971
6103 while (low <= high) { 5972 ASSERT(low <= high);
5973
5974 while (low != high) {
6104 int mid = (low + high) / 2; 5975 int mid = (low + high) / 2;
6105 String* mid_name = GetKey(mid); 5976 String* mid_name = GetKey(mid);
6106 uint32_t mid_hash = mid_name->Hash(); 5977 uint32_t mid_hash = mid_name->Hash();
6107 5978
6108 if (mid_hash > hash) { 5979 if (mid_hash >= hash) {
6109 high = mid - 1; 5980 high = mid;
6110 continue; 5981 } else {
5982 low = mid + 1;
6111 } 5983 }
6112 if (mid_hash < hash) {
6113 low = mid + 1;
6114 continue;
6115 }
6116 // Found an element with the same hash-code.
6117 ASSERT(hash == mid_hash);
6118 // There might be more, so we find the first one and
6119 // check them all to see if we have a match.
6120 if (name == mid_name && !IsNullDescriptor(mid)) return mid;
6121 while ((mid > low) && (GetKey(mid - 1)->Hash() == hash)) mid--;
6122 for (; (mid <= high) && (GetKey(mid)->Hash() == hash); mid++) {
6123 if (GetKey(mid)->Equals(name) && !IsNullDescriptor(mid)) return mid;
6124 }
6125 break;
6126 } 5984 }
5985
5986 for (; low <= limit && GetKey(low)->Hash() == hash; ++low) {
5987 if (GetKey(low)->Equals(name) && !IsNullDescriptor(low))
5988 return low;
5989 }
5990
6127 return kNotFound; 5991 return kNotFound;
6128 } 5992 }
6129 5993
6130 5994
6131 int DescriptorArray::LinearSearch(String* name, int len) { 5995 int DescriptorArray::LinearSearch(String* name, int len) {
6132 uint32_t hash = name->Hash(); 5996 uint32_t hash = name->Hash();
6133 for (int number = 0; number < len; number++) { 5997 for (int number = 0; number < len; number++) {
6134 String* entry = GetKey(number); 5998 String* entry = GetKey(number);
6135 if ((entry->Hash() == hash) && 5999 if (entry->Hash() > hash) break;
6136 name->Equals(entry) && 6000 if (name->Equals(entry) && !IsNullDescriptor(number)) {
6137 !IsNullDescriptor(number)) {
6138 return number; 6001 return number;
6139 } 6002 }
6140 } 6003 }
6141 return kNotFound; 6004 return kNotFound;
6142 } 6005 }
6143 6006
6144 6007
6145 MaybeObject* AccessorPair::CopyWithoutTransitions() { 6008 MaybeObject* AccessorPair::CopyWithoutTransitions() {
6146 Heap* heap = GetHeap(); 6009 Heap* heap = GetHeap();
6147 AccessorPair* copy; 6010 AccessorPair* copy;
(...skipping 1263 matching lines...) Expand 10 before | Expand all | Expand 10 after
7411 // live. If not, null the descriptor. Also drop the back pointer for that 7274 // live. If not, null the descriptor. Also drop the back pointer for that
7412 // map transition, so that this map is not reached again by following a back 7275 // map transition, so that this map is not reached again by following a back
7413 // pointer from that non-live map. 7276 // pointer from that non-live map.
7414 bool keep_entry = false; 7277 bool keep_entry = false;
7415 PropertyDetails details(d->GetDetails(i)); 7278 PropertyDetails details(d->GetDetails(i));
7416 switch (details.type()) { 7279 switch (details.type()) {
7417 case MAP_TRANSITION: 7280 case MAP_TRANSITION:
7418 case CONSTANT_TRANSITION: 7281 case CONSTANT_TRANSITION:
7419 ClearBackPointer(heap, d->GetValue(i), &keep_entry); 7282 ClearBackPointer(heap, d->GetValue(i), &keep_entry);
7420 break; 7283 break;
7421 case ELEMENTS_TRANSITION: {
7422 Object* object = d->GetValue(i);
7423 if (object->IsMap()) {
7424 ClearBackPointer(heap, object, &keep_entry);
7425 } else {
7426 FixedArray* array = FixedArray::cast(object);
7427 for (int j = 0; j < array->length(); ++j) {
7428 if (ClearBackPointer(heap, array->get(j), &keep_entry)) {
7429 array->set_undefined(j);
7430 }
7431 }
7432 }
7433 break;
7434 }
7435 case CALLBACKS: { 7284 case CALLBACKS: {
7436 Object* object = d->GetValue(i); 7285 Object* object = d->GetValue(i);
7437 if (object->IsAccessorPair()) { 7286 if (object->IsAccessorPair()) {
7438 AccessorPair* accessors = AccessorPair::cast(object); 7287 AccessorPair* accessors = AccessorPair::cast(object);
7439 if (ClearBackPointer(heap, accessors->getter(), &keep_entry)) { 7288 if (ClearBackPointer(heap, accessors->getter(), &keep_entry)) {
7440 accessors->set_getter(heap->the_hole_value()); 7289 accessors->set_getter(heap->the_hole_value());
7441 } 7290 }
7442 if (ClearBackPointer(heap, accessors->setter(), &keep_entry)) { 7291 if (ClearBackPointer(heap, accessors->setter(), &keep_entry)) {
7443 accessors->set_setter(heap->the_hole_value()); 7292 accessors->set_setter(heap->the_hole_value());
7444 } 7293 }
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after
7584 } 7433 }
7585 7434
7586 7435
7587 MaybeObject* JSFunction::SetInstancePrototype(Object* value) { 7436 MaybeObject* JSFunction::SetInstancePrototype(Object* value) {
7588 ASSERT(value->IsJSReceiver()); 7437 ASSERT(value->IsJSReceiver());
7589 Heap* heap = GetHeap(); 7438 Heap* heap = GetHeap();
7590 if (has_initial_map()) { 7439 if (has_initial_map()) {
7591 // If the function has allocated the initial map 7440 // If the function has allocated the initial map
7592 // replace it with a copy containing the new prototype. 7441 // replace it with a copy containing the new prototype.
7593 Map* new_map; 7442 Map* new_map;
7594 MaybeObject* maybe_new_map = initial_map()->CopyDropTransitions(); 7443 MaybeObject* maybe_new_map = initial_map()->CopyDropTransitions(false);
7595 if (!maybe_new_map->To(&new_map)) return maybe_new_map; 7444 if (!maybe_new_map->To(&new_map)) return maybe_new_map;
7596 new_map->set_prototype(value); 7445 new_map->set_prototype(value);
7597 MaybeObject* maybe_object = 7446 MaybeObject* maybe_object =
7598 set_initial_map_and_cache_transitions(new_map); 7447 set_initial_map_and_cache_transitions(new_map);
7599 if (maybe_object->IsFailure()) return maybe_object; 7448 if (maybe_object->IsFailure()) return maybe_object;
7600 } else { 7449 } else {
7601 // Put the value in the initial map field until an initial map is 7450 // Put the value in the initial map field until an initial map is
7602 // needed. At that point, a new initial map is created and the 7451 // needed. At that point, a new initial map is created and the
7603 // prototype is put into the initial map where it belongs. 7452 // prototype is put into the initial map where it belongs.
7604 set_prototype_or_initial_map(value); 7453 set_prototype_or_initial_map(value);
7605 } 7454 }
7606 heap->ClearInstanceofCache(); 7455 heap->ClearInstanceofCache();
7607 return value; 7456 return value;
7608 } 7457 }
7609 7458
7610 7459
7611 MaybeObject* JSFunction::SetPrototype(Object* value) { 7460 MaybeObject* JSFunction::SetPrototype(Object* value) {
7612 ASSERT(should_have_prototype()); 7461 ASSERT(should_have_prototype());
7613 Object* construct_prototype = value; 7462 Object* construct_prototype = value;
7614 7463
7615 // If the value is not a JSReceiver, store the value in the map's 7464 // If the value is not a JSReceiver, store the value in the map's
7616 // constructor field so it can be accessed. Also, set the prototype 7465 // constructor field so it can be accessed. Also, set the prototype
7617 // used for constructing objects to the original object prototype. 7466 // used for constructing objects to the original object prototype.
7618 // See ECMA-262 13.2.2. 7467 // See ECMA-262 13.2.2.
7619 if (!value->IsJSReceiver()) { 7468 if (!value->IsJSReceiver()) {
7620 // Copy the map so this does not affect unrelated functions. 7469 // Copy the map so this does not affect unrelated functions.
7621 // Remove map transitions because they point to maps with a 7470 // Remove map transitions because they point to maps with a
7622 // different prototype. 7471 // different prototype.
7623 Map* new_map; 7472 Map* new_map;
7624 { MaybeObject* maybe_new_map = map()->CopyDropTransitions(); 7473 { MaybeObject* maybe_new_map = map()->CopyDropTransitions(false);
7625 if (!maybe_new_map->To(&new_map)) return maybe_new_map; 7474 if (!maybe_new_map->To(&new_map)) return maybe_new_map;
7626 } 7475 }
7627 Heap* heap = new_map->GetHeap(); 7476 Heap* heap = new_map->GetHeap();
7628 set_map(new_map); 7477 set_map(new_map);
7629 new_map->set_constructor(value); 7478 new_map->set_constructor(value);
7630 new_map->set_non_instance_prototype(true); 7479 new_map->set_non_instance_prototype(true);
7631 construct_prototype = 7480 construct_prototype =
7632 heap->isolate()->context()->global_context()-> 7481 heap->isolate()->context()->global_context()->
7633 initial_object_prototype(); 7482 initial_object_prototype();
7634 } else { 7483 } else {
(...skipping 846 matching lines...) Expand 10 before | Expand all | Expand 10 after
8481 8330
8482 const char* Code::PropertyType2String(PropertyType type) { 8331 const char* Code::PropertyType2String(PropertyType type) {
8483 switch (type) { 8332 switch (type) {
8484 case NORMAL: return "NORMAL"; 8333 case NORMAL: return "NORMAL";
8485 case FIELD: return "FIELD"; 8334 case FIELD: return "FIELD";
8486 case CONSTANT_FUNCTION: return "CONSTANT_FUNCTION"; 8335 case CONSTANT_FUNCTION: return "CONSTANT_FUNCTION";
8487 case CALLBACKS: return "CALLBACKS"; 8336 case CALLBACKS: return "CALLBACKS";
8488 case HANDLER: return "HANDLER"; 8337 case HANDLER: return "HANDLER";
8489 case INTERCEPTOR: return "INTERCEPTOR"; 8338 case INTERCEPTOR: return "INTERCEPTOR";
8490 case MAP_TRANSITION: return "MAP_TRANSITION"; 8339 case MAP_TRANSITION: return "MAP_TRANSITION";
8491 case ELEMENTS_TRANSITION: return "ELEMENTS_TRANSITION";
8492 case CONSTANT_TRANSITION: return "CONSTANT_TRANSITION"; 8340 case CONSTANT_TRANSITION: return "CONSTANT_TRANSITION";
8493 case NULL_DESCRIPTOR: return "NULL_DESCRIPTOR"; 8341 case NULL_DESCRIPTOR: return "NULL_DESCRIPTOR";
8494 } 8342 }
8495 UNREACHABLE(); // keep the compiler happy 8343 UNREACHABLE(); // keep the compiler happy
8496 return NULL; 8344 return NULL;
8497 } 8345 }
8498 8346
8499 8347
8500 void Code::PrintExtraICState(FILE* out, Kind kind, ExtraICState extra) { 8348 void Code::PrintExtraICState(FILE* out, Kind kind, ExtraICState extra) {
8501 const char* name = NULL; 8349 const char* name = NULL;
(...skipping 370 matching lines...) Expand 10 before | Expand all | Expand 10 after
8872 } 8720 }
8873 8721
8874 // Set the new prototype of the object. 8722 // Set the new prototype of the object.
8875 Map* map = real_receiver->map(); 8723 Map* map = real_receiver->map();
8876 8724
8877 // Nothing to do if prototype is already set. 8725 // Nothing to do if prototype is already set.
8878 if (map->prototype() == value) return value; 8726 if (map->prototype() == value) return value;
8879 8727
8880 Object* new_map = map->GetPrototypeTransition(value); 8728 Object* new_map = map->GetPrototypeTransition(value);
8881 if (new_map == NULL) { 8729 if (new_map == NULL) {
8882 { MaybeObject* maybe_new_map = map->CopyDropTransitions(); 8730 { MaybeObject* maybe_new_map = map->CopyDropTransitions(false);
8883 if (!maybe_new_map->ToObject(&new_map)) return maybe_new_map; 8731 if (!maybe_new_map->ToObject(&new_map)) return maybe_new_map;
8884 } 8732 }
8885 8733
8886 { MaybeObject* maybe_new_cache = 8734 { MaybeObject* maybe_new_cache =
8887 map->PutPrototypeTransition(value, Map::cast(new_map)); 8735 map->PutPrototypeTransition(value, Map::cast(new_map));
8888 if (maybe_new_cache->IsFailure()) return maybe_new_cache; 8736 if (maybe_new_cache->IsFailure()) return maybe_new_cache;
8889 } 8737 }
8890 8738
8891 Map::cast(new_map)->set_prototype(value); 8739 Map::cast(new_map)->set_prototype(value);
8892 } 8740 }
(...skipping 2260 matching lines...) Expand 10 before | Expand all | Expand 10 after
11153 entry = NextProbe(entry, count++, capacity); 11001 entry = NextProbe(entry, count++, capacity);
11154 } 11002 }
11155 return kNotFound; 11003 return kNotFound;
11156 } 11004 }
11157 11005
11158 11006
11159 bool StringDictionary::ContainsTransition(int entry) { 11007 bool StringDictionary::ContainsTransition(int entry) {
11160 switch (DetailsAt(entry).type()) { 11008 switch (DetailsAt(entry).type()) {
11161 case MAP_TRANSITION: 11009 case MAP_TRANSITION:
11162 case CONSTANT_TRANSITION: 11010 case CONSTANT_TRANSITION:
11163 case ELEMENTS_TRANSITION:
11164 return true; 11011 return true;
11165 case CALLBACKS: { 11012 case CALLBACKS: {
11166 Object* value = ValueAt(entry); 11013 Object* value = ValueAt(entry);
11167 if (!value->IsAccessorPair()) return false; 11014 if (!value->IsAccessorPair()) return false;
11168 AccessorPair* accessors = AccessorPair::cast(value); 11015 AccessorPair* accessors = AccessorPair::cast(value);
11169 return accessors->getter()->IsMap() || accessors->setter()->IsMap(); 11016 return accessors->getter()->IsMap() || accessors->setter()->IsMap();
11170 } 11017 }
11171 case NORMAL: 11018 case NORMAL:
11172 case FIELD: 11019 case FIELD:
11173 case CONSTANT_FUNCTION: 11020 case CONSTANT_FUNCTION:
(...skipping 1429 matching lines...) Expand 10 before | Expand all | Expand 10 after
12603 if (type == NORMAL && 12450 if (type == NORMAL &&
12604 (!value->IsJSFunction() || heap->InNewSpace(value))) { 12451 (!value->IsJSFunction() || heap->InNewSpace(value))) {
12605 number_of_fields += 1; 12452 number_of_fields += 1;
12606 } 12453 }
12607 } 12454 }
12608 } 12455 }
12609 12456
12610 // Allocate the instance descriptor. 12457 // Allocate the instance descriptor.
12611 DescriptorArray* descriptors; 12458 DescriptorArray* descriptors;
12612 { MaybeObject* maybe_descriptors = 12459 { MaybeObject* maybe_descriptors =
12613 DescriptorArray::Allocate(instance_descriptor_length); 12460 DescriptorArray::Allocate(instance_descriptor_length, false);
12614 if (!maybe_descriptors->To<DescriptorArray>(&descriptors)) { 12461 if (!maybe_descriptors->To<DescriptorArray>(&descriptors)) {
12615 return maybe_descriptors; 12462 return maybe_descriptors;
12616 } 12463 }
12617 } 12464 }
12618 12465
12619 DescriptorArray::WhitenessWitness witness(descriptors); 12466 DescriptorArray::WhitenessWitness witness(descriptors);
12620 12467
12621 int inobject_props = obj->map()->inobject_properties(); 12468 int inobject_props = obj->map()->inobject_properties();
12622 int number_of_allocated_fields = 12469 int number_of_allocated_fields =
12623 number_of_fields + unused_property_fields - inobject_props; 12470 number_of_fields + unused_property_fields - inobject_props;
(...skipping 583 matching lines...) Expand 10 before | Expand all | Expand 10 after
13207 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER); 13054 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER);
13208 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER); 13055 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER);
13209 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER); 13056 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER);
13210 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER); 13057 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER);
13211 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER); 13058 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER);
13212 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER); 13059 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER);
13213 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER); 13060 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER);
13214 } 13061 }
13215 13062
13216 } } // namespace v8::internal 13063 } } // namespace v8::internal
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698