Skip to content

Commit 55d83e6

Browse files
authored
feat: Layouts and small perf imrpovement (#532)
* small improvements * perf improve * layouts + fix test
1 parent 823ac4d commit 55d83e6

File tree

9 files changed

+289
-88
lines changed

9 files changed

+289
-88
lines changed

build.zig

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,32 @@ pub fn build(b: *std.Build) void {
7878
// running `zig build`).
7979
b.installArtifact(lib);
8080

81+
// LSP helper for errors (check step)
82+
{
83+
const exe_check = b.addExecutable(.{
84+
.name = "ziggy-starkdust",
85+
// In this case the main source file is merely a path, however, in more
86+
// complicated build scripts, this could be a generated file.
87+
.root_source_file = b.path("src/main.zig"),
88+
.target = target,
89+
.optimize = optimize,
90+
91+
.link_libc = false,
92+
.omit_frame_pointer = if (optimize == .ReleaseFast) null else false,
93+
.strip = if (optimize == .ReleaseFast) true else null,
94+
});
95+
exe_check.root_module.addOptions("cfg", options);
96+
97+
// Add dependency modules to the executable.
98+
for (deps) |mod| exe_check.root_module.addImport(
99+
mod.name,
100+
mod.module,
101+
);
102+
103+
const check = b.step("check", "Check if cairo-vm compiles");
104+
check.dependOn(&exe_check.step);
105+
}
106+
81107
// **************************************************************
82108
// * ZIGGY STARKDUST AS AN EXECUTABLE *
83109
// **************************************************************
@@ -89,7 +115,7 @@ pub fn build(b: *std.Build) void {
89115
.target = target,
90116
.optimize = optimize,
91117

92-
.link_libc = true,
118+
.link_libc = false,
93119
.omit_frame_pointer = if (optimize == .ReleaseFast) null else false,
94120
.strip = if (optimize == .ReleaseFast) true else null,
95121
});

src/cmd/cmd.zig

Lines changed: 20 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -248,27 +248,27 @@ const UsageError = error{
248248
/// Returns a `UsageError` if there's a misuse of the CLI, specifically if tracing is attempted
249249
/// while it's disabled in the build.
250250
fn execute() anyerror!void {
251-
try runProgram(global_allocator, cfg);
251+
var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
252+
defer arena.deinit();
253+
254+
try runProgram(arena.allocator(), cfg);
252255
}
253256

254257
fn runProgram(allocator: std.mem.Allocator, _cfg: Args) !void {
255-
var arena = std.heap.ArenaAllocator.init(allocator);
256-
defer arena.deinit();
257-
258258
const trace_enabled = _cfg.trace_file != null or _cfg.air_public_input != null;
259259

260260
const file = try std.fs.cwd().openFile(_cfg.filename, .{});
261261
defer file.close();
262262

263263
// Read the entire file content into a buffer using the provided allocator
264264
const buffer = try file.readToEndAlloc(
265-
arena.allocator(),
265+
allocator,
266266
try file.getEndPos(),
267267
);
268-
defer arena.allocator().free(buffer);
268+
defer allocator.free(buffer);
269269

270270
var runner = try cairo_run.cairoRun(
271-
arena.allocator(),
271+
allocator,
272272
buffer,
273273
.{
274274
.entrypoint = _cfg.entrypoint,
@@ -281,11 +281,14 @@ fn runProgram(allocator: std.mem.Allocator, _cfg: Args) !void {
281281
},
282282
@constCast(&.{}),
283283
);
284-
defer runner.deinit(arena.allocator());
285-
defer runner.vm.segments.memory.deinitData(arena.allocator());
284+
defer allocator.destroy(runner.vm);
285+
defer runner.deinit(allocator);
286+
defer runner.vm.segments.memory.deinitData(allocator);
286287

287288
if (_cfg.print_output) {
288-
var output_buffer = try std.ArrayList(u8).initCapacity(arena.allocator(), 100);
289+
var output_buffer = try std.ArrayList(u8).initCapacity(allocator, 100);
290+
defer output_buffer.deinit();
291+
289292
output_buffer.appendSliceAssumeCapacity("Program Output:\n");
290293

291294
try runner.vm.writeOutput(output_buffer.writer());
@@ -321,8 +324,8 @@ fn runProgram(allocator: std.mem.Allocator, _cfg: Args) !void {
321324
var public_input = try runner.getAirPublicInput();
322325
defer public_input.deinit();
323326

324-
const public_input_json = try public_input.serialize(arena.allocator());
325-
defer arena.allocator().free(public_input_json);
327+
const public_input_json = try public_input.serialize(allocator);
328+
defer allocator.free(public_input_json);
326329

327330
var air_file = try std.fs.cwd().createFile(file_path, .{});
328331
defer air_file.close();
@@ -334,13 +337,13 @@ fn runProgram(allocator: std.mem.Allocator, _cfg: Args) !void {
334337
test "RunOK" {
335338
for ([_][]const u8{
336339
"plain",
337-
// "small",
338-
// "dex",
340+
"small",
341+
"dex",
339342
// "starknet",
340-
// "starknet_with_keccak",
341-
// "recursive_large_output",
343+
"starknet_with_keccak",
344+
"recursive_large_output",
342345
"all_cairo",
343-
// "all_solidity",
346+
"all_solidity",
344347
}) |layout| {
345348
inline for ([_]bool{ false, true }) |memory_file| {
346349
inline for ([_]bool{ false, true }) |_trace_file| {

src/vm/air_input_public.zig

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
const std = @import("std");
22
const Felt252 = @import("starknet").fields.Felt252;
33
const RelocatedTraceEntry = @import("trace_context.zig").RelocatedTraceEntry;
4+
const RelocatedFelt252 = @import("trace_context.zig").RelocatedFelt252;
45
const HintProcessor = @import("../hint_processor/hint_processor_def.zig").CairoVMHintProcessor;
56

67
const Config = @import("config.zig").Config;
@@ -117,15 +118,15 @@ pub const PublicInput = struct {
117118
// new - creating new PublicInput, all arguments caller is owner
118119
pub fn new(
119120
allocator: std.mem.Allocator,
120-
memory: []const ?Felt252,
121+
memory: []const RelocatedFelt252,
121122
layout: []const u8,
122123
public_memory_addresses: []const std.meta.Tuple(&.{ usize, usize }),
123124
memory_segment_addresses: std.StringHashMap(std.meta.Tuple(&.{ usize, usize })),
124125
trace: []const RelocatedTraceEntry,
125126
rc_limits: std.meta.Tuple(&.{ isize, isize }),
126127
) !Self {
127128
const memory_entry = (struct {
128-
fn func(mem: []const ?Felt252, addresses: std.meta.Tuple(&.{ usize, usize })) !PublicMemoryEntry {
129+
fn func(mem: []const RelocatedFelt252, addresses: std.meta.Tuple(&.{ usize, usize })) !PublicMemoryEntry {
129130
const address, const page = addresses;
130131
return .{
131132
.address = address,
@@ -181,7 +182,7 @@ pub const PublicMemoryEntry = struct {
181182
address: usize,
182183
value: struct {
183184
/// using struct only for json parse abstraction
184-
value: ?Felt252,
185+
value: RelocatedFelt252,
185186

186187
pub fn jsonParse(allocator: std.mem.Allocator, source: anytype, options: std.json.ParseOptions) !@This() {
187188
_ = allocator; // autofix
@@ -190,17 +191,17 @@ pub const PublicMemoryEntry = struct {
190191
inline .string => |data| {
191192
const val = try std.fmt.parseInt(u256, data, 0);
192193

193-
return .{ .value = Felt252.fromInt(u256, val) };
194+
return .{ .value = RelocatedFelt252.init(Felt252.fromInt(u256, val)) };
194195
},
195196
inline .null => return .{
196-
.value = null,
197+
.value = RelocatedFelt252.NONE,
197198
},
198199
else => return error.UnexpectedToken,
199200
}
200201
}
201202

202203
pub fn jsonStringify(self: @This(), out: anytype) !void {
203-
if (self.value) |v| try out.print("\"0x{x}\"", .{v.toU256()}) else try out.write(null);
204+
if (self.value.getValue()) |v| try out.print("\"0x{x}\"", .{v.toU256()}) else try out.write(null);
204205
}
205206
},
206207
page: usize,

src/vm/cairo_run.zig

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,11 @@ pub fn writeEncodedTrace(relocated_trace: []const RelocatedTraceEntry, dest: any
4343
///
4444
/// - `relocated_memory`: The post-execution memory, relocated.
4545
/// - `dest`: The destination file that the memory is to be written.
46-
pub fn writeEncodedMemory(relocated_memory: []?Felt252, dest: anytype) !void {
46+
pub fn writeEncodedMemory(relocated_memory: []RelocatedFelt252, dest: anytype) !void {
4747
var buf: [8]u8 = undefined;
4848

4949
for (relocated_memory, 0..) |memory_cell, i| {
50-
if (memory_cell) |cell| {
50+
if (memory_cell.getValue()) |cell| {
5151
std.mem.writeInt(u64, &buf, i, .little);
5252
_ = try dest.write(&buf);
5353
_ = try dest.write(&cell.toBytesLe());
@@ -217,7 +217,6 @@ pub fn runConfig(allocator: Allocator, config: Config) !CairoRunner {
217217
&hint_processor,
218218
);
219219

220-
221220
try runner.vm.verifyAutoDeductions(allocator);
222221

223222
// cairo_runner.read_return_values(allow_missing_builtins)?;
@@ -228,7 +227,6 @@ pub fn runConfig(allocator: Allocator, config: Config) !CairoRunner {
228227
if (secure_run)
229228
try security.verifySecureRunner(allocator, &runner, true, null);
230229

231-
232230
if (config.print_output) {
233231
var buf = try std.ArrayList(u8).initCapacity(allocator, 100);
234232
defer buf.deinit();
@@ -290,12 +288,12 @@ test "EncodedMemory: can round trip from valid memory binary" {
290288
defer file.close();
291289

292290
var reader = file.reader();
293-
var relocated_memory = std.ArrayList(?Felt252).init(allocator);
291+
var relocated_memory = std.ArrayList(RelocatedFelt252).init(allocator);
294292
defer relocated_memory.deinit();
295293

296294
// Relocated addresses start at 1,
297295
// it's the law.
298-
try relocated_memory.append(null);
296+
try relocated_memory.append(RelocatedFelt252.NONE);
299297

300298
// Read the entire file into a bytes buffer
301299
var expected_file_bytes = std.ArrayList(u8).init(allocator);
@@ -319,7 +317,7 @@ test "EncodedMemory: can round trip from valid memory binary" {
319317

320318
const value = std.mem.readInt(u256, &value_buf, .little);
321319

322-
try relocated_memory.insert(idx, Felt252.fromInt(u256, value));
320+
try relocated_memory.insert(idx, RelocatedFelt252.init(Felt252.fromInt(u256, value)));
323321
}
324322

325323
// now we have the shape of a bonafide relocated memory,

src/vm/core.zig

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -492,10 +492,10 @@ pub const CairoVM = struct {
492492
try self.opcodeAssertions(instruction, operands_result);
493493

494494
// Constants for offset bit manipulation.
495-
const OFFSET = 1 << 15;
496-
const off_0 = instruction.off_0 + OFFSET;
497-
const off_1 = instruction.off_1 + OFFSET;
498-
const off_2 = instruction.off_2 + OFFSET;
495+
const OFFSET: u16 = 1 << 15;
496+
const off_0 = @as(isize, instruction.off_0) + OFFSET;
497+
const off_1 = @as(isize, instruction.off_1) + OFFSET;
498+
const off_2 = @as(isize, instruction.off_2) + OFFSET;
499499

500500
// Calculate and update relocation limits.
501501
self.rc_limits = if (self.rc_limits) |limits| .{

src/vm/instructions.zig

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -136,15 +136,16 @@ pub const Instruction = struct {
136136
/// Offset 0
137137
///
138138
/// In the range [-2**15, 2*15) = [-2**(OFFSET_BITS-1), 2**(OFFSET_BITS-1)).
139-
off_0: isize = 0,
139+
/// 16 bit signed integer
140+
off_0: i16 = 0,
140141
/// Offset 1
141142
///
142143
/// In the range [-2**15, 2*15) = [-2**(OFFSET_BITS-1), 2**(OFFSET_BITS-1)).
143-
off_1: isize = 0,
144+
off_1: i16 = 0,
144145
/// Offset 2
145146
///
146147
/// In the range [-2**15, 2*15) = [-2**(OFFSET_BITS-1), 2**(OFFSET_BITS-1)).
147-
off_2: isize = 0,
148+
off_2: i16 = 0,
148149
/// Destination register.
149150
dst_reg: Register = .FP,
150151
/// Operand 0 register.

0 commit comments

Comments
 (0)