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 1859 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1870 WRITE_FIELD(this, kPropertiesOffset, GetHeap()->empty_fixed_array()); | 1870 WRITE_FIELD(this, kPropertiesOffset, GetHeap()->empty_fixed_array()); |
1871 } | 1871 } |
1872 | 1872 |
1873 | 1873 |
1874 void JSObject::initialize_elements() { | 1874 void JSObject::initialize_elements() { |
1875 FixedArrayBase* elements = map()->GetInitialElements(); | 1875 FixedArrayBase* elements = map()->GetInitialElements(); |
1876 WRITE_FIELD(this, kElementsOffset, elements); | 1876 WRITE_FIELD(this, kElementsOffset, elements); |
1877 } | 1877 } |
1878 | 1878 |
1879 | 1879 |
| 1880 Handle<String> Map::ExpectedTransitionKey(Handle<Map> map) { |
| 1881 DisallowHeapAllocation no_gc; |
| 1882 if (!map->HasTransitionArray()) return Handle<String>::null(); |
| 1883 TransitionArray* transitions = map->transitions(); |
| 1884 if (!transitions->IsSimpleTransition()) return Handle<String>::null(); |
| 1885 int transition = TransitionArray::kSimpleTransitionIndex; |
| 1886 PropertyDetails details = transitions->GetTargetDetails(transition); |
| 1887 Name* name = transitions->GetKey(transition); |
| 1888 if (details.type() != DATA) return Handle<String>::null(); |
| 1889 if (details.attributes() != NONE) return Handle<String>::null(); |
| 1890 if (!name->IsString()) return Handle<String>::null(); |
| 1891 return Handle<String>(String::cast(name)); |
| 1892 } |
| 1893 |
| 1894 |
| 1895 Handle<Map> Map::ExpectedTransitionTarget(Handle<Map> map) { |
| 1896 DCHECK(!ExpectedTransitionKey(map).is_null()); |
| 1897 return Handle<Map>(map->transitions()->GetTarget( |
| 1898 TransitionArray::kSimpleTransitionIndex)); |
| 1899 } |
| 1900 |
| 1901 |
| 1902 Handle<Map> Map::FindTransitionToField(Handle<Map> map, Handle<Name> key) { |
| 1903 DisallowHeapAllocation no_allocation; |
| 1904 if (!map->HasTransitionArray()) return Handle<Map>::null(); |
| 1905 TransitionArray* transitions = map->transitions(); |
| 1906 int transition = transitions->Search(kData, *key, NONE); |
| 1907 if (transition == TransitionArray::kNotFound) return Handle<Map>::null(); |
| 1908 PropertyDetails details = transitions->GetTargetDetails(transition); |
| 1909 if (details.type() != DATA) return Handle<Map>::null(); |
| 1910 DCHECK_EQ(NONE, details.attributes()); |
| 1911 return Handle<Map>(transitions->GetTarget(transition)); |
| 1912 } |
| 1913 |
| 1914 |
1880 ACCESSORS(Oddball, to_string, String, kToStringOffset) | 1915 ACCESSORS(Oddball, to_string, String, kToStringOffset) |
1881 ACCESSORS(Oddball, to_number, Object, kToNumberOffset) | 1916 ACCESSORS(Oddball, to_number, Object, kToNumberOffset) |
1882 | 1917 |
1883 | 1918 |
1884 byte Oddball::kind() const { | 1919 byte Oddball::kind() const { |
1885 return Smi::cast(READ_FIELD(this, kKindOffset))->value(); | 1920 return Smi::cast(READ_FIELD(this, kKindOffset))->value(); |
1886 } | 1921 } |
1887 | 1922 |
1888 | 1923 |
1889 void Oddball::set_kind(byte value) { | 1924 void Oddball::set_kind(byte value) { |
(...skipping 1105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2995 if (has_fast_smi_or_object_elements() || | 3030 if (has_fast_smi_or_object_elements() || |
2996 has_fast_double_elements()) { | 3031 has_fast_double_elements()) { |
2997 DCHECK(!GetHeap()->InNewSpace(GetHeap()->empty_fixed_array())); | 3032 DCHECK(!GetHeap()->InNewSpace(GetHeap()->empty_fixed_array())); |
2998 return GetHeap()->empty_fixed_array(); | 3033 return GetHeap()->empty_fixed_array(); |
2999 } else if (has_external_array_elements()) { | 3034 } else if (has_external_array_elements()) { |
3000 ExternalArray* empty_array = GetHeap()->EmptyExternalArrayForMap(this); | 3035 ExternalArray* empty_array = GetHeap()->EmptyExternalArrayForMap(this); |
3001 DCHECK(!GetHeap()->InNewSpace(empty_array)); | 3036 DCHECK(!GetHeap()->InNewSpace(empty_array)); |
3002 return empty_array; | 3037 return empty_array; |
3003 } else if (has_fixed_typed_array_elements()) { | 3038 } else if (has_fixed_typed_array_elements()) { |
3004 FixedTypedArrayBase* empty_array = | 3039 FixedTypedArrayBase* empty_array = |
3005 GetHeap()->EmptyFixedTypedArrayForMap(this); | 3040 GetHeap()->EmptyFixedTypedArrayForMap(this); |
3006 DCHECK(!GetHeap()->InNewSpace(empty_array)); | 3041 DCHECK(!GetHeap()->InNewSpace(empty_array)); |
3007 return empty_array; | 3042 return empty_array; |
3008 } else { | 3043 } else { |
3009 UNREACHABLE(); | 3044 UNREACHABLE(); |
3010 } | 3045 } |
3011 return NULL; | 3046 return NULL; |
3012 } | 3047 } |
3013 | 3048 |
3014 | 3049 |
3015 Object** DescriptorArray::GetKeySlot(int descriptor_number) { | 3050 Object** DescriptorArray::GetKeySlot(int descriptor_number) { |
(...skipping 2197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5213 } | 5248 } |
5214 | 5249 |
5215 | 5250 |
5216 void Map::set_prototype(Object* value, WriteBarrierMode mode) { | 5251 void Map::set_prototype(Object* value, WriteBarrierMode mode) { |
5217 DCHECK(value->IsNull() || value->IsJSReceiver()); | 5252 DCHECK(value->IsNull() || value->IsJSReceiver()); |
5218 WRITE_FIELD(this, kPrototypeOffset, value); | 5253 WRITE_FIELD(this, kPrototypeOffset, value); |
5219 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kPrototypeOffset, value, mode); | 5254 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kPrototypeOffset, value, mode); |
5220 } | 5255 } |
5221 | 5256 |
5222 | 5257 |
| 5258 // If the descriptor is using the empty transition array, install a new empty |
| 5259 // transition array that will have place for an element transition. |
| 5260 static void EnsureHasTransitionArray(Handle<Map> map) { |
| 5261 Handle<TransitionArray> transitions; |
| 5262 if (!map->HasTransitionArray()) { |
| 5263 transitions = TransitionArray::Allocate(map->GetIsolate(), 0); |
| 5264 transitions->set_back_pointer_storage(map->GetBackPointer()); |
| 5265 } else if (!map->transitions()->IsFullTransitionArray()) { |
| 5266 transitions = TransitionArray::ExtendToFullTransitionArray(map); |
| 5267 } else { |
| 5268 return; |
| 5269 } |
| 5270 map->set_transitions(*transitions); |
| 5271 } |
| 5272 |
| 5273 |
5223 LayoutDescriptor* Map::layout_descriptor_gc_safe() { | 5274 LayoutDescriptor* Map::layout_descriptor_gc_safe() { |
5224 Object* layout_desc = READ_FIELD(this, kLayoutDecriptorOffset); | 5275 Object* layout_desc = READ_FIELD(this, kLayoutDecriptorOffset); |
5225 return LayoutDescriptor::cast_gc_safe(layout_desc); | 5276 return LayoutDescriptor::cast_gc_safe(layout_desc); |
5226 } | 5277 } |
5227 | 5278 |
5228 | 5279 |
5229 bool Map::HasFastPointerLayout() const { | 5280 bool Map::HasFastPointerLayout() const { |
5230 Object* layout_desc = READ_FIELD(this, kLayoutDecriptorOffset); | 5281 Object* layout_desc = READ_FIELD(this, kLayoutDecriptorOffset); |
5231 return LayoutDescriptor::IsFastPointerLayout(layout_desc); | 5282 return LayoutDescriptor::IsFastPointerLayout(layout_desc); |
5232 } | 5283 } |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5315 | 5366 |
5316 Object* Map::GetBackPointer() { | 5367 Object* Map::GetBackPointer() { |
5317 Object* object = constructor_or_backpointer(); | 5368 Object* object = constructor_or_backpointer(); |
5318 if (object->IsMap()) { | 5369 if (object->IsMap()) { |
5319 return object; | 5370 return object; |
5320 } | 5371 } |
5321 return GetIsolate()->heap()->undefined_value(); | 5372 return GetIsolate()->heap()->undefined_value(); |
5322 } | 5373 } |
5323 | 5374 |
5324 | 5375 |
5325 Map* Map::ElementsTransitionMap() { | 5376 bool Map::HasElementsTransition() { |
5326 return TransitionArray::SearchSpecial( | 5377 return HasTransitionArray() && transitions()->HasElementsTransition(); |
5327 this, GetHeap()->elements_transition_symbol()); | |
5328 } | 5378 } |
5329 | 5379 |
5330 | 5380 |
5331 ACCESSORS(Map, raw_transitions, Object, kTransitionsOffset) | 5381 bool Map::HasTransitionArray() const { |
| 5382 Object* object = READ_FIELD(this, kTransitionsOffset); |
| 5383 return object->IsTransitionArray(); |
| 5384 } |
| 5385 |
| 5386 |
| 5387 Map* Map::elements_transition_map() { |
| 5388 int index = |
| 5389 transitions()->SearchSpecial(GetHeap()->elements_transition_symbol()); |
| 5390 return transitions()->GetTarget(index); |
| 5391 } |
| 5392 |
| 5393 |
| 5394 bool Map::CanHaveMoreTransitions() { |
| 5395 if (!HasTransitionArray()) return true; |
| 5396 return transitions()->number_of_transitions() < |
| 5397 TransitionArray::kMaxNumberOfTransitions; |
| 5398 } |
| 5399 |
| 5400 |
| 5401 Map* Map::GetTransition(int transition_index) { |
| 5402 return transitions()->GetTarget(transition_index); |
| 5403 } |
| 5404 |
| 5405 |
| 5406 int Map::SearchSpecialTransition(Symbol* name) { |
| 5407 if (HasTransitionArray()) { |
| 5408 return transitions()->SearchSpecial(name); |
| 5409 } |
| 5410 return TransitionArray::kNotFound; |
| 5411 } |
| 5412 |
| 5413 |
| 5414 int Map::SearchTransition(PropertyKind kind, Name* name, |
| 5415 PropertyAttributes attributes) { |
| 5416 if (HasTransitionArray()) { |
| 5417 return transitions()->Search(kind, name, attributes); |
| 5418 } |
| 5419 return TransitionArray::kNotFound; |
| 5420 } |
| 5421 |
| 5422 |
| 5423 FixedArray* Map::GetPrototypeTransitions() { |
| 5424 if (!HasTransitionArray()) return GetHeap()->empty_fixed_array(); |
| 5425 if (!transitions()->HasPrototypeTransitions()) { |
| 5426 return GetHeap()->empty_fixed_array(); |
| 5427 } |
| 5428 return transitions()->GetPrototypeTransitions(); |
| 5429 } |
| 5430 |
| 5431 |
| 5432 void Map::SetPrototypeTransitions( |
| 5433 Handle<Map> map, Handle<FixedArray> proto_transitions) { |
| 5434 EnsureHasTransitionArray(map); |
| 5435 int old_number_of_transitions = map->NumberOfProtoTransitions(); |
| 5436 if (Heap::ShouldZapGarbage() && map->HasPrototypeTransitions()) { |
| 5437 DCHECK(map->GetPrototypeTransitions() != *proto_transitions); |
| 5438 map->ZapPrototypeTransitions(); |
| 5439 } |
| 5440 map->transitions()->SetPrototypeTransitions(*proto_transitions); |
| 5441 map->SetNumberOfProtoTransitions(old_number_of_transitions); |
| 5442 } |
| 5443 |
| 5444 |
| 5445 bool Map::HasPrototypeTransitions() { |
| 5446 return HasTransitionArray() && transitions()->HasPrototypeTransitions(); |
| 5447 } |
| 5448 |
| 5449 |
| 5450 TransitionArray* Map::transitions() const { |
| 5451 DCHECK(HasTransitionArray()); |
| 5452 Object* object = READ_FIELD(this, kTransitionsOffset); |
| 5453 return TransitionArray::cast(object); |
| 5454 } |
| 5455 |
| 5456 |
| 5457 void Map::set_transitions(TransitionArray* transition_array, |
| 5458 WriteBarrierMode mode) { |
| 5459 // Transition arrays are not shared. When one is replaced, it should not |
| 5460 // keep referenced objects alive, so we zap it. |
| 5461 // When there is another reference to the array somewhere (e.g. a handle), |
| 5462 // not zapping turns from a waste of memory into a source of crashes. |
| 5463 if (HasTransitionArray()) { |
| 5464 #ifdef DEBUG |
| 5465 for (int i = 0; i < transitions()->number_of_transitions(); i++) { |
| 5466 Map* target = transitions()->GetTarget(i); |
| 5467 if (target->instance_descriptors() == instance_descriptors()) { |
| 5468 Name* key = transitions()->GetKey(i); |
| 5469 int new_target_index; |
| 5470 if (TransitionArray::IsSpecialTransition(key)) { |
| 5471 new_target_index = transition_array->SearchSpecial(Symbol::cast(key)); |
| 5472 } else { |
| 5473 PropertyDetails details = |
| 5474 TransitionArray::GetTargetDetails(key, target); |
| 5475 new_target_index = transition_array->Search(details.kind(), key, |
| 5476 details.attributes()); |
| 5477 } |
| 5478 DCHECK_NE(TransitionArray::kNotFound, new_target_index); |
| 5479 DCHECK_EQ(target, transition_array->GetTarget(new_target_index)); |
| 5480 } |
| 5481 } |
| 5482 #endif |
| 5483 DCHECK(transitions() != transition_array); |
| 5484 ZapTransitions(); |
| 5485 } |
| 5486 |
| 5487 WRITE_FIELD(this, kTransitionsOffset, transition_array); |
| 5488 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kTransitionsOffset, |
| 5489 transition_array, mode); |
| 5490 } |
| 5491 |
| 5492 |
| 5493 void Map::init_transitions(Object* undefined) { |
| 5494 DCHECK(undefined->IsUndefined()); |
| 5495 WRITE_FIELD(this, kTransitionsOffset, undefined); |
| 5496 } |
5332 | 5497 |
5333 | 5498 |
5334 void Map::SetBackPointer(Object* value, WriteBarrierMode mode) { | 5499 void Map::SetBackPointer(Object* value, WriteBarrierMode mode) { |
5335 DCHECK(instance_type() >= FIRST_JS_RECEIVER_TYPE); | 5500 DCHECK(instance_type() >= FIRST_JS_RECEIVER_TYPE); |
5336 DCHECK((value->IsUndefined() && GetBackPointer()->IsMap()) || | 5501 DCHECK((value->IsUndefined() && GetBackPointer()->IsMap()) || |
5337 (value->IsMap() && GetBackPointer()->IsUndefined())); | 5502 (value->IsMap() && GetBackPointer()->IsUndefined())); |
5338 DCHECK(!value->IsMap() || | 5503 DCHECK(!value->IsMap() || |
5339 Map::cast(value)->GetConstructor() == constructor_or_backpointer()); | 5504 Map::cast(value)->GetConstructor() == constructor_or_backpointer()); |
5340 set_constructor_or_backpointer(value, mode); | 5505 set_constructor_or_backpointer(value, mode); |
5341 } | 5506 } |
5342 | 5507 |
5343 | 5508 |
5344 ACCESSORS(Map, code_cache, Object, kCodeCacheOffset) | 5509 ACCESSORS(Map, code_cache, Object, kCodeCacheOffset) |
5345 ACCESSORS(Map, dependent_code, DependentCode, kDependentCodeOffset) | 5510 ACCESSORS(Map, dependent_code, DependentCode, kDependentCodeOffset) |
5346 ACCESSORS(Map, weak_cell_cache, Object, kWeakCellCacheOffset) | 5511 ACCESSORS(Map, weak_cell_cache, Object, kWeakCellCacheOffset) |
5347 ACCESSORS(Map, constructor_or_backpointer, Object, | 5512 ACCESSORS(Map, constructor_or_backpointer, Object, |
5348 kConstructorOrBackPointerOffset) | 5513 kConstructorOrBackPointerOffset) |
5349 | 5514 |
5350 | |
5351 Object* Map::GetConstructor() const { | 5515 Object* Map::GetConstructor() const { |
5352 Object* maybe_constructor = constructor_or_backpointer(); | 5516 Object* maybe_constructor = constructor_or_backpointer(); |
5353 // Follow any back pointers. | 5517 // Follow any back pointers. |
5354 while (maybe_constructor->IsMap()) { | 5518 while (maybe_constructor->IsMap()) { |
5355 maybe_constructor = | 5519 maybe_constructor = |
5356 Map::cast(maybe_constructor)->constructor_or_backpointer(); | 5520 Map::cast(maybe_constructor)->constructor_or_backpointer(); |
5357 } | 5521 } |
5358 return maybe_constructor; | 5522 return maybe_constructor; |
5359 } | 5523 } |
5360 | |
5361 | |
5362 void Map::SetConstructor(Object* constructor, WriteBarrierMode mode) { | 5524 void Map::SetConstructor(Object* constructor, WriteBarrierMode mode) { |
5363 // Never overwrite a back pointer with a constructor. | 5525 // Never overwrite a back pointer with a constructor. |
5364 DCHECK(!constructor_or_backpointer()->IsMap()); | 5526 DCHECK(!constructor_or_backpointer()->IsMap()); |
5365 set_constructor_or_backpointer(constructor, mode); | 5527 set_constructor_or_backpointer(constructor, mode); |
5366 } | 5528 } |
5367 | 5529 |
5368 | |
5369 ACCESSORS(JSFunction, shared, SharedFunctionInfo, kSharedFunctionInfoOffset) | 5530 ACCESSORS(JSFunction, shared, SharedFunctionInfo, kSharedFunctionInfoOffset) |
5370 ACCESSORS(JSFunction, literals_or_bindings, FixedArray, kLiteralsOffset) | 5531 ACCESSORS(JSFunction, literals_or_bindings, FixedArray, kLiteralsOffset) |
5371 ACCESSORS(JSFunction, next_function_link, Object, kNextFunctionLinkOffset) | 5532 ACCESSORS(JSFunction, next_function_link, Object, kNextFunctionLinkOffset) |
5372 | 5533 |
5373 ACCESSORS(GlobalObject, builtins, JSBuiltinsObject, kBuiltinsOffset) | 5534 ACCESSORS(GlobalObject, builtins, JSBuiltinsObject, kBuiltinsOffset) |
5374 ACCESSORS(GlobalObject, native_context, Context, kNativeContextOffset) | 5535 ACCESSORS(GlobalObject, native_context, Context, kNativeContextOffset) |
5375 ACCESSORS(GlobalObject, global_proxy, JSObject, kGlobalProxyOffset) | 5536 ACCESSORS(GlobalObject, global_proxy, JSObject, kGlobalProxyOffset) |
5376 | 5537 |
5377 ACCESSORS(JSGlobalProxy, native_context, Object, kNativeContextOffset) | 5538 ACCESSORS(JSGlobalProxy, native_context, Object, kNativeContextOffset) |
5378 ACCESSORS(JSGlobalProxy, hash, Object, kHashOffset) | 5539 ACCESSORS(JSGlobalProxy, hash, Object, kHashOffset) |
(...skipping 2090 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7469 #undef READ_SHORT_FIELD | 7630 #undef READ_SHORT_FIELD |
7470 #undef WRITE_SHORT_FIELD | 7631 #undef WRITE_SHORT_FIELD |
7471 #undef READ_BYTE_FIELD | 7632 #undef READ_BYTE_FIELD |
7472 #undef WRITE_BYTE_FIELD | 7633 #undef WRITE_BYTE_FIELD |
7473 #undef NOBARRIER_READ_BYTE_FIELD | 7634 #undef NOBARRIER_READ_BYTE_FIELD |
7474 #undef NOBARRIER_WRITE_BYTE_FIELD | 7635 #undef NOBARRIER_WRITE_BYTE_FIELD |
7475 | 7636 |
7476 } } // namespace v8::internal | 7637 } } // namespace v8::internal |
7477 | 7638 |
7478 #endif // V8_OBJECTS_INL_H_ | 7639 #endif // V8_OBJECTS_INL_H_ |
OLD | NEW |