Skip to content

Commit b7fa13a

Browse files
committed
Type-tagging for Fixnum/Integer
Adds the overhead of checking if bit 0 is set for all attempts to get the class for an object, but as a consequence significantly reduces object creation.
1 parent b37027d commit b7fa13a

File tree

2 files changed

+52
-61
lines changed

2 files changed

+52
-61
lines changed

compile_calls.rb

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -239,13 +239,36 @@ def compile_call(scope, func, args, block = nil)
239239
end
240240

241241

242-
# If adding type-tagging, this is the place to do it.
243-
# In the case of type tagging, the value in %esi
244-
# would be matched against the suitable type tags
245-
# to determine the class, instead of loading the class
246-
# from the first long of the object.
242+
# Load class for the object whose pointer is in %esi.
243+
#
244+
# For now, this is done by testing bit 0, and if it
245+
# is set we know this isn't a valid pointer to a Class
246+
# object. Instead we assume it is a Fixnum.
247+
#
248+
# This is similar to MRI, but MRI uses type tags for
249+
# more types of objects. We probably will here too
250+
# in the future (e.g. Float when it's added, at least)
251+
#
252+
# Upside: Far less need for garbage collection.
253+
# Downside: The cost of *this* every time we need the
254+
# class pointer. This can be mitigated somewhat by
255+
# better code generation (e.g. keeping class pointers
256+
# for objects that are accessed multiple times;
257+
# figuring out inlining and the like, but requires more
258+
# effort to optimize. As a first stage, however, this
259+
# will do as it makes self-compilation viable for this
260+
# compiler for the first time.
261+
#
247262
def load_class(scope)
263+
@e.testl(1, :esi)
264+
l1 = @e.get_local
265+
l2 = @e.get_local
266+
@e.jz(l1)
267+
@e.load(:global, :Fixnum)
268+
@e.jmp(l2)
269+
@e.label(l1)
248270
@e.load_indirect(:esi, :eax)
271+
@e.label(l2)
249272
end
250273

251274
# Load the super-class pointer

lib/core/fixnum.rb

Lines changed: 24 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,19 @@
11
class Fixnum < Integer
22

3-
def initialize
4-
# Can't use any Ruby expressions that use integers here,
5-
# directly or indirectly, so best not use *any*, because
6-
# it would cause recursion until running out of memory.
7-
%s(assign @value 0)
8-
end
9-
10-
def self.allocate
11-
%s(assign ob (__array_leaf 2))
12-
%s(assign (index ob 0) self)
13-
ob
3+
def class
4+
Fixnum
145
end
156

167
def % other
178
%s(assign r (callm other __get_raw))
18-
%s(assign m (mod @value r))
9+
%s(assign m (mod (sar self) r))
1910
%s(if (eq (ge m 0) (lt r 0))
2011
(assign m (add m r)))
2112
%s(__int m)
2213
end
2314

24-
def __set_raw(value)
25-
@value = value
26-
end
27-
2815
def __get_raw
29-
@value
16+
%s(sar self)
3017
end
3118

3219
def to_i
@@ -75,31 +62,32 @@ def inspect
7562
end
7663

7764
def chr
78-
%s(let (buf)
79-
(assign buf (__alloc_leaf 2))
80-
(snprintf buf 2 "%c" @value)
65+
%s(let (buf)
66+
(assign buf (__alloc_leaf 2))
67+
(snprintf buf 2 "%c" (sar self))
8168
(__get_string buf)
82-
)
69+
)
8370
end
8471

8572
def + other
86-
%s(call __int ((add @value (callm other __get_raw))))
73+
%s(__int (add (sar self) (callm other __get_raw)))
8774
end
8875

8976
def - other
90-
%s(call __int ((sub @value (callm other __get_raw))))
77+
%s(__int (sub (sar self) (callm other __get_raw)))
9178
end
9279

80+
9381
def <= other
94-
%s(if (le @value (callm other __get_raw)) true false)
82+
%s(if (le (sar self) (callm other __get_raw)) true false)
9583
end
9684

9785
def == other
9886
if other.nil?
9987
return false
10088
end
10189
return false if !other.is_a?(Numeric)
102-
%s(if (eq @value (callm other __get_raw)) true false)
90+
%s(if (eq (sar self) (callm other __get_raw)) true false)
10391
end
10492

10593
# FIXME: I don't know why '!' seems to get an argument...
@@ -110,19 +98,19 @@ def ! *args
11098
def != other
11199
return true if !other.is_a?(Numeric)
112100
other = other.to_i
113-
%s(if (ne @value (callm other __get_raw)) true false)
101+
%s(if (ne (sar self) (callm other __get_raw)) true false)
114102
end
115103

116104
def < other
117-
%s(if (lt @value (callm other __get_raw)) true false)
105+
%s(if (lt (sar self) (callm other __get_raw)) true false)
118106
end
119107

120108
def > other
121-
%s(if (gt @value (callm other __get_raw)) true false)
109+
%s(if (gt (sar self) (callm other __get_raw)) true false)
122110
end
123111

124112
def >= other
125-
%s(if (ge @value (callm other __get_raw)) true false)
113+
%s(if (ge (sar self) (callm other __get_raw)) true false)
126114
end
127115

128116
def <=> other
@@ -137,22 +125,22 @@ def <=> other
137125
end
138126

139127
def div other
140-
%s(call __int ((div @value (callm other __get_raw))))
128+
%s(__int (div (sar self) (sar other)))
141129
end
142130

143131
def mul other
144-
%s(call __int ((mul @value (callm other __get_raw))))
132+
%s(__int (mul (sar self) (sar other)))
145133
end
146134

147135
# These two definitions are only acceptable temporarily,
148136
# because we will for now only deal with integers
149137

150138
def * other
151-
mul(other)
139+
%s(__int (mul (sar self) (sar other)))
152140
end
153141

154142
def / other
155-
div(other)
143+
%s(__int (div (sar self) (sar other)))
156144
end
157145

158146
def ord
@@ -168,27 +156,7 @@ def times
168156
end
169157
end
170158

171-
%s(assign FixNum_cache_size 1000)
172-
%s(assign FixNum_cache (__array_leaf (mul FixNum_cache_size 2)))
173-
174159
%s(defun __int (val)
175-
(let (num)
176-
(if (and (ge val 0) (lt val FixNum_cache_size))
177-
(do
178-
# 32 bit class-ptr + 32 bit int; Naughty assumptions again. FIXME
179-
(assign num (add FixNum_cache (mul val 8)))
180-
(if (eq (index num 0) 0) (do
181-
(assign (index num 0) Fixnum) # class-ptr
182-
(callm num __set_raw (val))
183-
(return num)
184-
))
185-
(return num)
186-
)
187-
)
188-
(assign num (callm Fixnum allocate))
189-
(callm num __set_raw (val))
190-
(return num)
191-
)
192-
)
193-
194-
%s(__compiler_internal integer_list)
160+
(add (shl val) 1)
161+
)
162+

0 commit comments

Comments
 (0)