• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2018 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_OBJECTS_SMI_H_
6 #define V8_OBJECTS_SMI_H_
7 
8 #include "src/common/globals.h"
9 #include "src/objects/heap-object.h"
10 
11 // Has to be the last include (doesn't have include guards):
12 #include "src/objects/object-macros.h"
13 
14 namespace v8 {
15 namespace internal {
16 
17 // Smi represents integer Numbers that can be stored in 31 bits.
18 // Smis are immediate which means they are NOT allocated in the heap.
19 // The ptr_ value has the following format: [31 bit signed int] 0
20 // For long smis it has the following format:
21 //     [32 bit signed int] [31 bits zero padding] 0
22 // Smi stands for small integer.
23 class Smi : public Object {
24  public:
25   // This replaces the OBJECT_CONSTRUCTORS macro, because Smis are special
26   // in that we want them to be constexprs.
Smi()27   constexpr Smi() : Object() {}
Smi(Address ptr)28   explicit constexpr Smi(Address ptr) : Object(ptr) {
29     DCHECK(HAS_SMI_TAG(ptr));
30   }
31 
32   // Returns the integer value.
value()33   inline int value() const { return Internals::SmiValue(ptr()); }
ToUint32Smi()34   inline Smi ToUint32Smi() {
35     if (value() <= 0) return Smi::FromInt(0);
36     return Smi::FromInt(static_cast<uint32_t>(value()));
37   }
38 
39   // Convert a Smi object to an int.
ToInt(const Object object)40   static inline int ToInt(const Object object) {
41     return Smi::cast(object).value();
42   }
43 
44   // Convert a value to a Smi object.
FromInt(int value)45   static inline constexpr Smi FromInt(int value) {
46     DCHECK(Smi::IsValid(value));
47     return Smi(Internals::IntToSmi(value));
48   }
49 
FromIntptr(intptr_t value)50   static inline Smi FromIntptr(intptr_t value) {
51     DCHECK(Smi::IsValid(value));
52     int smi_shift_bits = kSmiTagSize + kSmiShiftSize;
53     return Smi((static_cast<Address>(value) << smi_shift_bits) | kSmiTag);
54   }
55 
56   // Given {value} in [0, 2^31-1], force it into Smi range by changing at most
57   // the MSB (leaving the lower 31 bit unchanged).
From31BitPattern(int value)58   static inline Smi From31BitPattern(int value) {
59     return Smi::FromInt((value << (32 - kSmiValueSize)) >>
60                         (32 - kSmiValueSize));
61   }
62 
63   template <typename E,
64             typename = typename std::enable_if<std::is_enum<E>::value>::type>
FromEnum(E value)65   static inline Smi FromEnum(E value) {
66     STATIC_ASSERT(sizeof(E) <= sizeof(int));
67     return FromInt(static_cast<int>(value));
68   }
69 
70   // Returns whether value can be represented in a Smi.
IsValid(intptr_t value)71   static inline bool constexpr IsValid(intptr_t value) {
72     DCHECK_EQ(Internals::IsValidSmi(value),
73               value >= kMinValue && value <= kMaxValue);
74     return Internals::IsValidSmi(value);
75   }
76 
77   // Compare two Smis x, y as if they were converted to strings and then
78   // compared lexicographically. Returns:
79   // -1 if x < y.
80   //  0 if x == y.
81   //  1 if x > y.
82   // Returns the result (a tagged Smi) as a raw Address for ExternalReference
83   // usage.
84   V8_EXPORT_PRIVATE static Address LexicographicCompare(Isolate* isolate, Smi x,
85                                                         Smi y);
86 
87   DECL_CAST(Smi)
88 
89   // Dispatched behavior.
90   V8_EXPORT_PRIVATE void SmiPrint(std::ostream& os) const;
DECL_VERIFIER(Smi)91   DECL_VERIFIER(Smi)
92 
93   // Since this is a constexpr, "calling" it is just as efficient
94   // as reading a constant.
95   static inline constexpr Smi zero() { return Smi::FromInt(0); }
96   static constexpr int kMinValue = kSmiMinValue;
97   static constexpr int kMaxValue = kSmiMaxValue;
98 
99   // Smi value for filling in not-yet initialized tagged field values with a
100   // valid tagged pointer. A field value equal to this doesn't necessarily
101   // indicate that a field is uninitialized, but an uninitialized field should
102   // definitely equal this value.
103   //
104   // This _has_ to be kNullAddress, so that an uninitialized field value read as
105   // an embedded pointer field is interpreted as nullptr. This is so that
106   // uninitialised embedded pointers are not forwarded to the embedder as part
107   // of embedder tracing (and similar mechanisms), as nullptrs are skipped for
108   // those cases and otherwise the embedder would try to dereference the
109   // uninitialized pointer value.
uninitialized_deserialization_value()110   static constexpr Smi uninitialized_deserialization_value() {
111     return Smi(kNullAddress);
112   }
113 };
114 
115 CAST_ACCESSOR(Smi)
116 
117 }  // namespace internal
118 }  // namespace v8
119 
120 #include "src/objects/object-macros-undef.h"
121 
122 #endif  // V8_OBJECTS_SMI_H_
123