| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 // | 4 // |
| 5 // Review notes: | 5 // Review notes: |
| 6 // | 6 // |
| 7 // - The use of macros in these inline functions may seem superfluous | 7 // - The use of macros in these inline functions may seem superfluous |
| 8 // but it is absolutely needed to make sure gcc generates optimal | 8 // but it is absolutely needed to make sure gcc generates optimal |
| 9 // code. gcc is not happy when attempting to inline too deep. | 9 // code. gcc is not happy when attempting to inline too deep. |
| 10 // | 10 // |
| (...skipping 1862 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1873 WRITE_FIELD(this, kPropertiesOffset, GetHeap()->empty_fixed_array()); | 1873 WRITE_FIELD(this, kPropertiesOffset, GetHeap()->empty_fixed_array()); |
| 1874 } | 1874 } |
| 1875 | 1875 |
| 1876 | 1876 |
| 1877 void JSObject::initialize_elements() { | 1877 void JSObject::initialize_elements() { |
| 1878 FixedArrayBase* elements = map()->GetInitialElements(); | 1878 FixedArrayBase* elements = map()->GetInitialElements(); |
| 1879 WRITE_FIELD(this, kElementsOffset, elements); | 1879 WRITE_FIELD(this, kElementsOffset, elements); |
| 1880 } | 1880 } |
| 1881 | 1881 |
| 1882 | 1882 |
| 1883 Handle<String> Map::ExpectedTransitionKey(Handle<Map> map) { | |
| 1884 DisallowHeapAllocation no_gc; | |
| 1885 if (!map->HasTransitionArray()) return Handle<String>::null(); | |
| 1886 TransitionArray* transitions = map->transitions(); | |
| 1887 if (!transitions->IsSimpleTransition()) return Handle<String>::null(); | |
| 1888 int transition = TransitionArray::kSimpleTransitionIndex; | |
| 1889 PropertyDetails details = transitions->GetTargetDetails(transition); | |
| 1890 Name* name = transitions->GetKey(transition); | |
| 1891 if (details.type() != DATA) return Handle<String>::null(); | |
| 1892 if (details.attributes() != NONE) return Handle<String>::null(); | |
| 1893 if (!name->IsString()) return Handle<String>::null(); | |
| 1894 return Handle<String>(String::cast(name)); | |
| 1895 } | |
| 1896 | |
| 1897 | |
| 1898 Handle<Map> Map::ExpectedTransitionTarget(Handle<Map> map) { | |
| 1899 DCHECK(!ExpectedTransitionKey(map).is_null()); | |
| 1900 return Handle<Map>(map->transitions()->GetTarget( | |
| 1901 TransitionArray::kSimpleTransitionIndex)); | |
| 1902 } | |
| 1903 | |
| 1904 | |
| 1905 Handle<Map> Map::FindTransitionToField(Handle<Map> map, Handle<Name> key) { | |
| 1906 DisallowHeapAllocation no_allocation; | |
| 1907 if (!map->HasTransitionArray()) return Handle<Map>::null(); | |
| 1908 TransitionArray* transitions = map->transitions(); | |
| 1909 int transition = transitions->Search(kData, *key, NONE); | |
| 1910 if (transition == TransitionArray::kNotFound) return Handle<Map>::null(); | |
| 1911 PropertyDetails details = transitions->GetTargetDetails(transition); | |
| 1912 if (details.type() != DATA) return Handle<Map>::null(); | |
| 1913 DCHECK_EQ(NONE, details.attributes()); | |
| 1914 return Handle<Map>(transitions->GetTarget(transition)); | |
| 1915 } | |
| 1916 | |
| 1917 | |
| 1918 ACCESSORS(Oddball, to_string, String, kToStringOffset) | 1883 ACCESSORS(Oddball, to_string, String, kToStringOffset) |
| 1919 ACCESSORS(Oddball, to_number, Object, kToNumberOffset) | 1884 ACCESSORS(Oddball, to_number, Object, kToNumberOffset) |
| 1920 | 1885 |
| 1921 | 1886 |
| 1922 byte Oddball::kind() const { | 1887 byte Oddball::kind() const { |
| 1923 return Smi::cast(READ_FIELD(this, kKindOffset))->value(); | 1888 return Smi::cast(READ_FIELD(this, kKindOffset))->value(); |
| 1924 } | 1889 } |
| 1925 | 1890 |
| 1926 | 1891 |
| 1927 void Oddball::set_kind(byte value) { | 1892 void Oddball::set_kind(byte value) { |
| (...skipping 1163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3091 if (has_fast_smi_or_object_elements() || | 3056 if (has_fast_smi_or_object_elements() || |
| 3092 has_fast_double_elements()) { | 3057 has_fast_double_elements()) { |
| 3093 DCHECK(!GetHeap()->InNewSpace(GetHeap()->empty_fixed_array())); | 3058 DCHECK(!GetHeap()->InNewSpace(GetHeap()->empty_fixed_array())); |
| 3094 return GetHeap()->empty_fixed_array(); | 3059 return GetHeap()->empty_fixed_array(); |
| 3095 } else if (has_external_array_elements()) { | 3060 } else if (has_external_array_elements()) { |
| 3096 ExternalArray* empty_array = GetHeap()->EmptyExternalArrayForMap(this); | 3061 ExternalArray* empty_array = GetHeap()->EmptyExternalArrayForMap(this); |
| 3097 DCHECK(!GetHeap()->InNewSpace(empty_array)); | 3062 DCHECK(!GetHeap()->InNewSpace(empty_array)); |
| 3098 return empty_array; | 3063 return empty_array; |
| 3099 } else if (has_fixed_typed_array_elements()) { | 3064 } else if (has_fixed_typed_array_elements()) { |
| 3100 FixedTypedArrayBase* empty_array = | 3065 FixedTypedArrayBase* empty_array = |
| 3101 GetHeap()->EmptyFixedTypedArrayForMap(this); | 3066 GetHeap()->EmptyFixedTypedArrayForMap(this); |
| 3102 DCHECK(!GetHeap()->InNewSpace(empty_array)); | 3067 DCHECK(!GetHeap()->InNewSpace(empty_array)); |
| 3103 return empty_array; | 3068 return empty_array; |
| 3104 } else { | 3069 } else { |
| 3105 UNREACHABLE(); | 3070 UNREACHABLE(); |
| 3106 } | 3071 } |
| 3107 return NULL; | 3072 return NULL; |
| 3108 } | 3073 } |
| 3109 | 3074 |
| 3110 | 3075 |
| 3111 Object** DescriptorArray::GetKeySlot(int descriptor_number) { | 3076 Object** DescriptorArray::GetKeySlot(int descriptor_number) { |
| (...skipping 2198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5310 } | 5275 } |
| 5311 | 5276 |
| 5312 | 5277 |
| 5313 void Map::set_prototype(Object* value, WriteBarrierMode mode) { | 5278 void Map::set_prototype(Object* value, WriteBarrierMode mode) { |
| 5314 DCHECK(value->IsNull() || value->IsJSReceiver()); | 5279 DCHECK(value->IsNull() || value->IsJSReceiver()); |
| 5315 WRITE_FIELD(this, kPrototypeOffset, value); | 5280 WRITE_FIELD(this, kPrototypeOffset, value); |
| 5316 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kPrototypeOffset, value, mode); | 5281 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kPrototypeOffset, value, mode); |
| 5317 } | 5282 } |
| 5318 | 5283 |
| 5319 | 5284 |
| 5320 // If the descriptor is using the empty transition array, install a new empty | |
| 5321 // transition array that will have place for an element transition. | |
| 5322 static void EnsureHasTransitionArray(Handle<Map> map) { | |
| 5323 Handle<TransitionArray> transitions; | |
| 5324 if (!map->HasTransitionArray()) { | |
| 5325 transitions = TransitionArray::Allocate(map->GetIsolate(), 0); | |
| 5326 transitions->set_back_pointer_storage(map->GetBackPointer()); | |
| 5327 } else if (!map->transitions()->IsFullTransitionArray()) { | |
| 5328 transitions = TransitionArray::ExtendToFullTransitionArray(map); | |
| 5329 } else { | |
| 5330 return; | |
| 5331 } | |
| 5332 map->set_transitions(*transitions); | |
| 5333 } | |
| 5334 | |
| 5335 | |
| 5336 LayoutDescriptor* Map::layout_descriptor_gc_safe() { | 5285 LayoutDescriptor* Map::layout_descriptor_gc_safe() { |
| 5337 Object* layout_desc = READ_FIELD(this, kLayoutDecriptorOffset); | 5286 Object* layout_desc = READ_FIELD(this, kLayoutDecriptorOffset); |
| 5338 return LayoutDescriptor::cast_gc_safe(layout_desc); | 5287 return LayoutDescriptor::cast_gc_safe(layout_desc); |
| 5339 } | 5288 } |
| 5340 | 5289 |
| 5341 | 5290 |
| 5342 bool Map::HasFastPointerLayout() const { | 5291 bool Map::HasFastPointerLayout() const { |
| 5343 Object* layout_desc = READ_FIELD(this, kLayoutDecriptorOffset); | 5292 Object* layout_desc = READ_FIELD(this, kLayoutDecriptorOffset); |
| 5344 return LayoutDescriptor::IsFastPointerLayout(layout_desc); | 5293 return LayoutDescriptor::IsFastPointerLayout(layout_desc); |
| 5345 } | 5294 } |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5428 | 5377 |
| 5429 Object* Map::GetBackPointer() { | 5378 Object* Map::GetBackPointer() { |
| 5430 Object* object = constructor_or_backpointer(); | 5379 Object* object = constructor_or_backpointer(); |
| 5431 if (object->IsMap()) { | 5380 if (object->IsMap()) { |
| 5432 return object; | 5381 return object; |
| 5433 } | 5382 } |
| 5434 return GetIsolate()->heap()->undefined_value(); | 5383 return GetIsolate()->heap()->undefined_value(); |
| 5435 } | 5384 } |
| 5436 | 5385 |
| 5437 | 5386 |
| 5438 bool Map::HasElementsTransition() { | 5387 Map* Map::ElementsTransitionMap() { |
| 5439 return HasTransitionArray() && transitions()->HasElementsTransition(); | 5388 return TransitionArray::SearchSpecial( |
| 5389 this, GetHeap()->elements_transition_symbol()); |
| 5440 } | 5390 } |
| 5441 | 5391 |
| 5442 | 5392 |
| 5443 bool Map::HasTransitionArray() const { | 5393 ACCESSORS(Map, raw_transitions, Object, kTransitionsOffset) |
| 5444 Object* object = READ_FIELD(this, kTransitionsOffset); | |
| 5445 return object->IsTransitionArray(); | |
| 5446 } | |
| 5447 | |
| 5448 | |
| 5449 Map* Map::elements_transition_map() { | |
| 5450 int index = | |
| 5451 transitions()->SearchSpecial(GetHeap()->elements_transition_symbol()); | |
| 5452 return transitions()->GetTarget(index); | |
| 5453 } | |
| 5454 | |
| 5455 | |
| 5456 bool Map::CanHaveMoreTransitions() { | |
| 5457 if (!HasTransitionArray()) return true; | |
| 5458 return transitions()->number_of_transitions() < | |
| 5459 TransitionArray::kMaxNumberOfTransitions; | |
| 5460 } | |
| 5461 | |
| 5462 | |
| 5463 Map* Map::GetTransition(int transition_index) { | |
| 5464 return transitions()->GetTarget(transition_index); | |
| 5465 } | |
| 5466 | |
| 5467 | |
| 5468 int Map::SearchSpecialTransition(Symbol* name) { | |
| 5469 if (HasTransitionArray()) { | |
| 5470 return transitions()->SearchSpecial(name); | |
| 5471 } | |
| 5472 return TransitionArray::kNotFound; | |
| 5473 } | |
| 5474 | |
| 5475 | |
| 5476 int Map::SearchTransition(PropertyKind kind, Name* name, | |
| 5477 PropertyAttributes attributes) { | |
| 5478 if (HasTransitionArray()) { | |
| 5479 return transitions()->Search(kind, name, attributes); | |
| 5480 } | |
| 5481 return TransitionArray::kNotFound; | |
| 5482 } | |
| 5483 | |
| 5484 | |
| 5485 FixedArray* Map::GetPrototypeTransitions() { | |
| 5486 if (!HasTransitionArray()) return GetHeap()->empty_fixed_array(); | |
| 5487 if (!transitions()->HasPrototypeTransitions()) { | |
| 5488 return GetHeap()->empty_fixed_array(); | |
| 5489 } | |
| 5490 return transitions()->GetPrototypeTransitions(); | |
| 5491 } | |
| 5492 | |
| 5493 | |
| 5494 void Map::SetPrototypeTransitions( | |
| 5495 Handle<Map> map, Handle<FixedArray> proto_transitions) { | |
| 5496 EnsureHasTransitionArray(map); | |
| 5497 int old_number_of_transitions = map->NumberOfProtoTransitions(); | |
| 5498 if (Heap::ShouldZapGarbage() && map->HasPrototypeTransitions()) { | |
| 5499 DCHECK(map->GetPrototypeTransitions() != *proto_transitions); | |
| 5500 map->ZapPrototypeTransitions(); | |
| 5501 } | |
| 5502 map->transitions()->SetPrototypeTransitions(*proto_transitions); | |
| 5503 map->SetNumberOfProtoTransitions(old_number_of_transitions); | |
| 5504 } | |
| 5505 | |
| 5506 | |
| 5507 bool Map::HasPrototypeTransitions() { | |
| 5508 return HasTransitionArray() && transitions()->HasPrototypeTransitions(); | |
| 5509 } | |
| 5510 | |
| 5511 | |
| 5512 TransitionArray* Map::transitions() const { | |
| 5513 DCHECK(HasTransitionArray()); | |
| 5514 Object* object = READ_FIELD(this, kTransitionsOffset); | |
| 5515 return TransitionArray::cast(object); | |
| 5516 } | |
| 5517 | |
| 5518 | |
| 5519 void Map::set_transitions(TransitionArray* transition_array, | |
| 5520 WriteBarrierMode mode) { | |
| 5521 // Transition arrays are not shared. When one is replaced, it should not | |
| 5522 // keep referenced objects alive, so we zap it. | |
| 5523 // When there is another reference to the array somewhere (e.g. a handle), | |
| 5524 // not zapping turns from a waste of memory into a source of crashes. | |
| 5525 if (HasTransitionArray()) { | |
| 5526 #ifdef DEBUG | |
| 5527 for (int i = 0; i < transitions()->number_of_transitions(); i++) { | |
| 5528 Map* target = transitions()->GetTarget(i); | |
| 5529 if (target->instance_descriptors() == instance_descriptors()) { | |
| 5530 Name* key = transitions()->GetKey(i); | |
| 5531 int new_target_index; | |
| 5532 if (TransitionArray::IsSpecialTransition(key)) { | |
| 5533 new_target_index = transition_array->SearchSpecial(Symbol::cast(key)); | |
| 5534 } else { | |
| 5535 PropertyDetails details = | |
| 5536 TransitionArray::GetTargetDetails(key, target); | |
| 5537 new_target_index = transition_array->Search(details.kind(), key, | |
| 5538 details.attributes()); | |
| 5539 } | |
| 5540 DCHECK_NE(TransitionArray::kNotFound, new_target_index); | |
| 5541 DCHECK_EQ(target, transition_array->GetTarget(new_target_index)); | |
| 5542 } | |
| 5543 } | |
| 5544 #endif | |
| 5545 DCHECK(transitions() != transition_array); | |
| 5546 ZapTransitions(); | |
| 5547 } | |
| 5548 | |
| 5549 WRITE_FIELD(this, kTransitionsOffset, transition_array); | |
| 5550 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kTransitionsOffset, | |
| 5551 transition_array, mode); | |
| 5552 } | |
| 5553 | |
| 5554 | |
| 5555 void Map::init_transitions(Object* undefined) { | |
| 5556 DCHECK(undefined->IsUndefined()); | |
| 5557 WRITE_FIELD(this, kTransitionsOffset, undefined); | |
| 5558 } | |
| 5559 | 5394 |
| 5560 | 5395 |
| 5561 void Map::SetBackPointer(Object* value, WriteBarrierMode mode) { | 5396 void Map::SetBackPointer(Object* value, WriteBarrierMode mode) { |
| 5562 DCHECK(instance_type() >= FIRST_JS_RECEIVER_TYPE); | 5397 DCHECK(instance_type() >= FIRST_JS_RECEIVER_TYPE); |
| 5563 DCHECK((value->IsUndefined() && GetBackPointer()->IsMap()) || | 5398 DCHECK((value->IsUndefined() && GetBackPointer()->IsMap()) || |
| 5564 (value->IsMap() && GetBackPointer()->IsUndefined())); | 5399 (value->IsMap() && GetBackPointer()->IsUndefined())); |
| 5565 DCHECK(!value->IsMap() || | 5400 DCHECK(!value->IsMap() || |
| 5566 Map::cast(value)->GetConstructor() == constructor_or_backpointer()); | 5401 Map::cast(value)->GetConstructor() == constructor_or_backpointer()); |
| 5567 set_constructor_or_backpointer(value, mode); | 5402 set_constructor_or_backpointer(value, mode); |
| 5568 } | 5403 } |
| 5569 | 5404 |
| 5570 | 5405 |
| 5571 ACCESSORS(Map, code_cache, Object, kCodeCacheOffset) | 5406 ACCESSORS(Map, code_cache, Object, kCodeCacheOffset) |
| 5572 ACCESSORS(Map, dependent_code, DependentCode, kDependentCodeOffset) | 5407 ACCESSORS(Map, dependent_code, DependentCode, kDependentCodeOffset) |
| 5573 ACCESSORS(Map, weak_cell_cache, Object, kWeakCellCacheOffset) | 5408 ACCESSORS(Map, weak_cell_cache, Object, kWeakCellCacheOffset) |
| 5574 ACCESSORS(Map, constructor_or_backpointer, Object, | 5409 ACCESSORS(Map, constructor_or_backpointer, Object, |
| 5575 kConstructorOrBackPointerOffset) | 5410 kConstructorOrBackPointerOffset) |
| 5576 | 5411 |
| 5412 |
| 5577 Object* Map::GetConstructor() const { | 5413 Object* Map::GetConstructor() const { |
| 5578 Object* maybe_constructor = constructor_or_backpointer(); | 5414 Object* maybe_constructor = constructor_or_backpointer(); |
| 5579 // Follow any back pointers. | 5415 // Follow any back pointers. |
| 5580 while (maybe_constructor->IsMap()) { | 5416 while (maybe_constructor->IsMap()) { |
| 5581 maybe_constructor = | 5417 maybe_constructor = |
| 5582 Map::cast(maybe_constructor)->constructor_or_backpointer(); | 5418 Map::cast(maybe_constructor)->constructor_or_backpointer(); |
| 5583 } | 5419 } |
| 5584 return maybe_constructor; | 5420 return maybe_constructor; |
| 5585 } | 5421 } |
| 5422 |
| 5423 |
| 5586 void Map::SetConstructor(Object* constructor, WriteBarrierMode mode) { | 5424 void Map::SetConstructor(Object* constructor, WriteBarrierMode mode) { |
| 5587 // Never overwrite a back pointer with a constructor. | 5425 // Never overwrite a back pointer with a constructor. |
| 5588 DCHECK(!constructor_or_backpointer()->IsMap()); | 5426 DCHECK(!constructor_or_backpointer()->IsMap()); |
| 5589 set_constructor_or_backpointer(constructor, mode); | 5427 set_constructor_or_backpointer(constructor, mode); |
| 5590 } | 5428 } |
| 5591 | 5429 |
| 5430 |
| 5592 ACCESSORS(JSFunction, shared, SharedFunctionInfo, kSharedFunctionInfoOffset) | 5431 ACCESSORS(JSFunction, shared, SharedFunctionInfo, kSharedFunctionInfoOffset) |
| 5593 ACCESSORS(JSFunction, literals_or_bindings, FixedArray, kLiteralsOffset) | 5432 ACCESSORS(JSFunction, literals_or_bindings, FixedArray, kLiteralsOffset) |
| 5594 ACCESSORS(JSFunction, next_function_link, Object, kNextFunctionLinkOffset) | 5433 ACCESSORS(JSFunction, next_function_link, Object, kNextFunctionLinkOffset) |
| 5595 | 5434 |
| 5596 ACCESSORS(GlobalObject, builtins, JSBuiltinsObject, kBuiltinsOffset) | 5435 ACCESSORS(GlobalObject, builtins, JSBuiltinsObject, kBuiltinsOffset) |
| 5597 ACCESSORS(GlobalObject, native_context, Context, kNativeContextOffset) | 5436 ACCESSORS(GlobalObject, native_context, Context, kNativeContextOffset) |
| 5598 ACCESSORS(GlobalObject, global_proxy, JSObject, kGlobalProxyOffset) | 5437 ACCESSORS(GlobalObject, global_proxy, JSObject, kGlobalProxyOffset) |
| 5599 | 5438 |
| 5600 ACCESSORS(JSGlobalProxy, native_context, Object, kNativeContextOffset) | 5439 ACCESSORS(JSGlobalProxy, native_context, Object, kNativeContextOffset) |
| 5601 ACCESSORS(JSGlobalProxy, hash, Object, kHashOffset) | 5440 ACCESSORS(JSGlobalProxy, hash, Object, kHashOffset) |
| (...skipping 2090 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7692 #undef READ_SHORT_FIELD | 7531 #undef READ_SHORT_FIELD |
| 7693 #undef WRITE_SHORT_FIELD | 7532 #undef WRITE_SHORT_FIELD |
| 7694 #undef READ_BYTE_FIELD | 7533 #undef READ_BYTE_FIELD |
| 7695 #undef WRITE_BYTE_FIELD | 7534 #undef WRITE_BYTE_FIELD |
| 7696 #undef NOBARRIER_READ_BYTE_FIELD | 7535 #undef NOBARRIER_READ_BYTE_FIELD |
| 7697 #undef NOBARRIER_WRITE_BYTE_FIELD | 7536 #undef NOBARRIER_WRITE_BYTE_FIELD |
| 7698 | 7537 |
| 7699 } } // namespace v8::internal | 7538 } } // namespace v8::internal |
| 7700 | 7539 |
| 7701 #endif // V8_OBJECTS_INL_H_ | 7540 #endif // V8_OBJECTS_INL_H_ |
| OLD | NEW |