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 | |
1915 ACCESSORS(Oddball, to_string, String, kToStringOffset) | 1880 ACCESSORS(Oddball, to_string, String, kToStringOffset) |
1916 ACCESSORS(Oddball, to_number, Object, kToNumberOffset) | 1881 ACCESSORS(Oddball, to_number, Object, kToNumberOffset) |
1917 | 1882 |
1918 | 1883 |
1919 byte Oddball::kind() const { | 1884 byte Oddball::kind() const { |
1920 return Smi::cast(READ_FIELD(this, kKindOffset))->value(); | 1885 return Smi::cast(READ_FIELD(this, kKindOffset))->value(); |
1921 } | 1886 } |
1922 | 1887 |
1923 | 1888 |
1924 void Oddball::set_kind(byte value) { | 1889 void Oddball::set_kind(byte value) { |
(...skipping 1105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3030 if (has_fast_smi_or_object_elements() || | 2995 if (has_fast_smi_or_object_elements() || |
3031 has_fast_double_elements()) { | 2996 has_fast_double_elements()) { |
3032 DCHECK(!GetHeap()->InNewSpace(GetHeap()->empty_fixed_array())); | 2997 DCHECK(!GetHeap()->InNewSpace(GetHeap()->empty_fixed_array())); |
3033 return GetHeap()->empty_fixed_array(); | 2998 return GetHeap()->empty_fixed_array(); |
3034 } else if (has_external_array_elements()) { | 2999 } else if (has_external_array_elements()) { |
3035 ExternalArray* empty_array = GetHeap()->EmptyExternalArrayForMap(this); | 3000 ExternalArray* empty_array = GetHeap()->EmptyExternalArrayForMap(this); |
3036 DCHECK(!GetHeap()->InNewSpace(empty_array)); | 3001 DCHECK(!GetHeap()->InNewSpace(empty_array)); |
3037 return empty_array; | 3002 return empty_array; |
3038 } else if (has_fixed_typed_array_elements()) { | 3003 } else if (has_fixed_typed_array_elements()) { |
3039 FixedTypedArrayBase* empty_array = | 3004 FixedTypedArrayBase* empty_array = |
3040 GetHeap()->EmptyFixedTypedArrayForMap(this); | 3005 GetHeap()->EmptyFixedTypedArrayForMap(this); |
3041 DCHECK(!GetHeap()->InNewSpace(empty_array)); | 3006 DCHECK(!GetHeap()->InNewSpace(empty_array)); |
3042 return empty_array; | 3007 return empty_array; |
3043 } else { | 3008 } else { |
3044 UNREACHABLE(); | 3009 UNREACHABLE(); |
3045 } | 3010 } |
3046 return NULL; | 3011 return NULL; |
3047 } | 3012 } |
3048 | 3013 |
3049 | 3014 |
3050 Object** DescriptorArray::GetKeySlot(int descriptor_number) { | 3015 Object** DescriptorArray::GetKeySlot(int descriptor_number) { |
(...skipping 2197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5248 } | 5213 } |
5249 | 5214 |
5250 | 5215 |
5251 void Map::set_prototype(Object* value, WriteBarrierMode mode) { | 5216 void Map::set_prototype(Object* value, WriteBarrierMode mode) { |
5252 DCHECK(value->IsNull() || value->IsJSReceiver()); | 5217 DCHECK(value->IsNull() || value->IsJSReceiver()); |
5253 WRITE_FIELD(this, kPrototypeOffset, value); | 5218 WRITE_FIELD(this, kPrototypeOffset, value); |
5254 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kPrototypeOffset, value, mode); | 5219 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kPrototypeOffset, value, mode); |
5255 } | 5220 } |
5256 | 5221 |
5257 | 5222 |
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 | |
5274 LayoutDescriptor* Map::layout_descriptor_gc_safe() { | 5223 LayoutDescriptor* Map::layout_descriptor_gc_safe() { |
5275 Object* layout_desc = READ_FIELD(this, kLayoutDecriptorOffset); | 5224 Object* layout_desc = READ_FIELD(this, kLayoutDecriptorOffset); |
5276 return LayoutDescriptor::cast_gc_safe(layout_desc); | 5225 return LayoutDescriptor::cast_gc_safe(layout_desc); |
5277 } | 5226 } |
5278 | 5227 |
5279 | 5228 |
5280 bool Map::HasFastPointerLayout() const { | 5229 bool Map::HasFastPointerLayout() const { |
5281 Object* layout_desc = READ_FIELD(this, kLayoutDecriptorOffset); | 5230 Object* layout_desc = READ_FIELD(this, kLayoutDecriptorOffset); |
5282 return LayoutDescriptor::IsFastPointerLayout(layout_desc); | 5231 return LayoutDescriptor::IsFastPointerLayout(layout_desc); |
5283 } | 5232 } |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5366 | 5315 |
5367 Object* Map::GetBackPointer() { | 5316 Object* Map::GetBackPointer() { |
5368 Object* object = constructor_or_backpointer(); | 5317 Object* object = constructor_or_backpointer(); |
5369 if (object->IsMap()) { | 5318 if (object->IsMap()) { |
5370 return object; | 5319 return object; |
5371 } | 5320 } |
5372 return GetIsolate()->heap()->undefined_value(); | 5321 return GetIsolate()->heap()->undefined_value(); |
5373 } | 5322 } |
5374 | 5323 |
5375 | 5324 |
5376 bool Map::HasElementsTransition() { | 5325 Map* Map::ElementsTransitionMap() { |
5377 return HasTransitionArray() && transitions()->HasElementsTransition(); | 5326 return TransitionArray::SearchSpecial( |
| 5327 this, GetHeap()->elements_transition_symbol()); |
5378 } | 5328 } |
5379 | 5329 |
5380 | 5330 |
5381 bool Map::HasTransitionArray() const { | 5331 ACCESSORS(Map, raw_transitions, Object, kTransitionsOffset); |
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 } | |
5497 | 5332 |
5498 | 5333 |
5499 void Map::SetBackPointer(Object* value, WriteBarrierMode mode) { | 5334 void Map::SetBackPointer(Object* value, WriteBarrierMode mode) { |
5500 DCHECK(instance_type() >= FIRST_JS_RECEIVER_TYPE); | 5335 DCHECK(instance_type() >= FIRST_JS_RECEIVER_TYPE); |
5501 DCHECK((value->IsUndefined() && GetBackPointer()->IsMap()) || | 5336 DCHECK((value->IsUndefined() && GetBackPointer()->IsMap()) || |
5502 (value->IsMap() && GetBackPointer()->IsUndefined())); | 5337 (value->IsMap() && GetBackPointer()->IsUndefined())); |
5503 DCHECK(!value->IsMap() || | 5338 DCHECK(!value->IsMap() || |
5504 Map::cast(value)->GetConstructor() == constructor_or_backpointer()); | 5339 Map::cast(value)->GetConstructor() == constructor_or_backpointer()); |
5505 set_constructor_or_backpointer(value, mode); | 5340 set_constructor_or_backpointer(value, mode); |
5506 } | 5341 } |
5507 | 5342 |
5508 | 5343 |
5509 ACCESSORS(Map, code_cache, Object, kCodeCacheOffset) | 5344 ACCESSORS(Map, code_cache, Object, kCodeCacheOffset) |
5510 ACCESSORS(Map, dependent_code, DependentCode, kDependentCodeOffset) | 5345 ACCESSORS(Map, dependent_code, DependentCode, kDependentCodeOffset) |
5511 ACCESSORS(Map, weak_cell_cache, Object, kWeakCellCacheOffset) | 5346 ACCESSORS(Map, weak_cell_cache, Object, kWeakCellCacheOffset) |
5512 ACCESSORS(Map, constructor_or_backpointer, Object, | 5347 ACCESSORS(Map, constructor_or_backpointer, Object, |
5513 kConstructorOrBackPointerOffset) | 5348 kConstructorOrBackPointerOffset) |
5514 | 5349 |
| 5350 |
5515 Object* Map::GetConstructor() const { | 5351 Object* Map::GetConstructor() const { |
5516 Object* maybe_constructor = constructor_or_backpointer(); | 5352 Object* maybe_constructor = constructor_or_backpointer(); |
5517 // Follow any back pointers. | 5353 // Follow any back pointers. |
5518 while (maybe_constructor->IsMap()) { | 5354 while (maybe_constructor->IsMap()) { |
5519 maybe_constructor = | 5355 maybe_constructor = |
5520 Map::cast(maybe_constructor)->constructor_or_backpointer(); | 5356 Map::cast(maybe_constructor)->constructor_or_backpointer(); |
5521 } | 5357 } |
5522 return maybe_constructor; | 5358 return maybe_constructor; |
5523 } | 5359 } |
| 5360 |
| 5361 |
5524 void Map::SetConstructor(Object* constructor, WriteBarrierMode mode) { | 5362 void Map::SetConstructor(Object* constructor, WriteBarrierMode mode) { |
5525 // Never overwrite a back pointer with a constructor. | 5363 // Never overwrite a back pointer with a constructor. |
5526 DCHECK(!constructor_or_backpointer()->IsMap()); | 5364 DCHECK(!constructor_or_backpointer()->IsMap()); |
5527 set_constructor_or_backpointer(constructor, mode); | 5365 set_constructor_or_backpointer(constructor, mode); |
5528 } | 5366 } |
5529 | 5367 |
| 5368 |
5530 ACCESSORS(JSFunction, shared, SharedFunctionInfo, kSharedFunctionInfoOffset) | 5369 ACCESSORS(JSFunction, shared, SharedFunctionInfo, kSharedFunctionInfoOffset) |
5531 ACCESSORS(JSFunction, literals_or_bindings, FixedArray, kLiteralsOffset) | 5370 ACCESSORS(JSFunction, literals_or_bindings, FixedArray, kLiteralsOffset) |
5532 ACCESSORS(JSFunction, next_function_link, Object, kNextFunctionLinkOffset) | 5371 ACCESSORS(JSFunction, next_function_link, Object, kNextFunctionLinkOffset) |
5533 | 5372 |
5534 ACCESSORS(GlobalObject, builtins, JSBuiltinsObject, kBuiltinsOffset) | 5373 ACCESSORS(GlobalObject, builtins, JSBuiltinsObject, kBuiltinsOffset) |
5535 ACCESSORS(GlobalObject, native_context, Context, kNativeContextOffset) | 5374 ACCESSORS(GlobalObject, native_context, Context, kNativeContextOffset) |
5536 ACCESSORS(GlobalObject, global_proxy, JSObject, kGlobalProxyOffset) | 5375 ACCESSORS(GlobalObject, global_proxy, JSObject, kGlobalProxyOffset) |
5537 | 5376 |
5538 ACCESSORS(JSGlobalProxy, native_context, Object, kNativeContextOffset) | 5377 ACCESSORS(JSGlobalProxy, native_context, Object, kNativeContextOffset) |
5539 ACCESSORS(JSGlobalProxy, hash, Object, kHashOffset) | 5378 ACCESSORS(JSGlobalProxy, hash, Object, kHashOffset) |
(...skipping 2090 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7630 #undef READ_SHORT_FIELD | 7469 #undef READ_SHORT_FIELD |
7631 #undef WRITE_SHORT_FIELD | 7470 #undef WRITE_SHORT_FIELD |
7632 #undef READ_BYTE_FIELD | 7471 #undef READ_BYTE_FIELD |
7633 #undef WRITE_BYTE_FIELD | 7472 #undef WRITE_BYTE_FIELD |
7634 #undef NOBARRIER_READ_BYTE_FIELD | 7473 #undef NOBARRIER_READ_BYTE_FIELD |
7635 #undef NOBARRIER_WRITE_BYTE_FIELD | 7474 #undef NOBARRIER_WRITE_BYTE_FIELD |
7636 | 7475 |
7637 } } // namespace v8::internal | 7476 } } // namespace v8::internal |
7638 | 7477 |
7639 #endif // V8_OBJECTS_INL_H_ | 7478 #endif // V8_OBJECTS_INL_H_ |
OLD | NEW |