-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathSmallInteger.h
More file actions
77 lines (61 loc) · 2.03 KB
/
SmallInteger.h
File metadata and controls
77 lines (61 loc) · 2.03 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
/*
Copyright (c) 2019-2023 Javier Pimás, Jan Vrany, Labware.
See (MIT) license in root directory.
*/
#ifndef _SMALL_INTEGER_H_
#define _SMALL_INTEGER_H_
#include "Util.h"
#include <string>
namespace Egg {
struct Object;
/**
* Class `SmallInteger` represents an immediate small integer, encoded
* in a pointer. It is signed and tagged with 1 in its least significant
* bit. It is always held as a pointer.
*/
struct SmallInteger {
static const intptr_t SMALLINT_MIN = INTPTR_MIN >> 1;
static const intptr_t SMALLINT_MAX = INTPTR_MAX >> 1;
operator Object *() /// just a cast
{
return (Object *)(void *)this;
}
static SmallInteger *
from(intptr_t intVal) /// makes a tagged SmallInteger from a native value
{
ASSERT(SMALLINT_MIN <= intVal && intVal <= SMALLINT_MAX);
return (SmallInteger *)(((uintptr_t)intVal << 1) | 1);
}
/**
* Returns a `small pointer` from an aligned address: it is a way to encode
* a pointer as a small integer (marking int bit), so that GC doesn't mess
* with it when tracing. It only requires the pointer is aligned to pointer
* size (rightmost bits are 0). Used for example to encode native code addresses.
*/
static SmallInteger*
smallpointerFrom(void* alignedBuffer)
{
ASSERT( ((uintptr_t)alignedBuffer & 1) == 0 );
return (SmallInteger *)(((uintptr_t)alignedBuffer) | 1);
}
bool isSmallInteger();
/**
* Assuming `this` encodes a SmallInteger, decode its
* (signed) integer value
**/
intptr_t asNative();
/**
* Assuming `this` encodes a pointer stored as a SmallInteger,
* return the address of the original pointer (by clearing last bit)
**/
template <typename T = void *>
T asObject()
{
// ASSERT(this->object()->isSmallInteger());
return (T)((intptr_t)this & (intptr_t)~1);
}
// debugging
std::string printString(){ return std::to_string(this->asNative()); }
};
} // namespace Egg
#endif /* _SMALL_INTEGER_H_ */