Skip to content

Commit 93c8072

Browse files
authored
Refactor Crystal::DWARF::LineNumbers::Sequence (#16214)
Removes unused fields and drops the bang properties, creating the struct only after all the fields are read. This struct now measures 64 bytes instead of 216.
1 parent df35581 commit 93c8072

File tree

1 file changed

+64
-67
lines changed

1 file changed

+64
-67
lines changed

src/crystal/dwarf/line_numbers.cr

Lines changed: 64 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -119,42 +119,29 @@ module Crystal
119119
# :nodoc:
120120
#
121121
# An individual compressed sequence.
122-
struct Sequence
123-
property! offset : Int64
124-
property! unit_length : UInt32
125-
property! version : UInt16
126-
property! address_size : Int32
127-
property! segment_selector_size : Int32
128-
property! header_length : UInt32 # FIXME: UInt64 for DWARF64 (uncommon)
129-
property! minimum_instruction_length : Int32
130-
property! maximum_operations_per_instruction : Int32
131-
property! default_is_stmt : Bool
132-
property! line_base : Int32
133-
property! line_range : Int32
134-
property! opcode_base : Int32
135-
122+
record Sequence,
123+
offset : Int64,
124+
unit_length : UInt32,
125+
minimum_instruction_length : Int32,
126+
maximum_operations_per_instruction : Int32,
127+
default_is_stmt : Bool,
128+
line_base : Int32,
129+
line_range : Int32,
130+
opcode_base : Int32,
136131
# An array of how many args an array. Starts at 1 because 0 means an
137132
# extended opcode.
138-
getter standard_opcode_lengths
139-
133+
standard_opcode_lengths : Array(UInt8),
140134
# An array of directory names. Starts at 1; 0 means that the information
141135
# is missing.
142-
property! include_directories : Array(String)
143-
136+
include_directories : Array(String),
137+
# An array of file names. Starts at 1; 0 means that the information is
138+
# missing.
139+
file_names : Array(FileEntry) do
144140
record FileEntry,
145141
path : String,
146142
mtime : UInt64,
147143
size : UInt64
148144

149-
# An array of file names. Starts at 1; 0 means that the information is
150-
# missing.
151-
property! file_names : Array(FileEntry)
152-
153-
def initialize
154-
@maximum_operations_per_instruction = 1_u8
155-
@standard_opcode_lengths = [0_u8]
156-
end
157-
158145
# Returns the unit length, adding the size of the `unit_length`.
159146
def total_length
160147
unit_length + sizeof(typeof(unit_length))
@@ -194,71 +181,81 @@ module Crystal
194181
offset = pos - @offset
195182
break unless offset < size
196183

197-
sequence = Sequence.new
198-
sequence.offset = offset
199-
sequence.unit_length = @io.read_bytes(UInt32)
200-
sequence.version = @io.read_bytes(UInt16)
184+
unit_length = @io.read_bytes(UInt32)
185+
total_length = unit_length + sizeof(typeof(unit_length))
186+
version = @io.read_bytes(UInt16)
201187

202-
if sequence.version < 2 || sequence.version > 5
203-
raise "Unknown line table version: #{sequence.version}"
188+
if version < 2 || version > 5
189+
raise "Unknown line table version: #{version}"
204190
end
205191

206-
if sequence.version >= 5
207-
sequence.address_size = @io.read_bytes(UInt8).to_i
208-
sequence.segment_selector_size = @io.read_bytes(UInt8).to_i
192+
if version >= 5
193+
_address_size = @io.read_bytes(UInt8).to_i
194+
_segment_selector_size = @io.read_bytes(UInt8).to_i
209195
else
210-
sequence.address_size = {{ flag?(:bits64) ? 8 : 4 }}
211-
sequence.segment_selector_size = 0
196+
_address_size = {{ flag?(:bits64) ? 8 : 4 }}
197+
_segment_selector_size = 0
212198
end
213199

214-
sequence.header_length = @io.read_bytes(UInt32)
215-
sequence.minimum_instruction_length = @io.read_bytes(UInt8).to_i
200+
_header_length = @io.read_bytes(UInt32) # FIXME: UInt64 for DWARF64 (uncommon)
201+
minimum_instruction_length = @io.read_bytes(UInt8).to_i
216202

217-
if sequence.version >= 4
218-
sequence.maximum_operations_per_instruction = @io.read_bytes(UInt8).to_i
203+
if version >= 4
204+
maximum_operations_per_instruction = @io.read_bytes(UInt8).to_i
219205
else
220-
sequence.maximum_operations_per_instruction = 1
206+
maximum_operations_per_instruction = 1
221207
end
222208

223-
if sequence.maximum_operations_per_instruction == 0
209+
if maximum_operations_per_instruction == 0
224210
raise "Invalid maximum operations per instruction: 0"
225211
end
226212

227-
sequence.default_is_stmt = @io.read_byte == 1
228-
sequence.line_base = @io.read_bytes(Int8).to_i
229-
sequence.line_range = @io.read_bytes(UInt8).to_i
230-
if sequence.line_range == 0
213+
default_is_stmt = @io.read_byte == 1
214+
line_base = @io.read_bytes(Int8).to_i
215+
line_range = @io.read_bytes(UInt8).to_i
216+
if line_range == 0
231217
raise "Invalid line range: 0"
232218
end
233219

234-
sequence.opcode_base = @io.read_bytes(UInt8).to_i
235-
read_opcodes(sequence)
220+
opcode_base = @io.read_bytes(UInt8).to_i
221+
standard_opcode_lengths = Array(UInt8).new(opcode_base)
222+
standard_opcode_lengths << 0_u8
223+
(opcode_base - 1).times do
224+
standard_opcode_lengths << @io.read_byte.not_nil!
225+
end
236226

237-
if sequence.version < 5
238-
sequence.include_directories = read_directory_table(sequence)
239-
sequence.file_names = read_filename_table(sequence)
227+
if version < 5
228+
include_directories = read_directory_table
229+
file_names = read_filename_table(include_directories)
240230
else
241231
dir_format = read_lnct_format
242232
count = DWARF.read_unsigned_leb128(@io)
243-
sequence.include_directories = Array.new(count) { read_lnct(sequence, dir_format).path }
233+
include_directories = Array.new(count) { read_lnct(nil, dir_format).path }
244234

245235
file_format = read_lnct_format
246236
count = DWARF.read_unsigned_leb128(@io)
247-
sequence.file_names = Array.new(count) { read_lnct(sequence, file_format) }
237+
file_names = Array.new(count) { read_lnct(include_directories, file_format) }
248238
end
249239

250-
if @io.tell - @offset < sequence.offset + sequence.total_length
240+
if @io.tell - @offset < offset + total_length
241+
sequence = Sequence.new(
242+
offset,
243+
unit_length,
244+
minimum_instruction_length,
245+
maximum_operations_per_instruction,
246+
default_is_stmt,
247+
line_base,
248+
line_range,
249+
opcode_base,
250+
standard_opcode_lengths,
251+
include_directories,
252+
file_names,
253+
)
251254
read_statement_program(sequence)
252255
end
253256
end
254257
end
255258

256-
private def read_opcodes(sequence)
257-
1.upto(sequence.opcode_base - 1) do
258-
sequence.standard_opcode_lengths << @io.read_byte.not_nil!
259-
end
260-
end
261-
262259
record LNCTFormat,
263260
lnct : LNCT,
264261
format : FORM
@@ -285,7 +282,7 @@ module Crystal
285282
end
286283
end
287284

288-
private def read_lnct(sequence, formats)
285+
private def read_lnct(include_directories, formats)
289286
dir = ""
290287
path = ""
291288
mtime = 0_u64
@@ -340,7 +337,7 @@ module Crystal
340337
path = str if str
341338
in .directory_index?
342339
if val
343-
dir = sequence.include_directories[val]
340+
dir = include_directories.not_nil![val]
344341
end
345342
in .timestamp?
346343
mtime = val.to_u64
@@ -358,7 +355,7 @@ module Crystal
358355
Sequence::FileEntry.new(path, mtime, size)
359356
end
360357

361-
private def read_directory_table(sequence)
358+
private def read_directory_table
362359
ary = [""]
363360
loop do
364361
name = @io.gets('\0', chomp: true).to_s
@@ -368,7 +365,7 @@ module Crystal
368365
ary
369366
end
370367

371-
private def read_filename_table(sequence)
368+
private def read_filename_table(include_directories)
372369
ary = [Sequence::FileEntry.new("", 0, 0)]
373370
loop do
374371
name = @io.gets('\0', chomp: true).to_s
@@ -377,7 +374,7 @@ module Crystal
377374
time = DWARF.read_unsigned_leb128(@io)
378375
length = DWARF.read_unsigned_leb128(@io)
379376

380-
dir = sequence.include_directories[dir]
377+
dir = include_directories[dir]
381378
if (name != "" && dir != "")
382379
name = File.join(dir, name)
383380
end

0 commit comments

Comments
 (0)