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 |