1 // Copyright 2020 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #ifndef V8_HEAP_FACTORY_BASE_INL_H_
6 #define V8_HEAP_FACTORY_BASE_INL_H_
7
8 #include "src/heap/factory-base.h"
9 #include "src/numbers/conversions.h"
10 #include "src/objects/heap-number.h"
11 #include "src/objects/map.h"
12 #include "src/objects/slots-inl.h"
13 #include "src/objects/smi.h"
14 #include "src/roots/roots.h"
15
16 namespace v8 {
17 namespace internal {
18
19 template <typename Impl>
ToBoolean(bool value)20 Handle<Oddball> FactoryBase<Impl>::ToBoolean(bool value) {
21 return value ? impl()->true_value() : impl()->false_value();
22 }
23
24 template <typename Impl>
25 template <AllocationType allocation>
NewNumber(double value)26 Handle<Object> FactoryBase<Impl>::NewNumber(double value) {
27 // Materialize as a SMI if possible.
28 int32_t int_value;
29 if (DoubleToSmiInteger(value, &int_value)) {
30 return handle(Smi::FromInt(int_value), isolate());
31 }
32 return NewHeapNumber<allocation>(value);
33 }
34
35 template <typename Impl>
36 template <AllocationType allocation>
NewNumberFromInt(int32_t value)37 Handle<Object> FactoryBase<Impl>::NewNumberFromInt(int32_t value) {
38 if (Smi::IsValid(value)) return handle(Smi::FromInt(value), isolate());
39 // Bypass NewNumber to avoid various redundant checks.
40 return NewHeapNumber<allocation>(FastI2D(value));
41 }
42
43 template <typename Impl>
44 template <AllocationType allocation>
NewNumberFromUint(uint32_t value)45 Handle<Object> FactoryBase<Impl>::NewNumberFromUint(uint32_t value) {
46 int32_t int32v = static_cast<int32_t>(value);
47 if (int32v >= 0 && Smi::IsValid(int32v)) {
48 return handle(Smi::FromInt(int32v), isolate());
49 }
50 return NewHeapNumber<allocation>(FastUI2D(value));
51 }
52
53 template <typename Impl>
54 template <AllocationType allocation>
NewNumberFromSize(size_t value)55 Handle<Object> FactoryBase<Impl>::NewNumberFromSize(size_t value) {
56 // We can't use Smi::IsValid() here because that operates on a signed
57 // intptr_t, and casting from size_t could create a bogus sign bit.
58 if (value <= static_cast<size_t>(Smi::kMaxValue)) {
59 return handle(Smi::FromIntptr(static_cast<intptr_t>(value)), isolate());
60 }
61 return NewHeapNumber<allocation>(static_cast<double>(value));
62 }
63
64 template <typename Impl>
65 template <AllocationType allocation>
NewNumberFromInt64(int64_t value)66 Handle<Object> FactoryBase<Impl>::NewNumberFromInt64(int64_t value) {
67 if (value <= std::numeric_limits<int32_t>::max() &&
68 value >= std::numeric_limits<int32_t>::min() &&
69 Smi::IsValid(static_cast<int32_t>(value))) {
70 return handle(Smi::FromInt(static_cast<int32_t>(value)), isolate());
71 }
72 return NewHeapNumber<allocation>(static_cast<double>(value));
73 }
74
75 template <typename Impl>
76 template <AllocationType allocation>
NewHeapNumber(double value)77 Handle<HeapNumber> FactoryBase<Impl>::NewHeapNumber(double value) {
78 Handle<HeapNumber> heap_number = NewHeapNumber<allocation>();
79 heap_number->set_value(value, kRelaxedStore);
80 return heap_number;
81 }
82
83 template <typename Impl>
84 template <AllocationType allocation>
NewHeapNumberFromBits(uint64_t bits)85 Handle<HeapNumber> FactoryBase<Impl>::NewHeapNumberFromBits(uint64_t bits) {
86 Handle<HeapNumber> heap_number = NewHeapNumber<allocation>();
87 heap_number->set_value_as_bits(bits, kRelaxedStore);
88 return heap_number;
89 }
90
91 template <typename Impl>
92 template <AllocationType allocation>
NewHeapNumberWithHoleNaN()93 Handle<HeapNumber> FactoryBase<Impl>::NewHeapNumberWithHoleNaN() {
94 return NewHeapNumberFromBits<allocation>(kHoleNanInt64);
95 }
96
97 template <typename Impl>
98 template <typename StructType>
NewStructInternal(InstanceType type,AllocationType allocation)99 StructType FactoryBase<Impl>::NewStructInternal(InstanceType type,
100 AllocationType allocation) {
101 ReadOnlyRoots roots = read_only_roots();
102 Map map = Map::GetInstanceTypeMap(roots, type);
103 int size = StructType::kSize;
104 return StructType::cast(NewStructInternal(roots, map, size, allocation));
105 }
106
107 template <typename Impl>
NewStructInternal(ReadOnlyRoots roots,Map map,int size,AllocationType allocation)108 Struct FactoryBase<Impl>::NewStructInternal(ReadOnlyRoots roots, Map map,
109 int size,
110 AllocationType allocation) {
111 DCHECK_EQ(size, map.instance_size());
112 HeapObject result = AllocateRawWithImmortalMap(size, allocation, map);
113 Struct str = Struct::cast(result);
114 Object value = roots.undefined_value();
115 int length = (size >> kTaggedSizeLog2) - 1;
116 MemsetTagged(str.RawField(Struct::kHeaderSize), value, length);
117 return str;
118 }
119
120 } // namespace internal
121 } // namespace v8
122
123 #endif // V8_HEAP_FACTORY_BASE_INL_H_
124