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