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 739 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
750 if (Symbol::cast(this)->is_private()) return true; | 750 if (Symbol::cast(this)->is_private()) return true; |
751 } else { | 751 } else { |
752 if (filter & SKIP_STRINGS) return true; | 752 if (filter & SKIP_STRINGS) return true; |
753 } | 753 } |
754 return false; | 754 return false; |
755 } | 755 } |
756 | 756 |
757 Handle<Object> Object::NewStorageFor(Isolate* isolate, Handle<Object> object, | 757 Handle<Object> Object::NewStorageFor(Isolate* isolate, Handle<Object> object, |
758 Representation representation) { | 758 Representation representation) { |
759 if (!representation.IsDouble()) return object; | 759 if (!representation.IsDouble()) return object; |
760 double value; | 760 Handle<HeapNumber> result = isolate->factory()->NewHeapNumber(MUTABLE); |
761 if (object->IsUninitialized(isolate)) { | 761 if (object->IsUninitialized(isolate)) { |
762 value = bit_cast<double>(kHoleNanInt64); | 762 result->set_value_as_bits(kHoleNanInt64); |
763 } else if (object->IsMutableHeapNumber()) { | 763 } else if (object->IsMutableHeapNumber()) { |
764 value = HeapNumber::cast(*object)->value(); | 764 // Ensure that all bits of the double value are preserved. |
| 765 result->set_value_as_bits(HeapNumber::cast(*object)->value_as_bits()); |
765 } else { | 766 } else { |
766 value = object->Number(); | 767 result->set_value(object->Number()); |
767 } | 768 } |
768 return isolate->factory()->NewHeapNumber(value, MUTABLE); | 769 return result; |
769 } | 770 } |
770 | 771 |
771 Handle<Object> Object::WrapForRead(Isolate* isolate, Handle<Object> object, | 772 Handle<Object> Object::WrapForRead(Isolate* isolate, Handle<Object> object, |
772 Representation representation) { | 773 Representation representation) { |
773 DCHECK(!object->IsUninitialized(isolate)); | 774 DCHECK(!object->IsUninitialized(isolate)); |
774 if (!representation.IsDouble()) { | 775 if (!representation.IsDouble()) { |
775 DCHECK(object->FitsRepresentation(representation)); | 776 DCHECK(object->FitsRepresentation(representation)); |
776 return object; | 777 return object; |
777 } | 778 } |
778 return isolate->factory()->NewHeapNumber(HeapNumber::cast(*object)->value()); | 779 return isolate->factory()->NewHeapNumber(HeapNumber::cast(*object)->value()); |
(...skipping 771 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1550 | 1551 |
1551 double HeapNumber::value() const { | 1552 double HeapNumber::value() const { |
1552 return READ_DOUBLE_FIELD(this, kValueOffset); | 1553 return READ_DOUBLE_FIELD(this, kValueOffset); |
1553 } | 1554 } |
1554 | 1555 |
1555 | 1556 |
1556 void HeapNumber::set_value(double value) { | 1557 void HeapNumber::set_value(double value) { |
1557 WRITE_DOUBLE_FIELD(this, kValueOffset, value); | 1558 WRITE_DOUBLE_FIELD(this, kValueOffset, value); |
1558 } | 1559 } |
1559 | 1560 |
| 1561 uint64_t HeapNumber::value_as_bits() const { |
| 1562 return READ_UINT64_FIELD(this, kValueOffset); |
| 1563 } |
| 1564 |
| 1565 void HeapNumber::set_value_as_bits(uint64_t bits) { |
| 1566 WRITE_UINT64_FIELD(this, kValueOffset, bits); |
| 1567 } |
1560 | 1568 |
1561 int HeapNumber::get_exponent() { | 1569 int HeapNumber::get_exponent() { |
1562 return ((READ_INT_FIELD(this, kExponentOffset) & kExponentMask) >> | 1570 return ((READ_INT_FIELD(this, kExponentOffset) & kExponentMask) >> |
1563 kExponentShift) - kExponentBias; | 1571 kExponentShift) - kExponentBias; |
1564 } | 1572 } |
1565 | 1573 |
1566 | 1574 |
1567 int HeapNumber::get_sign() { | 1575 int HeapNumber::get_sign() { |
1568 return READ_INT_FIELD(this, kExponentOffset) & kSignMask; | 1576 return READ_INT_FIELD(this, kExponentOffset) & kSignMask; |
1569 } | 1577 } |
(...skipping 731 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2301 return properties()->get(index.outobject_array_index()); | 2309 return properties()->get(index.outobject_array_index()); |
2302 } | 2310 } |
2303 } | 2311 } |
2304 | 2312 |
2305 | 2313 |
2306 double JSObject::RawFastDoublePropertyAt(FieldIndex index) { | 2314 double JSObject::RawFastDoublePropertyAt(FieldIndex index) { |
2307 DCHECK(IsUnboxedDoubleField(index)); | 2315 DCHECK(IsUnboxedDoubleField(index)); |
2308 return READ_DOUBLE_FIELD(this, index.offset()); | 2316 return READ_DOUBLE_FIELD(this, index.offset()); |
2309 } | 2317 } |
2310 | 2318 |
| 2319 uint64_t JSObject::RawFastDoublePropertyAsBitsAt(FieldIndex index) { |
| 2320 DCHECK(IsUnboxedDoubleField(index)); |
| 2321 return READ_UINT64_FIELD(this, index.offset()); |
| 2322 } |
2311 | 2323 |
2312 void JSObject::RawFastPropertyAtPut(FieldIndex index, Object* value) { | 2324 void JSObject::RawFastPropertyAtPut(FieldIndex index, Object* value) { |
2313 if (index.is_inobject()) { | 2325 if (index.is_inobject()) { |
2314 int offset = index.offset(); | 2326 int offset = index.offset(); |
2315 WRITE_FIELD(this, offset, value); | 2327 WRITE_FIELD(this, offset, value); |
2316 WRITE_BARRIER(GetHeap(), this, offset, value); | 2328 WRITE_BARRIER(GetHeap(), this, offset, value); |
2317 } else { | 2329 } else { |
2318 properties()->set(index.outobject_array_index(), value); | 2330 properties()->set(index.outobject_array_index(), value); |
2319 } | 2331 } |
2320 } | 2332 } |
2321 | 2333 |
2322 | 2334 void JSObject::RawFastDoublePropertyAsBitsAtPut(FieldIndex index, |
2323 void JSObject::RawFastDoublePropertyAtPut(FieldIndex index, double value) { | 2335 uint64_t bits) { |
2324 WRITE_DOUBLE_FIELD(this, index.offset(), value); | 2336 WRITE_UINT64_FIELD(this, index.offset(), bits); |
2325 } | 2337 } |
2326 | 2338 |
2327 | |
2328 void JSObject::FastPropertyAtPut(FieldIndex index, Object* value) { | 2339 void JSObject::FastPropertyAtPut(FieldIndex index, Object* value) { |
2329 if (IsUnboxedDoubleField(index)) { | 2340 if (IsUnboxedDoubleField(index)) { |
2330 DCHECK(value->IsMutableHeapNumber()); | 2341 DCHECK(value->IsMutableHeapNumber()); |
2331 RawFastDoublePropertyAtPut(index, HeapNumber::cast(value)->value()); | 2342 // Ensure that all bits of the double value are preserved. |
| 2343 RawFastDoublePropertyAsBitsAtPut(index, |
| 2344 HeapNumber::cast(value)->value_as_bits()); |
2332 } else { | 2345 } else { |
2333 RawFastPropertyAtPut(index, value); | 2346 RawFastPropertyAtPut(index, value); |
2334 } | 2347 } |
2335 } | 2348 } |
2336 | 2349 |
2337 void JSObject::WriteToField(int descriptor, PropertyDetails details, | 2350 void JSObject::WriteToField(int descriptor, PropertyDetails details, |
2338 Object* value) { | 2351 Object* value) { |
2339 DCHECK_EQ(kField, details.location()); | 2352 DCHECK_EQ(kField, details.location()); |
2340 DCHECK_EQ(kData, details.kind()); | 2353 DCHECK_EQ(kData, details.kind()); |
2341 DisallowHeapAllocation no_gc; | 2354 DisallowHeapAllocation no_gc; |
2342 FieldIndex index = FieldIndex::ForDescriptor(map(), descriptor); | 2355 FieldIndex index = FieldIndex::ForDescriptor(map(), descriptor); |
2343 if (details.representation().IsDouble()) { | 2356 if (details.representation().IsDouble()) { |
2344 // Nothing more to be done. | 2357 // Nothing more to be done. |
2345 if (value->IsUninitialized(this->GetIsolate())) { | 2358 if (value->IsUninitialized(this->GetIsolate())) { |
2346 return; | 2359 return; |
2347 } | 2360 } |
| 2361 // Manipulating the signaling NaN used for the hole and uninitialized |
| 2362 // double field sentinel in C++, e.g. with bit_cast or value()/set_value(), |
| 2363 // will change its value on ia32 (the x87 stack is used to return values |
| 2364 // and stores to the stack silently clear the signalling bit). |
| 2365 uint64_t bits; |
| 2366 if (value->IsSmi()) { |
| 2367 bits = bit_cast<uint64_t>(static_cast<double>(Smi::cast(value)->value())); |
| 2368 } else { |
| 2369 DCHECK(value->IsHeapNumber()); |
| 2370 bits = HeapNumber::cast(value)->value_as_bits(); |
| 2371 } |
2348 if (IsUnboxedDoubleField(index)) { | 2372 if (IsUnboxedDoubleField(index)) { |
2349 RawFastDoublePropertyAtPut(index, value->Number()); | 2373 RawFastDoublePropertyAsBitsAtPut(index, bits); |
2350 } else { | 2374 } else { |
2351 HeapNumber* box = HeapNumber::cast(RawFastPropertyAt(index)); | 2375 HeapNumber* box = HeapNumber::cast(RawFastPropertyAt(index)); |
2352 DCHECK(box->IsMutableHeapNumber()); | 2376 DCHECK(box->IsMutableHeapNumber()); |
2353 box->set_value(value->Number()); | 2377 box->set_value_as_bits(bits); |
2354 } | 2378 } |
2355 } else { | 2379 } else { |
2356 RawFastPropertyAtPut(index, value); | 2380 RawFastPropertyAtPut(index, value); |
2357 } | 2381 } |
2358 } | 2382 } |
2359 | 2383 |
2360 int JSObject::GetInObjectPropertyOffset(int index) { | 2384 int JSObject::GetInObjectPropertyOffset(int index) { |
2361 return map()->GetInObjectPropertyOffset(index); | 2385 return map()->GetInObjectPropertyOffset(index); |
2362 } | 2386 } |
2363 | 2387 |
(...skipping 6054 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8418 #undef WRITE_INT64_FIELD | 8442 #undef WRITE_INT64_FIELD |
8419 #undef READ_BYTE_FIELD | 8443 #undef READ_BYTE_FIELD |
8420 #undef WRITE_BYTE_FIELD | 8444 #undef WRITE_BYTE_FIELD |
8421 #undef NOBARRIER_READ_BYTE_FIELD | 8445 #undef NOBARRIER_READ_BYTE_FIELD |
8422 #undef NOBARRIER_WRITE_BYTE_FIELD | 8446 #undef NOBARRIER_WRITE_BYTE_FIELD |
8423 | 8447 |
8424 } // namespace internal | 8448 } // namespace internal |
8425 } // namespace v8 | 8449 } // namespace v8 |
8426 | 8450 |
8427 #endif // V8_OBJECTS_INL_H_ | 8451 #endif // V8_OBJECTS_INL_H_ |
OLD | NEW |