OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 1279 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1290 | 1290 |
1291 ACCESSORS(JSObject, properties, FixedArray, kPropertiesOffset) | 1291 ACCESSORS(JSObject, properties, FixedArray, kPropertiesOffset) |
1292 | 1292 |
1293 | 1293 |
1294 FixedArrayBase* JSObject::elements() { | 1294 FixedArrayBase* JSObject::elements() { |
1295 Object* array = READ_FIELD(this, kElementsOffset); | 1295 Object* array = READ_FIELD(this, kElementsOffset); |
1296 ASSERT(array->HasValidElements()); | 1296 ASSERT(array->HasValidElements()); |
1297 return static_cast<FixedArrayBase*>(array); | 1297 return static_cast<FixedArrayBase*>(array); |
1298 } | 1298 } |
1299 | 1299 |
| 1300 void JSObject::ValidateSmiOnlyElements() { |
| 1301 #if DEBUG |
| 1302 if (FLAG_smi_only_arrays && |
| 1303 map()->elements_kind() == FAST_SMI_ONLY_ELEMENTS) { |
| 1304 Heap* heap = GetHeap(); |
| 1305 // Don't use elements, since integrity checks will fail if there |
| 1306 // are filler pointers in the array. |
| 1307 FixedArray* fixed_array = |
| 1308 reinterpret_cast<FixedArray*>(READ_FIELD(this, kElementsOffset)); |
| 1309 Map* map = fixed_array->map(); |
| 1310 // Arrays that have been shifted in place can't be verified. |
| 1311 if (map != heap->raw_unchecked_one_pointer_filler_map() && |
| 1312 map != heap->raw_unchecked_two_pointer_filler_map() && |
| 1313 map != heap->free_space_map()) { |
| 1314 for (int i = 0; i < fixed_array->length(); i++) { |
| 1315 Object* current = fixed_array->get(i); |
| 1316 ASSERT(current->IsSmi() || current == heap->the_hole_value()); |
| 1317 } |
| 1318 } |
| 1319 } |
| 1320 #endif |
| 1321 } |
| 1322 |
| 1323 |
| 1324 MaybeObject* JSObject::EnsureCanContainNonSmiElements() { |
| 1325 #if DEBUG |
| 1326 ValidateSmiOnlyElements(); |
| 1327 #endif |
| 1328 if (FLAG_smi_only_arrays && |
| 1329 (map()->elements_kind() == FAST_SMI_ONLY_ELEMENTS)) { |
| 1330 Object* obj; |
| 1331 MaybeObject* maybe_obj = GetElementsTransitionMap(FAST_ELEMENTS); |
| 1332 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 1333 set_map(Map::cast(obj)); |
| 1334 } |
| 1335 return this; |
| 1336 } |
| 1337 |
| 1338 |
| 1339 MaybeObject* JSObject::EnsureCanContainElements(Object** objects, |
| 1340 uint32_t count) { |
| 1341 if (FLAG_smi_only_arrays && |
| 1342 map()->elements_kind() == FAST_SMI_ONLY_ELEMENTS) { |
| 1343 for (uint32_t i = 0; i < count; ++i) { |
| 1344 Object* current = *objects++; |
| 1345 if (!current->IsSmi() && current != GetHeap()->the_hole_value()) { |
| 1346 return EnsureCanContainNonSmiElements(); |
| 1347 } |
| 1348 } |
| 1349 } |
| 1350 return this; |
| 1351 } |
| 1352 |
| 1353 |
| 1354 MaybeObject* JSObject::EnsureCanContainElements(FixedArray* elements) { |
| 1355 if (FLAG_smi_only_arrays) { |
| 1356 Object** objects = reinterpret_cast<Object**>( |
| 1357 FIELD_ADDR(elements, elements->OffsetOfElementAt(0))); |
| 1358 return EnsureCanContainElements(objects, elements->length()); |
| 1359 } else { |
| 1360 return this; |
| 1361 } |
| 1362 } |
| 1363 |
1300 | 1364 |
1301 void JSObject::set_elements(FixedArrayBase* value, WriteBarrierMode mode) { | 1365 void JSObject::set_elements(FixedArrayBase* value, WriteBarrierMode mode) { |
1302 ASSERT(map()->has_fast_elements() == | 1366 ASSERT((map()->has_fast_elements() || |
| 1367 map()->has_fast_smi_only_elements()) == |
1303 (value->map() == GetHeap()->fixed_array_map() || | 1368 (value->map() == GetHeap()->fixed_array_map() || |
1304 value->map() == GetHeap()->fixed_cow_array_map())); | 1369 value->map() == GetHeap()->fixed_cow_array_map())); |
1305 ASSERT(map()->has_fast_double_elements() == | 1370 ASSERT(map()->has_fast_double_elements() == |
1306 value->IsFixedDoubleArray()); | 1371 value->IsFixedDoubleArray()); |
1307 ASSERT(value->HasValidElements()); | 1372 ASSERT(value->HasValidElements()); |
| 1373 #ifdef DEBUG |
| 1374 ValidateSmiOnlyElements(); |
| 1375 #endif |
1308 WRITE_FIELD(this, kElementsOffset, value); | 1376 WRITE_FIELD(this, kElementsOffset, value); |
1309 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kElementsOffset, value, mode); | 1377 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kElementsOffset, value, mode); |
1310 } | 1378 } |
1311 | 1379 |
1312 | 1380 |
1313 void JSObject::initialize_properties() { | 1381 void JSObject::initialize_properties() { |
1314 ASSERT(!GetHeap()->InNewSpace(GetHeap()->empty_fixed_array())); | 1382 ASSERT(!GetHeap()->InNewSpace(GetHeap()->empty_fixed_array())); |
1315 WRITE_FIELD(this, kPropertiesOffset, GetHeap()->empty_fixed_array()); | 1383 WRITE_FIELD(this, kPropertiesOffset, GetHeap()->empty_fixed_array()); |
1316 } | 1384 } |
1317 | 1385 |
1318 | 1386 |
1319 void JSObject::initialize_elements() { | 1387 void JSObject::initialize_elements() { |
1320 ASSERT(map()->has_fast_elements()); | 1388 ASSERT(map()->has_fast_elements() || map()->has_fast_smi_only_elements()); |
1321 ASSERT(!GetHeap()->InNewSpace(GetHeap()->empty_fixed_array())); | 1389 ASSERT(!GetHeap()->InNewSpace(GetHeap()->empty_fixed_array())); |
1322 WRITE_FIELD(this, kElementsOffset, GetHeap()->empty_fixed_array()); | 1390 WRITE_FIELD(this, kElementsOffset, GetHeap()->empty_fixed_array()); |
1323 } | 1391 } |
1324 | 1392 |
1325 | 1393 |
1326 MaybeObject* JSObject::ResetElements() { | 1394 MaybeObject* JSObject::ResetElements() { |
1327 Object* obj; | 1395 Object* obj; |
1328 { MaybeObject* maybe_obj = GetElementsTransitionMap(FAST_ELEMENTS); | 1396 ElementsKind elements_kind = FLAG_smi_only_arrays |
1329 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 1397 ? FAST_SMI_ONLY_ELEMENTS |
1330 } | 1398 : FAST_ELEMENTS; |
| 1399 MaybeObject* maybe_obj = GetElementsTransitionMap(elements_kind); |
| 1400 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
1331 set_map(Map::cast(obj)); | 1401 set_map(Map::cast(obj)); |
1332 initialize_elements(); | 1402 initialize_elements(); |
1333 return this; | 1403 return this; |
1334 } | 1404 } |
1335 | 1405 |
1336 | 1406 |
1337 ACCESSORS(Oddball, to_string, String, kToStringOffset) | 1407 ACCESSORS(Oddball, to_string, String, kToStringOffset) |
1338 ACCESSORS(Oddball, to_number, Object, kToNumberOffset) | 1408 ACCESSORS(Oddball, to_number, Object, kToNumberOffset) |
1339 | 1409 |
1340 | 1410 |
(...skipping 335 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1676 int offset = kHeaderSize + old_length * kDoubleSize; | 1746 int offset = kHeaderSize + old_length * kDoubleSize; |
1677 for (int current = from->length(); current < length(); ++current) { | 1747 for (int current = from->length(); current < length(); ++current) { |
1678 WRITE_DOUBLE_FIELD(this, offset, hole_nan_as_double()); | 1748 WRITE_DOUBLE_FIELD(this, offset, hole_nan_as_double()); |
1679 offset += kDoubleSize; | 1749 offset += kDoubleSize; |
1680 } | 1750 } |
1681 } | 1751 } |
1682 | 1752 |
1683 | 1753 |
1684 void FixedDoubleArray::Initialize(FixedArray* from) { | 1754 void FixedDoubleArray::Initialize(FixedArray* from) { |
1685 int old_length = from->length(); | 1755 int old_length = from->length(); |
1686 ASSERT(old_length < length()); | 1756 ASSERT(old_length <= length()); |
1687 for (int i = 0; i < old_length; i++) { | 1757 for (int i = 0; i < old_length; i++) { |
1688 Object* hole_or_object = from->get(i); | 1758 Object* hole_or_object = from->get(i); |
1689 if (hole_or_object->IsTheHole()) { | 1759 if (hole_or_object->IsTheHole()) { |
1690 set_the_hole(i); | 1760 set_the_hole(i); |
1691 } else { | 1761 } else { |
1692 set(i, hole_or_object->Number()); | 1762 set(i, hole_or_object->Number()); |
1693 } | 1763 } |
1694 } | 1764 } |
1695 int offset = kHeaderSize + old_length * kDoubleSize; | 1765 int offset = kHeaderSize + old_length * kDoubleSize; |
1696 for (int current = from->length(); current < length(); ++current) { | 1766 for (int current = from->length(); current < length(); ++current) { |
(...skipping 2248 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3945 fa->set_unchecked(index, Smi::cast(value)); | 4015 fa->set_unchecked(index, Smi::cast(value)); |
3946 } else { | 4016 } else { |
3947 // We only do this during GC, so we don't need to notify the write barrier. | 4017 // We only do this during GC, so we don't need to notify the write barrier. |
3948 fa->set_unchecked(heap, index, value, SKIP_WRITE_BARRIER); | 4018 fa->set_unchecked(heap, index, value, SKIP_WRITE_BARRIER); |
3949 } | 4019 } |
3950 } | 4020 } |
3951 | 4021 |
3952 | 4022 |
3953 ElementsKind JSObject::GetElementsKind() { | 4023 ElementsKind JSObject::GetElementsKind() { |
3954 ElementsKind kind = map()->elements_kind(); | 4024 ElementsKind kind = map()->elements_kind(); |
3955 ASSERT((kind == FAST_ELEMENTS && | 4025 #if DEBUG |
3956 (elements()->map() == GetHeap()->fixed_array_map() || | 4026 FixedArrayBase* fixed_array = |
3957 elements()->map() == GetHeap()->fixed_cow_array_map())) || | 4027 reinterpret_cast<FixedArrayBase*>(READ_FIELD(this, kElementsOffset)); |
| 4028 Map* map = fixed_array->map(); |
| 4029 ASSERT(((kind == FAST_ELEMENTS || kind == FAST_SMI_ONLY_ELEMENTS) && |
| 4030 (map == GetHeap()->fixed_array_map() || |
| 4031 map == GetHeap()->fixed_cow_array_map())) || |
3958 (kind == FAST_DOUBLE_ELEMENTS && | 4032 (kind == FAST_DOUBLE_ELEMENTS && |
3959 elements()->IsFixedDoubleArray()) || | 4033 fixed_array->IsFixedDoubleArray()) || |
3960 (kind == DICTIONARY_ELEMENTS && | 4034 (kind == DICTIONARY_ELEMENTS && |
3961 elements()->IsFixedArray() && | 4035 fixed_array->IsFixedArray() && |
3962 elements()->IsDictionary()) || | 4036 fixed_array->IsDictionary()) || |
3963 (kind > DICTIONARY_ELEMENTS)); | 4037 (kind > DICTIONARY_ELEMENTS)); |
| 4038 #endif |
3964 return kind; | 4039 return kind; |
3965 } | 4040 } |
3966 | 4041 |
3967 | 4042 |
3968 ElementsAccessor* JSObject::GetElementsAccessor() { | 4043 ElementsAccessor* JSObject::GetElementsAccessor() { |
3969 return ElementsAccessor::ForKind(GetElementsKind()); | 4044 return ElementsAccessor::ForKind(GetElementsKind()); |
3970 } | 4045 } |
3971 | 4046 |
3972 | 4047 |
3973 bool JSObject::HasFastElements() { | 4048 bool JSObject::HasFastElements() { |
3974 return GetElementsKind() == FAST_ELEMENTS; | 4049 return GetElementsKind() == FAST_ELEMENTS; |
3975 } | 4050 } |
3976 | 4051 |
3977 | 4052 |
| 4053 bool JSObject::HasFastSmiOnlyElements() { |
| 4054 return GetElementsKind() == FAST_SMI_ONLY_ELEMENTS; |
| 4055 } |
| 4056 |
| 4057 |
| 4058 bool JSObject::HasFastTypeElements() { |
| 4059 ElementsKind elements_kind = GetElementsKind(); |
| 4060 return elements_kind == FAST_SMI_ONLY_ELEMENTS || |
| 4061 elements_kind == FAST_ELEMENTS; |
| 4062 } |
| 4063 |
| 4064 |
3978 bool JSObject::HasFastDoubleElements() { | 4065 bool JSObject::HasFastDoubleElements() { |
3979 return GetElementsKind() == FAST_DOUBLE_ELEMENTS; | 4066 return GetElementsKind() == FAST_DOUBLE_ELEMENTS; |
3980 } | 4067 } |
3981 | 4068 |
3982 | 4069 |
3983 bool JSObject::HasDictionaryElements() { | 4070 bool JSObject::HasDictionaryElements() { |
3984 return GetElementsKind() == DICTIONARY_ELEMENTS; | 4071 return GetElementsKind() == DICTIONARY_ELEMENTS; |
3985 } | 4072 } |
3986 | 4073 |
3987 | 4074 |
| 4075 bool JSObject::HasNonStrictArgumentsElements() { |
| 4076 return GetElementsKind() == NON_STRICT_ARGUMENTS_ELEMENTS; |
| 4077 } |
| 4078 |
| 4079 |
3988 bool JSObject::HasExternalArrayElements() { | 4080 bool JSObject::HasExternalArrayElements() { |
3989 HeapObject* array = elements(); | 4081 HeapObject* array = elements(); |
3990 ASSERT(array != NULL); | 4082 ASSERT(array != NULL); |
3991 return array->IsExternalArray(); | 4083 return array->IsExternalArray(); |
3992 } | 4084 } |
3993 | 4085 |
3994 | 4086 |
3995 #define EXTERNAL_ELEMENTS_CHECK(name, type) \ | 4087 #define EXTERNAL_ELEMENTS_CHECK(name, type) \ |
3996 bool JSObject::HasExternal##name##Elements() { \ | 4088 bool JSObject::HasExternal##name##Elements() { \ |
3997 HeapObject* array = elements(); \ | 4089 HeapObject* array = elements(); \ |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4029 | 4121 |
4030 bool JSObject::AllowsSetElementsLength() { | 4122 bool JSObject::AllowsSetElementsLength() { |
4031 bool result = elements()->IsFixedArray() || | 4123 bool result = elements()->IsFixedArray() || |
4032 elements()->IsFixedDoubleArray(); | 4124 elements()->IsFixedDoubleArray(); |
4033 ASSERT(result == !HasExternalArrayElements()); | 4125 ASSERT(result == !HasExternalArrayElements()); |
4034 return result; | 4126 return result; |
4035 } | 4127 } |
4036 | 4128 |
4037 | 4129 |
4038 MaybeObject* JSObject::EnsureWritableFastElements() { | 4130 MaybeObject* JSObject::EnsureWritableFastElements() { |
4039 ASSERT(HasFastElements()); | 4131 ASSERT(HasFastTypeElements()); |
4040 FixedArray* elems = FixedArray::cast(elements()); | 4132 FixedArray* elems = FixedArray::cast(elements()); |
4041 Isolate* isolate = GetIsolate(); | 4133 Isolate* isolate = GetIsolate(); |
4042 if (elems->map() != isolate->heap()->fixed_cow_array_map()) return elems; | 4134 if (elems->map() != isolate->heap()->fixed_cow_array_map()) return elems; |
4043 Object* writable_elems; | 4135 Object* writable_elems; |
4044 { MaybeObject* maybe_writable_elems = isolate->heap()->CopyFixedArrayWithMap( | 4136 { MaybeObject* maybe_writable_elems = isolate->heap()->CopyFixedArrayWithMap( |
4045 elems, isolate->heap()->fixed_array_map()); | 4137 elems, isolate->heap()->fixed_array_map()); |
4046 if (!maybe_writable_elems->ToObject(&writable_elems)) { | 4138 if (!maybe_writable_elems->ToObject(&writable_elems)) { |
4047 return maybe_writable_elems; | 4139 return maybe_writable_elems; |
4048 } | 4140 } |
4049 } | 4141 } |
(...skipping 344 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4394 void Map::ClearCodeCache(Heap* heap) { | 4486 void Map::ClearCodeCache(Heap* heap) { |
4395 // No write barrier is needed since empty_fixed_array is not in new space. | 4487 // No write barrier is needed since empty_fixed_array is not in new space. |
4396 // Please note this function is used during marking: | 4488 // Please note this function is used during marking: |
4397 // - MarkCompactCollector::MarkUnmarkedObject | 4489 // - MarkCompactCollector::MarkUnmarkedObject |
4398 ASSERT(!heap->InNewSpace(heap->raw_unchecked_empty_fixed_array())); | 4490 ASSERT(!heap->InNewSpace(heap->raw_unchecked_empty_fixed_array())); |
4399 WRITE_FIELD(this, kCodeCacheOffset, heap->raw_unchecked_empty_fixed_array()); | 4491 WRITE_FIELD(this, kCodeCacheOffset, heap->raw_unchecked_empty_fixed_array()); |
4400 } | 4492 } |
4401 | 4493 |
4402 | 4494 |
4403 void JSArray::EnsureSize(int required_size) { | 4495 void JSArray::EnsureSize(int required_size) { |
4404 ASSERT(HasFastElements()); | 4496 ASSERT(HasFastTypeElements()); |
4405 FixedArray* elts = FixedArray::cast(elements()); | 4497 FixedArray* elts = FixedArray::cast(elements()); |
4406 const int kArraySizeThatFitsComfortablyInNewSpace = 128; | 4498 const int kArraySizeThatFitsComfortablyInNewSpace = 128; |
4407 if (elts->length() < required_size) { | 4499 if (elts->length() < required_size) { |
4408 // Doubling in size would be overkill, but leave some slack to avoid | 4500 // Doubling in size would be overkill, but leave some slack to avoid |
4409 // constantly growing. | 4501 // constantly growing. |
4410 Expand(required_size + (required_size >> 3)); | 4502 Expand(required_size + (required_size >> 3)); |
4411 // It's a performance benefit to keep a frequently used array in new-space. | 4503 // It's a performance benefit to keep a frequently used array in new-space. |
4412 } else if (!GetHeap()->new_space()->Contains(elts) && | 4504 } else if (!GetHeap()->new_space()->Contains(elts) && |
4413 required_size < kArraySizeThatFitsComfortablyInNewSpace) { | 4505 required_size < kArraySizeThatFitsComfortablyInNewSpace) { |
4414 // Expand will allocate a new backing store in new space even if the size | 4506 // Expand will allocate a new backing store in new space even if the size |
4415 // we asked for isn't larger than what we had before. | 4507 // we asked for isn't larger than what we had before. |
4416 Expand(required_size); | 4508 Expand(required_size); |
4417 } | 4509 } |
4418 } | 4510 } |
4419 | 4511 |
4420 | 4512 |
4421 void JSArray::set_length(Smi* length) { | 4513 void JSArray::set_length(Smi* length) { |
4422 // Don't need a write barrier for a Smi. | 4514 // Don't need a write barrier for a Smi. |
4423 set_length(static_cast<Object*>(length), SKIP_WRITE_BARRIER); | 4515 set_length(static_cast<Object*>(length), SKIP_WRITE_BARRIER); |
4424 } | 4516 } |
4425 | 4517 |
4426 | 4518 |
4427 void JSArray::SetContent(FixedArray* storage) { | 4519 MaybeObject* JSArray::SetContent(FixedArray* storage) { |
| 4520 MaybeObject* maybe_object = EnsureCanContainElements(storage); |
| 4521 if (maybe_object->IsFailure()) return maybe_object; |
4428 set_length(Smi::FromInt(storage->length())); | 4522 set_length(Smi::FromInt(storage->length())); |
4429 set_elements(storage); | 4523 set_elements(storage); |
| 4524 return this; |
4430 } | 4525 } |
4431 | 4526 |
4432 | 4527 |
4433 MaybeObject* FixedArray::Copy() { | 4528 MaybeObject* FixedArray::Copy() { |
4434 if (length() == 0) return this; | 4529 if (length() == 0) return this; |
4435 return GetHeap()->CopyFixedArray(this); | 4530 return GetHeap()->CopyFixedArray(this); |
4436 } | 4531 } |
4437 | 4532 |
4438 | 4533 |
4439 Relocatable::Relocatable(Isolate* isolate) { | 4534 Relocatable::Relocatable(Isolate* isolate) { |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4536 #undef WRITE_INT_FIELD | 4631 #undef WRITE_INT_FIELD |
4537 #undef READ_SHORT_FIELD | 4632 #undef READ_SHORT_FIELD |
4538 #undef WRITE_SHORT_FIELD | 4633 #undef WRITE_SHORT_FIELD |
4539 #undef READ_BYTE_FIELD | 4634 #undef READ_BYTE_FIELD |
4540 #undef WRITE_BYTE_FIELD | 4635 #undef WRITE_BYTE_FIELD |
4541 | 4636 |
4542 | 4637 |
4543 } } // namespace v8::internal | 4638 } } // namespace v8::internal |
4544 | 4639 |
4545 #endif // V8_OBJECTS_INL_H_ | 4640 #endif // V8_OBJECTS_INL_H_ |
OLD | NEW |