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

Side by Side Diff: src/objects.cc

Issue 35413006: Correct handling of arrays with callbacks in the prototype chain. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Test fixes Created 7 years, 1 month 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 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 2930 matching lines...) Expand 10 before | Expand all | Expand 10 after
2941 bool has_pending_exception; 2941 bool has_pending_exception;
2942 Handle<Object> argv[] = { value }; 2942 Handle<Object> argv[] = { value };
2943 Execution::Call( 2943 Execution::Call(
2944 isolate, setter, object, ARRAY_SIZE(argv), argv, &has_pending_exception); 2944 isolate, setter, object, ARRAY_SIZE(argv), argv, &has_pending_exception);
2945 // Check for pending exception and return the result. 2945 // Check for pending exception and return the result.
2946 if (has_pending_exception) return Handle<Object>(); 2946 if (has_pending_exception) return Handle<Object>();
2947 return value; 2947 return value;
2948 } 2948 }
2949 2949
2950 2950
2951 bool Map::MayHaveIndexedCallbacksInPrototypeChain() {
2952 Heap* heap = GetHeap();
2953
2954 if (has_element_callbacks()) {
2955 return true;
2956 }
2957
2958 for (Object* pt = prototype();
danno 2013/10/30 12:17:45 don't use the abbreviation, use the variable name
mvstanton 2013/10/30 18:22:28 Done.
2959 pt != heap->null_value();
2960 pt = pt->GetPrototype(GetIsolate())) {
2961 if (pt->IsJSProxy()) {
2962 // Be conservative, don't walk into proxies.
2963 return true;
2964 }
2965
2966 if (JSObject::cast(pt)->map()->has_element_callbacks()) {
2967 return true;
2968 }
2969 }
2970
2971 return false;
2972 }
2973
2974
2951 MaybeObject* JSObject::SetElementWithCallbackSetterInPrototypes( 2975 MaybeObject* JSObject::SetElementWithCallbackSetterInPrototypes(
2952 uint32_t index, 2976 uint32_t index,
2953 Object* value, 2977 Object* value,
2954 bool* found, 2978 bool* found,
2955 StrictModeFlag strict_mode) { 2979 StrictModeFlag strict_mode) {
2956 Heap* heap = GetHeap(); 2980 Heap* heap = GetHeap();
2957 for (Object* pt = GetPrototype(); 2981 for (Object* pt = GetPrototype();
2958 pt != heap->null_value(); 2982 pt != heap->null_value();
2959 pt = pt->GetPrototype(GetIsolate())) { 2983 pt = pt->GetPrototype(GetIsolate())) {
2960 if (pt->IsJSProxy()) { 2984 if (pt->IsJSProxy()) {
(...skipping 1510 matching lines...) Expand 10 before | Expand all | Expand 10 after
4471 4495
4472 4496
4473 Handle<Map> NormalizedMapCache::Get(Handle<NormalizedMapCache> cache, 4497 Handle<Map> NormalizedMapCache::Get(Handle<NormalizedMapCache> cache,
4474 Handle<JSObject> obj, 4498 Handle<JSObject> obj,
4475 PropertyNormalizationMode mode) { 4499 PropertyNormalizationMode mode) {
4476 int index = obj->map()->Hash() % kEntries; 4500 int index = obj->map()->Hash() % kEntries;
4477 Handle<Object> result = handle(cache->get(index), cache->GetIsolate()); 4501 Handle<Object> result = handle(cache->get(index), cache->GetIsolate());
4478 if (result->IsMap() && 4502 if (result->IsMap() &&
4479 Handle<Map>::cast(result)->EquivalentToForNormalization(obj->map(), 4503 Handle<Map>::cast(result)->EquivalentToForNormalization(obj->map(),
4480 mode)) { 4504 mode)) {
4505 Handle<Map> result_map = Handle<Map>::cast(result);
4481 #ifdef VERIFY_HEAP 4506 #ifdef VERIFY_HEAP
4482 if (FLAG_verify_heap) { 4507 if (FLAG_verify_heap) {
4483 Handle<Map>::cast(result)->SharedMapVerify(); 4508 result_map->SharedMapVerify();
4484 } 4509 }
4485 #endif 4510 #endif
4486 #ifdef ENABLE_SLOW_ASSERTS 4511 #ifdef ENABLE_SLOW_ASSERTS
4487 if (FLAG_enable_slow_asserts) { 4512 if (FLAG_enable_slow_asserts) {
4488 // The cached map should match newly created normalized map bit-by-bit, 4513 // The cached map should match newly created normalized map bit-by-bit,
4489 // except for the code cache, which can contain some ics which can be 4514 // except for the code cache, which can contain some ics which can be
4490 // applied to the shared map. 4515 // applied to the shared map.
4491 Handle<Map> fresh = Map::CopyNormalized(handle(obj->map()), mode, 4516 Handle<Map> fresh = Map::CopyNormalized(handle(obj->map()), mode,
4492 SHARED_NORMALIZED_MAP); 4517 SHARED_NORMALIZED_MAP);
4493 4518
4494 ASSERT(memcmp(fresh->address(), 4519 ASSERT(memcmp(fresh->address(),
4495 Handle<Map>::cast(result)->address(), 4520 result_map->address(),
4496 Map::kCodeCacheOffset) == 0); 4521 Map::kTransitionsOrBackPointerOffset) == 0);
4497 STATIC_ASSERT(Map::kDependentCodeOffset == 4522 STATIC_ASSERT(Map::kDependentCodeOffset ==
4498 Map::kCodeCacheOffset + kPointerSize); 4523 Map::kTransitionsOrBackPointerOffset + 3 * kPointerSize);
4499 int offset = Map::kDependentCodeOffset + kPointerSize; 4524
4500 ASSERT(memcmp(fresh->address() + offset, 4525 // The final fields to look at are flag fields 3 and 4. Field 3
danno 2013/10/30 12:17:45 Is the logic needed? I thought the conclusion was
4501 Handle<Map>::cast(result)->address() + offset, 4526 // needs special attention.
4502 Map::kSize - offset) == 0); 4527 STATIC_ASSERT(Map::kDependentCodeOffset + kPointerSize ==
4528 Map::kBitField3Offset);
4529 STATIC_ASSERT(Map::kSize - (2 * kPointerSize) == Map::kBitField3Offset);
4530 STATIC_ASSERT(Map::kSize - kPointerSize == Map::kBitField4Offset);
4531
4532 int mask = Map::EnumLengthBits::kMask |
4533 Map::NumberOfOwnDescriptorsBits::kMask |
4534 Map::IsShared::kMask |
4535 Map::FunctionWithPrototype::kMask |
4536 Map::DictionaryMap::kMask |
4537 // OwnsDescriptors::kMask |
4538 Map::IsObserved::kMask |
4539 Map::Deprecated::kMask |
4540 Map::IsFrozen::kMask |
4541 Map::IsUnstable::kMask |
4542 Map::IsMigrationTarget::kMask;
4543 int fresh_field3 = fresh->bit_field3() & mask;
4544 int result_field3 = result_map->bit_field3() & mask;
4545 ASSERT(fresh_field3 == result_field3);
4546 ASSERT(fresh->bit_field4() == result_map->bit_field4());
4503 } 4547 }
4504 #endif 4548 #endif
4505 return Handle<Map>::cast(result); 4549 return result_map;
4506 } 4550 }
4507 4551
4508 Isolate* isolate = cache->GetIsolate(); 4552 Isolate* isolate = cache->GetIsolate();
4509 Handle<Map> map = Map::CopyNormalized(handle(obj->map()), mode, 4553 Handle<Map> map = Map::CopyNormalized(handle(obj->map()), mode,
4510 SHARED_NORMALIZED_MAP); 4554 SHARED_NORMALIZED_MAP);
4511 ASSERT(map->is_dictionary_map()); 4555 ASSERT(map->is_dictionary_map());
4512 cache->set(index, *map); 4556 cache->set(index, *map);
4513 isolate->counters()->normalized_maps()->Increment(); 4557 isolate->counters()->normalized_maps()->Increment();
4514 4558
4515 return map; 4559 return map;
(...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after
4696 4740
4697 Handle<SeededNumberDictionary> JSObject::NormalizeElements( 4741 Handle<SeededNumberDictionary> JSObject::NormalizeElements(
4698 Handle<JSObject> object) { 4742 Handle<JSObject> object) {
4699 CALL_HEAP_FUNCTION(object->GetIsolate(), 4743 CALL_HEAP_FUNCTION(object->GetIsolate(),
4700 object->NormalizeElements(), 4744 object->NormalizeElements(),
4701 SeededNumberDictionary); 4745 SeededNumberDictionary);
4702 } 4746 }
4703 4747
4704 4748
4705 MaybeObject* JSObject::NormalizeElements() { 4749 MaybeObject* JSObject::NormalizeElements() {
4706 ASSERT(!HasExternalArrayElements()); 4750 SeededNumberDictionary* dictionary;
4707 4751 FixedArrayBase* array = GetElements();
danno 2013/10/30 12:17:45 I'd call this GetElementBackingStore(), and you mi
4708 // Find the backing store.
4709 FixedArrayBase* array = FixedArrayBase::cast(elements());
4710 Map* old_map = array->map();
4711 bool is_arguments =
4712 (old_map == old_map->GetHeap()->non_strict_arguments_elements_map());
4713 if (is_arguments) {
4714 array = FixedArrayBase::cast(FixedArray::cast(array)->get(1));
4715 }
4716 if (array->IsDictionary()) return array; 4752 if (array->IsDictionary()) return array;
4717 4753
4718 ASSERT(HasFastSmiOrObjectElements() || 4754 MaybeObject* maybe_dictionary = CreateNormalizedElements();
4719 HasFastDoubleElements() ||
4720 HasFastArgumentsElements());
4721 // Compute the effective length and allocate a new backing store.
4722 int length = IsJSArray()
4723 ? Smi::cast(JSArray::cast(this)->length())->value()
4724 : array->length();
4725 int old_capacity = 0;
4726 int used_elements = 0;
4727 GetElementsCapacityAndUsage(&old_capacity, &used_elements);
4728 SeededNumberDictionary* dictionary;
4729 MaybeObject* maybe_dictionary =
4730 SeededNumberDictionary::Allocate(GetHeap(), used_elements);
4731 if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary;
4732
4733 maybe_dictionary = CopyFastElementsToDictionary(
4734 GetIsolate(), array, length, dictionary);
4735 if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary; 4755 if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary;
4736 4756
4737 // Switch to using the dictionary as the backing storage for elements. 4757 // Switch to using the dictionary as the backing storage for elements.
4738 if (is_arguments) { 4758 if (HasNonStrictArgumentsElementsMap()) {
4739 FixedArray::cast(elements())->set(1, dictionary); 4759 FixedArray::cast(elements())->set(1, dictionary);
4740 } else { 4760 } else {
4741 // Set the new map first to satify the elements type assert in 4761 // Set the new map first to satify the elements type assert in
4742 // set_elements(). 4762 // set_elements().
4743 Map* new_map; 4763 Map* new_map;
4744 MaybeObject* maybe = GetElementsTransitionMap(GetIsolate(), 4764 MaybeObject* maybe = GetElementsTransitionMap(GetIsolate(),
4745 DICTIONARY_ELEMENTS); 4765 DICTIONARY_ELEMENTS);
4746 if (!maybe->To(&new_map)) return maybe; 4766 if (!maybe->To(&new_map)) return maybe;
4747 set_map(new_map); 4767 set_map(new_map);
4748 set_elements(dictionary); 4768 set_elements(dictionary);
4749 } 4769 }
4750 4770
4751 old_map->GetHeap()->isolate()->counters()->elements_to_dictionary()-> 4771 GetHeap()->isolate()->counters()->elements_to_dictionary()->Increment();
4752 Increment();
4753 4772
4754 #ifdef DEBUG 4773 #ifdef DEBUG
4755 if (FLAG_trace_normalization) { 4774 if (FLAG_trace_normalization) {
4756 PrintF("Object elements have been normalized:\n"); 4775 PrintF("Object elements have been normalized:\n");
4757 Print(); 4776 Print();
4758 } 4777 }
4759 #endif 4778 #endif
4760 4779
4761 ASSERT(HasDictionaryElements() || HasDictionaryArgumentsElements()); 4780 ASSERT(HasDictionaryElements() || HasDictionaryArgumentsElements());
4762 return dictionary; 4781 return dictionary;
4763 } 4782 }
4764 4783
4765 4784
4785 Handle<SeededNumberDictionary> JSObject::CreateNormalizedElements(
4786 Handle<JSObject> object) {
4787 CALL_HEAP_FUNCTION(object->GetIsolate(),
4788 object->CreateNormalizedElements(),
4789 SeededNumberDictionary);
4790 }
4791
4792
4793 MaybeObject* JSObject::CreateNormalizedElements() {
4794 ASSERT(!HasExternalArrayElements());
4795
4796 // Find the backing store.
4797 FixedArrayBase* array = GetElements();
4798 ASSERT(!array->IsDictionary());
4799
4800 ASSERT(HasFastSmiOrObjectElements() ||
4801 HasFastDoubleElements() ||
4802 HasFastArgumentsElements());
4803 // Compute the effective length and allocate a new backing store.
4804 int length = IsJSArray()
4805 ? Smi::cast(JSArray::cast(this)->length())->value()
4806 : array->length();
4807 int old_capacity = 0;
4808 int used_elements = 0;
4809 GetElementsCapacityAndUsage(&old_capacity, &used_elements);
4810 SeededNumberDictionary* dictionary;
4811 MaybeObject* maybe_dictionary =
4812 SeededNumberDictionary::Allocate(GetHeap(), used_elements);
4813 if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary;
4814
4815 maybe_dictionary = CopyFastElementsToDictionary(
4816 GetIsolate(), array, length, dictionary);
4817 if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary;
4818
4819 return dictionary;
4820 }
4821
4822
4766 Smi* JSReceiver::GenerateIdentityHash() { 4823 Smi* JSReceiver::GenerateIdentityHash() {
4767 Isolate* isolate = GetIsolate(); 4824 Isolate* isolate = GetIsolate();
4768 4825
4769 int hash_value; 4826 int hash_value;
4770 int attempts = 0; 4827 int attempts = 0;
4771 do { 4828 do {
4772 // Generate a random 32-bit hash value but limit range to fit 4829 // Generate a random 32-bit hash value but limit range to fit
4773 // within a smi. 4830 // within a smi.
4774 hash_value = isolate->random_number_generator()->NextInt() & Smi::kMaxValue; 4831 hash_value = isolate->random_number_generator()->NextInt() & Smi::kMaxValue;
4775 attempts++; 4832 attempts++;
(...skipping 782 matching lines...) Expand 10 before | Expand all | Expand 10 after
5558 } 5615 }
5559 } 5616 }
5560 5617
5561 LookupResult result(isolate); 5618 LookupResult result(isolate);
5562 Handle<Map> old_map(object->map()); 5619 Handle<Map> old_map(object->map());
5563 old_map->LookupTransition(*object, isolate->heap()->frozen_symbol(), &result); 5620 old_map->LookupTransition(*object, isolate->heap()->frozen_symbol(), &result);
5564 if (result.IsTransition()) { 5621 if (result.IsTransition()) {
5565 Map* transition_map = result.GetTransitionTarget(); 5622 Map* transition_map = result.GetTransitionTarget();
5566 ASSERT(transition_map->has_dictionary_elements()); 5623 ASSERT(transition_map->has_dictionary_elements());
5567 ASSERT(transition_map->is_frozen()); 5624 ASSERT(transition_map->is_frozen());
5568 ASSERT(!transition_map->is_extensible()); 5625 ASSERT(!transition_map->is_extensible());
danno 2013/10/30 12:17:45 nit: remove stray whitespace change.
mvstanton 2013/10/30 18:22:28 Done.
5569 object->set_map(transition_map); 5626 object->set_map(transition_map);
5570 } else if (object->HasFastProperties() && old_map->CanHaveMoreTransitions()) { 5627 } else if (object->HasFastProperties() && old_map->CanHaveMoreTransitions()) {
5571 // Create a new descriptor array with fully-frozen properties 5628 // Create a new descriptor array with fully-frozen properties
5572 int num_descriptors = old_map->NumberOfOwnDescriptors(); 5629 int num_descriptors = old_map->NumberOfOwnDescriptors();
5573 Handle<DescriptorArray> new_descriptors = 5630 Handle<DescriptorArray> new_descriptors =
5574 DescriptorArray::CopyUpToAddAttributes( 5631 DescriptorArray::CopyUpToAddAttributes(
5575 handle(old_map->instance_descriptors()), num_descriptors, FROZEN); 5632 handle(old_map->instance_descriptors()), num_descriptors, FROZEN);
5576 Handle<Map> new_map = Map::CopyReplaceDescriptors( 5633 Handle<Map> new_map = Map::CopyReplaceDescriptors(
5577 old_map, new_descriptors, INSERT_TRANSITION, 5634 old_map, new_descriptors, INSERT_TRANSITION,
5578 isolate->factory()->frozen_symbol()); 5635 isolate->factory()->frozen_symbol());
(...skipping 640 matching lines...) Expand 10 before | Expand all | Expand 10 after
6219 } 6276 }
6220 } 6277 }
6221 return true; 6278 return true;
6222 } 6279 }
6223 6280
6224 6281
6225 void JSObject::SetElementCallback(Handle<JSObject> object, 6282 void JSObject::SetElementCallback(Handle<JSObject> object,
6226 uint32_t index, 6283 uint32_t index,
6227 Handle<Object> structure, 6284 Handle<Object> structure,
6228 PropertyAttributes attributes) { 6285 PropertyAttributes attributes) {
6286 Isolate* isolate = object->GetIsolate();
6229 Heap* heap = object->GetHeap(); 6287 Heap* heap = object->GetHeap();
6230 PropertyDetails details = PropertyDetails(attributes, CALLBACKS, 0); 6288 PropertyDetails details = PropertyDetails(attributes, CALLBACKS, 0);
6289 bool is_arguments = object->HasNonStrictArgumentsElements();
6231 6290
6232 // Normalize elements to make this operation simple. 6291 // Do we need to create a new dictionary?
6233 Handle<SeededNumberDictionary> dictionary = NormalizeElements(object); 6292 Handle<SeededNumberDictionary> new_element_dictionary;
danno 2013/10/30 12:17:45 I think NormalizeElements will do the right thing
mvstanton 2013/10/30 18:22:28 Yep, I thought combining the move to dictionary an
6293 FixedArrayBase* array = object->GetElements();
6294 if (!array->IsDictionary()) {
6295 new_element_dictionary = CreateNormalizedElements(object);
6296 }
6297
6298 if (!object->map()->has_element_callbacks()) {
6299 LookupResult result(isolate);
6300 Handle<Map> old_map(object->map());
6301 old_map->LookupTransition(*object,
danno 2013/10/30 12:17:45 It looks like JSObject::SetObserve does almost exa
mvstanton 2013/10/30 18:22:28 addressed.
6302 heap->element_callbacks_symbol(),
6303 &result);
6304 if (result.IsTransition()) {
6305 object->set_map(result.GetTransitionTarget());
6306 } else {
6307 Handle<Map> new_map = Map::CopyAsElementCallbacksTransition(old_map,
6308 !is_arguments);
6309 object->set_map(*new_map);
6310 }
6311
6312 ASSERT(object->map()->has_element_callbacks());
6313
6314 // Install the dictionary if required without doing an extra transition.
6315 if (!new_element_dictionary.is_null()) {
6316 if (is_arguments) {
6317 FixedArray::cast(object->elements())->set(1, *new_element_dictionary);
6318 } else {
6319 object->set_elements(*new_element_dictionary);
6320 }
6321 }
6322
6323 // KeyedStoreICs (at least the non-generic ones) need a reset.
6324 // I *could* look at the maps and only reset the poly/mono ones that
danno 2013/10/30 12:17:45 nit: we try to avoid using "I" or "we" in comments
mvstanton 2013/10/30 18:22:28 :) done.
6325 // depend on a map in this prototype chain?
6326 heap->ClearAllICsByKind(Code::KEYED_STORE_IC);
6327 } else {
6328 // If our map is already flagged for element callbacks, then we should
6329 // not have had to create a new element dictionary.
6330 ASSERT(new_element_dictionary.is_null());
6331 }
6332
6333 Handle<SeededNumberDictionary> dictionary = Handle<SeededNumberDictionary>(
6334 SeededNumberDictionary::cast(object->GetElements()), isolate);
6335
6234 ASSERT(object->HasDictionaryElements() || 6336 ASSERT(object->HasDictionaryElements() ||
6235 object->HasDictionaryArgumentsElements()); 6337 object->HasDictionaryArgumentsElements());
6236 6338
6237 // Update the dictionary with the new CALLBACKS property. 6339 // Update the dictionary with the new CALLBACKS property.
6238 dictionary = SeededNumberDictionary::Set(dictionary, index, structure, 6340 dictionary = SeededNumberDictionary::Set(dictionary, index, structure,
6239 details); 6341 details);
6240 dictionary->set_requires_slow_elements(); 6342 dictionary->set_requires_slow_elements();
6241 6343
6242 // Update the dictionary backing store on the object. 6344 // Update the dictionary backing store on the object.
6243 if (object->elements()->map() == heap->non_strict_arguments_elements_map()) { 6345 if (is_arguments) {
6244 // Also delete any parameter alias. 6346 // Also delete any parameter alias.
6245 // 6347 //
6246 // TODO(kmillikin): when deleting the last parameter alias we could 6348 // TODO(kmillikin): when deleting the last parameter alias we could
6247 // switch to a direct backing store without the parameter map. This 6349 // switch to a direct backing store without the parameter map. This
6248 // would allow GC of the context. 6350 // would allow GC of the context.
6249 FixedArray* parameter_map = FixedArray::cast(object->elements()); 6351 FixedArray* parameter_map = FixedArray::cast(object->elements());
6250 if (index < static_cast<uint32_t>(parameter_map->length()) - 2) { 6352 if (index < static_cast<uint32_t>(parameter_map->length()) - 2) {
6251 parameter_map->set(index + 2, heap->the_hole_value()); 6353 parameter_map->set(index + 2, heap->the_hole_value());
6252 } 6354 }
6253 parameter_map->set(1, *dictionary); 6355 parameter_map->set(1, *dictionary);
(...skipping 411 matching lines...) Expand 10 before | Expand all | Expand 10 after
6665 result->set_constructor(constructor()); 6767 result->set_constructor(constructor());
6666 result->set_bit_field(bit_field()); 6768 result->set_bit_field(bit_field());
6667 result->set_bit_field2(bit_field2()); 6769 result->set_bit_field2(bit_field2());
6668 int new_bit_field3 = bit_field3(); 6770 int new_bit_field3 = bit_field3();
6669 new_bit_field3 = OwnsDescriptors::update(new_bit_field3, true); 6771 new_bit_field3 = OwnsDescriptors::update(new_bit_field3, true);
6670 new_bit_field3 = NumberOfOwnDescriptorsBits::update(new_bit_field3, 0); 6772 new_bit_field3 = NumberOfOwnDescriptorsBits::update(new_bit_field3, 0);
6671 new_bit_field3 = EnumLengthBits::update(new_bit_field3, kInvalidEnumCache); 6773 new_bit_field3 = EnumLengthBits::update(new_bit_field3, kInvalidEnumCache);
6672 new_bit_field3 = Deprecated::update(new_bit_field3, false); 6774 new_bit_field3 = Deprecated::update(new_bit_field3, false);
6673 new_bit_field3 = IsUnstable::update(new_bit_field3, false); 6775 new_bit_field3 = IsUnstable::update(new_bit_field3, false);
6674 result->set_bit_field3(new_bit_field3); 6776 result->set_bit_field3(new_bit_field3);
6777 result->set_bit_field4(bit_field4());
6675 return result; 6778 return result;
6676 } 6779 }
6677 6780
6678 6781
6679 Handle<Map> Map::CopyNormalized(Handle<Map> map, 6782 Handle<Map> Map::CopyNormalized(Handle<Map> map,
6680 PropertyNormalizationMode mode, 6783 PropertyNormalizationMode mode,
6681 NormalizedMapSharingMode sharing) { 6784 NormalizedMapSharingMode sharing) {
6682 int new_instance_size = map->instance_size(); 6785 int new_instance_size = map->instance_size();
6683 if (mode == CLEAR_INOBJECT_PROPERTIES) { 6786 if (mode == CLEAR_INOBJECT_PROPERTIES) {
6684 new_instance_size -= map->inobject_properties() * kPointerSize; 6787 new_instance_size -= map->inobject_properties() * kPointerSize;
(...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after
6916 if (insert_transition) { 7019 if (insert_transition) {
6917 MaybeObject* added_elements = set_elements_transition_map(new_map); 7020 MaybeObject* added_elements = set_elements_transition_map(new_map);
6918 if (added_elements->IsFailure()) return added_elements; 7021 if (added_elements->IsFailure()) return added_elements;
6919 new_map->SetBackPointer(this); 7022 new_map->SetBackPointer(this);
6920 } 7023 }
6921 7024
6922 return new_map; 7025 return new_map;
6923 } 7026 }
6924 7027
6925 7028
7029 MaybeObject* Map::CopyAsElementCallbacksTransition(
danno 2013/10/30 12:17:45 I think with a little work, you can 100% share thi
mvstanton 2013/10/30 18:22:28 I this this in a basic way, with a protected funct
7030 bool with_dictionary_elements) {
7031 ASSERT(!HasElementCallbacksTransition());
7032
7033 if (owns_descriptors()) {
7034 // In case the map owned its own descriptors, share the descriptors and
7035 // transfer ownership to the new map.
7036 Map* new_map;
7037 MaybeObject* maybe_new_map = CopyDropDescriptors();
7038 if (!maybe_new_map->To(&new_map)) return maybe_new_map;
7039
7040 MaybeObject* added_elements = set_element_callbacks_map(new_map);
7041 if (added_elements->IsFailure()) return added_elements;
7042
7043 new_map->InitializeDescriptors(instance_descriptors());
7044 new_map->set_has_element_callbacks(true);
7045 if (with_dictionary_elements) {
7046 new_map->set_elements_kind(DICTIONARY_ELEMENTS);
7047 }
7048 new_map->SetBackPointer(this);
7049 set_owns_descriptors(false);
7050 return new_map;
7051 }
7052
7053 // In case the map did not own its own descriptors, a split is forced by
7054 // copying the map; creating a new descriptor array cell.
7055 // Create a new free-floating map only if we are not allowed to store it.
7056 Map* new_map;
7057 MaybeObject* maybe_new_map = Copy();
7058 if (!maybe_new_map->To(&new_map)) return maybe_new_map;
7059 new_map->set_has_element_callbacks(true);
7060 if (with_dictionary_elements) {
7061 new_map->set_elements_kind(DICTIONARY_ELEMENTS);
7062 }
7063
7064 MaybeObject* added_elements = set_element_callbacks_map(new_map);
7065 if (added_elements->IsFailure()) return added_elements;
7066 new_map->SetBackPointer(this);
7067
7068 return new_map;
7069 }
7070
7071
7072 Handle<Map> Map::CopyAsElementCallbacksTransition(
7073 Handle<Map> map,
7074 bool with_dictionary_elements) {
7075 Isolate* isolate = map->GetIsolate();
7076 CALL_HEAP_FUNCTION(isolate,
7077 map->CopyAsElementCallbacksTransition(
7078 with_dictionary_elements),
7079 Map);
7080 }
7081
7082
6926 Handle<Map> Map::CopyForObserved(Handle<Map> map) { 7083 Handle<Map> Map::CopyForObserved(Handle<Map> map) {
6927 ASSERT(!map->is_observed()); 7084 ASSERT(!map->is_observed());
6928 7085
6929 Isolate* isolate = map->GetIsolate(); 7086 Isolate* isolate = map->GetIsolate();
6930 7087
6931 // In case the map owned its own descriptors, share the descriptors and 7088 // In case the map owned its own descriptors, share the descriptors and
6932 // transfer ownership to the new map. 7089 // transfer ownership to the new map.
6933 Handle<Map> new_map; 7090 Handle<Map> new_map;
6934 if (map->owns_descriptors()) { 7091 if (map->owns_descriptors()) {
6935 new_map = Map::CopyDropDescriptors(map); 7092 new_map = Map::CopyDropDescriptors(map);
(...skipping 2488 matching lines...) Expand 10 before | Expand all | Expand 10 after
9424 } 9581 }
9425 9582
9426 9583
9427 static bool CheckEquivalent(Map* first, Map* second) { 9584 static bool CheckEquivalent(Map* first, Map* second) {
9428 return 9585 return
9429 first->constructor() == second->constructor() && 9586 first->constructor() == second->constructor() &&
9430 first->prototype() == second->prototype() && 9587 first->prototype() == second->prototype() &&
9431 first->instance_type() == second->instance_type() && 9588 first->instance_type() == second->instance_type() &&
9432 first->bit_field() == second->bit_field() && 9589 first->bit_field() == second->bit_field() &&
9433 first->bit_field2() == second->bit_field2() && 9590 first->bit_field2() == second->bit_field2() &&
9591 first->bit_field4() == second->bit_field4() &&
9434 first->is_observed() == second->is_observed() && 9592 first->is_observed() == second->is_observed() &&
9435 first->function_with_prototype() == second->function_with_prototype(); 9593 first->function_with_prototype() == second->function_with_prototype();
9436 } 9594 }
9437 9595
9438 9596
9439 bool Map::EquivalentToForTransition(Map* other) { 9597 bool Map::EquivalentToForTransition(Map* other) {
9440 return CheckEquivalent(this, other); 9598 return CheckEquivalent(this, other);
9441 } 9599 }
9442 9600
9443 9601
(...skipping 1114 matching lines...) Expand 10 before | Expand all | Expand 10 after
10558 if (--n == 0) { 10716 if (--n == 0) {
10559 info->set_target_cell(replace_with); 10717 info->set_target_cell(replace_with);
10560 return; 10718 return;
10561 } 10719 }
10562 } 10720 }
10563 UNREACHABLE(); 10721 UNREACHABLE();
10564 } 10722 }
10565 10723
10566 10724
10567 void Code::ClearInlineCaches() { 10725 void Code::ClearInlineCaches() {
10726 ClearInlineCaches(NULL);
10727 }
10728
10729
10730 void Code::ClearInlineCaches(Code::Kind kind) {
10731 ClearInlineCaches(&kind);
10732 }
10733
10734
10735 void Code::ClearInlineCaches(Code::Kind* kind) {
10568 int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET) | 10736 int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET) |
10569 RelocInfo::ModeMask(RelocInfo::CONSTRUCT_CALL) | 10737 RelocInfo::ModeMask(RelocInfo::CONSTRUCT_CALL) |
10570 RelocInfo::ModeMask(RelocInfo::CODE_TARGET_WITH_ID) | 10738 RelocInfo::ModeMask(RelocInfo::CODE_TARGET_WITH_ID) |
10571 RelocInfo::ModeMask(RelocInfo::CODE_TARGET_CONTEXT); 10739 RelocInfo::ModeMask(RelocInfo::CODE_TARGET_CONTEXT);
10572 for (RelocIterator it(this, mask); !it.done(); it.next()) { 10740 for (RelocIterator it(this, mask); !it.done(); it.next()) {
10573 RelocInfo* info = it.rinfo(); 10741 RelocInfo* info = it.rinfo();
10574 Code* target(Code::GetCodeFromTargetAddress(info->target_address())); 10742 Code* target(Code::GetCodeFromTargetAddress(info->target_address()));
10575 if (target->is_inline_cache_stub()) { 10743 if (target->is_inline_cache_stub()) {
10576 IC::Clear(this->GetIsolate(), info->pc()); 10744 if (kind == NULL || *kind == target->kind()) {
10745 IC::Clear(this->GetIsolate(), info->pc());
10746 }
10577 } 10747 }
10578 } 10748 }
10579 } 10749 }
10580 10750
10581 10751
10582 void Code::ClearTypeFeedbackCells(Heap* heap) { 10752 void Code::ClearTypeFeedbackCells(Heap* heap) {
10583 if (kind() != FUNCTION) return; 10753 if (kind() != FUNCTION) return;
10584 Object* raw_info = type_feedback_info(); 10754 Object* raw_info = type_feedback_info();
10585 if (raw_info->IsTypeFeedbackInfo()) { 10755 if (raw_info->IsTypeFeedbackInfo()) {
10586 TypeFeedbackCells* type_feedback_cells = 10756 TypeFeedbackCells* type_feedback_cells =
(...skipping 1152 matching lines...) Expand 10 before | Expand all | Expand 10 after
11739 pt = pt->GetPrototype(isolate)) { 11909 pt = pt->GetPrototype(isolate)) {
11740 if (JSReceiver::cast(pt) == *object) { 11910 if (JSReceiver::cast(pt) == *object) {
11741 // Cycle detected. 11911 // Cycle detected.
11742 Handle<Object> error = isolate->factory()->NewError( 11912 Handle<Object> error = isolate->factory()->NewError(
11743 "cyclic_proto", HandleVector<Object>(NULL, 0)); 11913 "cyclic_proto", HandleVector<Object>(NULL, 0));
11744 isolate->Throw(*error); 11914 isolate->Throw(*error);
11745 return Handle<Object>(); 11915 return Handle<Object>();
11746 } 11916 }
11747 } 11917 }
11748 11918
11919 bool has_element_callbacks_in_chain =
11920 object->map()->MayHaveIndexedCallbacksInPrototypeChain();
11749 Handle<JSObject> real_receiver = object; 11921 Handle<JSObject> real_receiver = object;
11750 11922
11751 if (skip_hidden_prototypes) { 11923 if (skip_hidden_prototypes) {
11752 // Find the first object in the chain whose prototype object is not 11924 // Find the first object in the chain whose prototype object is not
11753 // hidden and set the new prototype on that object. 11925 // hidden and set the new prototype on that object.
11754 Object* current_proto = real_receiver->GetPrototype(); 11926 Object* current_proto = real_receiver->GetPrototype();
11755 while (current_proto->IsJSObject() && 11927 while (current_proto->IsJSObject() &&
11756 JSObject::cast(current_proto)->map()->is_hidden_prototype()) { 11928 JSObject::cast(current_proto)->map()->is_hidden_prototype()) {
11757 real_receiver = handle(JSObject::cast(current_proto), isolate); 11929 real_receiver = handle(JSObject::cast(current_proto), isolate);
11758 current_proto = current_proto->GetPrototype(isolate); 11930 current_proto = current_proto->GetPrototype(isolate);
(...skipping 12 matching lines...) Expand all
11771 11943
11772 Handle<Map> new_map = Map::GetPrototypeTransition(map, value); 11944 Handle<Map> new_map = Map::GetPrototypeTransition(map, value);
11773 if (new_map.is_null()) { 11945 if (new_map.is_null()) {
11774 new_map = Map::Copy(map); 11946 new_map = Map::Copy(map);
11775 Map::PutPrototypeTransition(map, value, new_map); 11947 Map::PutPrototypeTransition(map, value, new_map);
11776 new_map->set_prototype(*value); 11948 new_map->set_prototype(*value);
11777 } 11949 }
11778 ASSERT(new_map->prototype() == *value); 11950 ASSERT(new_map->prototype() == *value);
11779 real_receiver->set_map(*new_map); 11951 real_receiver->set_map(*new_map);
11780 11952
11953 if (!has_element_callbacks_in_chain &&
11954 new_map->MayHaveIndexedCallbacksInPrototypeChain()) {
11955 // If our prototype chain didn't have element callbacks, and now we do
11956 // have them, then we need to clear KeyedStoreICs.
11957 object->GetHeap()->ClearAllICsByKind(Code::KEYED_STORE_IC);
11958 }
11959
11781 heap->ClearInstanceofCache(); 11960 heap->ClearInstanceofCache();
11782 ASSERT(size == object->Size()); 11961 ASSERT(size == object->Size());
11783 return value; 11962 return value;
11784 } 11963 }
11785 11964
11786 11965
11787 MaybeObject* JSObject::EnsureCanContainElements(Arguments* args, 11966 MaybeObject* JSObject::EnsureCanContainElements(Arguments* args,
11788 uint32_t first_arg, 11967 uint32_t first_arg,
11789 uint32_t arg_count, 11968 uint32_t arg_count,
11790 EnsureElementsMode mode) { 11969 EnsureElementsMode mode) {
(...skipping 969 matching lines...) Expand 10 before | Expand all | Expand 10 after
12760 MaybeObject* JSObject::TransitionElementsKind(ElementsKind to_kind) { 12939 MaybeObject* JSObject::TransitionElementsKind(ElementsKind to_kind) {
12761 ASSERT(!map()->is_observed()); 12940 ASSERT(!map()->is_observed());
12762 ElementsKind from_kind = map()->elements_kind(); 12941 ElementsKind from_kind = map()->elements_kind();
12763 12942
12764 if (IsFastHoleyElementsKind(from_kind)) { 12943 if (IsFastHoleyElementsKind(from_kind)) {
12765 to_kind = GetHoleyElementsKind(to_kind); 12944 to_kind = GetHoleyElementsKind(to_kind);
12766 } 12945 }
12767 12946
12768 if (from_kind == to_kind) return this; 12947 if (from_kind == to_kind) return this;
12769 12948
12770 MaybeObject* maybe_failure = UpdateAllocationSite(to_kind); 12949 // Don't update the site if to_kind isn't fast
12771 if (maybe_failure->IsFailure()) return maybe_failure; 12950 if (IsFastElementsKind(to_kind)) {
12951 MaybeObject* maybe_failure = UpdateAllocationSite(to_kind);
12952 if (maybe_failure->IsFailure()) return maybe_failure;
12953 }
12772 12954
12773 Isolate* isolate = GetIsolate(); 12955 Isolate* isolate = GetIsolate();
12774 if (elements() == isolate->heap()->empty_fixed_array() || 12956 if (elements() == isolate->heap()->empty_fixed_array() ||
12775 (IsFastSmiOrObjectElementsKind(from_kind) && 12957 (IsFastSmiOrObjectElementsKind(from_kind) &&
12776 IsFastSmiOrObjectElementsKind(to_kind)) || 12958 IsFastSmiOrObjectElementsKind(to_kind)) ||
12777 (from_kind == FAST_DOUBLE_ELEMENTS && 12959 (from_kind == FAST_DOUBLE_ELEMENTS &&
12778 to_kind == FAST_HOLEY_DOUBLE_ELEMENTS)) { 12960 to_kind == FAST_HOLEY_DOUBLE_ELEMENTS)) {
12779 ASSERT(from_kind != TERMINAL_FAST_ELEMENTS_KIND); 12961 ASSERT(from_kind != TERMINAL_FAST_ELEMENTS_KIND);
12780 // No change is needed to the elements() buffer, the transition 12962 // No change is needed to the elements() buffer, the transition
12781 // only requires a map change. 12963 // only requires a map change.
(...skipping 3616 matching lines...) Expand 10 before | Expand all | Expand 10 after
16398 #define ERROR_MESSAGES_TEXTS(C, T) T, 16580 #define ERROR_MESSAGES_TEXTS(C, T) T,
16399 static const char* error_messages_[] = { 16581 static const char* error_messages_[] = {
16400 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS) 16582 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS)
16401 }; 16583 };
16402 #undef ERROR_MESSAGES_TEXTS 16584 #undef ERROR_MESSAGES_TEXTS
16403 return error_messages_[reason]; 16585 return error_messages_[reason];
16404 } 16586 }
16405 16587
16406 16588
16407 } } // namespace v8::internal 16589 } } // namespace v8::internal
OLDNEW
« src/objects.h ('K') | « src/objects.h ('k') | src/objects-inl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698