Skip to content

Commit

Permalink
feat: Layouts and small perf imrpovement (#532)
Browse files Browse the repository at this point in the history
* small improvements

* perf improve

* layouts + fix test
  • Loading branch information
StringNick committed Jul 24, 2024
1 parent 823ac4d commit 55d83e6
Show file tree
Hide file tree
Showing 9 changed files with 289 additions and 88 deletions.
28 changes: 27 additions & 1 deletion build.zig
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,32 @@ pub fn build(b: *std.Build) void {
// running `zig build`).
b.installArtifact(lib);

// LSP helper for errors (check step)
{
const exe_check = b.addExecutable(.{
.name = "ziggy-starkdust",
// In this case the main source file is merely a path, however, in more
// complicated build scripts, this could be a generated file.
.root_source_file = b.path("src/main.zig"),
.target = target,
.optimize = optimize,

.link_libc = false,
.omit_frame_pointer = if (optimize == .ReleaseFast) null else false,
.strip = if (optimize == .ReleaseFast) true else null,
});
exe_check.root_module.addOptions("cfg", options);

// Add dependency modules to the executable.
for (deps) |mod| exe_check.root_module.addImport(
mod.name,
mod.module,
);

const check = b.step("check", "Check if cairo-vm compiles");
check.dependOn(&exe_check.step);
}

// **************************************************************
// * ZIGGY STARKDUST AS AN EXECUTABLE *
// **************************************************************
Expand All @@ -89,7 +115,7 @@ pub fn build(b: *std.Build) void {
.target = target,
.optimize = optimize,

.link_libc = true,
.link_libc = false,
.omit_frame_pointer = if (optimize == .ReleaseFast) null else false,
.strip = if (optimize == .ReleaseFast) true else null,
});
Expand Down
37 changes: 20 additions & 17 deletions src/cmd/cmd.zig
Original file line number Diff line number Diff line change
Expand Up @@ -248,27 +248,27 @@ const UsageError = error{
/// Returns a `UsageError` if there's a misuse of the CLI, specifically if tracing is attempted
/// while it's disabled in the build.
fn execute() anyerror!void {
try runProgram(global_allocator, cfg);
var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
defer arena.deinit();

try runProgram(arena.allocator(), cfg);
}

fn runProgram(allocator: std.mem.Allocator, _cfg: Args) !void {
var arena = std.heap.ArenaAllocator.init(allocator);
defer arena.deinit();

const trace_enabled = _cfg.trace_file != null or _cfg.air_public_input != null;

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

// Read the entire file content into a buffer using the provided allocator
const buffer = try file.readToEndAlloc(
arena.allocator(),
allocator,
try file.getEndPos(),
);
defer arena.allocator().free(buffer);
defer allocator.free(buffer);

var runner = try cairo_run.cairoRun(
arena.allocator(),
allocator,
buffer,
.{
.entrypoint = _cfg.entrypoint,
Expand All @@ -281,11 +281,14 @@ fn runProgram(allocator: std.mem.Allocator, _cfg: Args) !void {
},
@constCast(&.{}),
);
defer runner.deinit(arena.allocator());
defer runner.vm.segments.memory.deinitData(arena.allocator());
defer allocator.destroy(runner.vm);
defer runner.deinit(allocator);
defer runner.vm.segments.memory.deinitData(allocator);

if (_cfg.print_output) {
var output_buffer = try std.ArrayList(u8).initCapacity(arena.allocator(), 100);
var output_buffer = try std.ArrayList(u8).initCapacity(allocator, 100);
defer output_buffer.deinit();

output_buffer.appendSliceAssumeCapacity("Program Output:\n");

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

const public_input_json = try public_input.serialize(arena.allocator());
defer arena.allocator().free(public_input_json);
const public_input_json = try public_input.serialize(allocator);
defer allocator.free(public_input_json);

var air_file = try std.fs.cwd().createFile(file_path, .{});
defer air_file.close();
Expand All @@ -334,13 +337,13 @@ fn runProgram(allocator: std.mem.Allocator, _cfg: Args) !void {
test "RunOK" {
for ([_][]const u8{
"plain",
// "small",
// "dex",
"small",
"dex",
// "starknet",
// "starknet_with_keccak",
// "recursive_large_output",
"starknet_with_keccak",
"recursive_large_output",
"all_cairo",
// "all_solidity",
"all_solidity",
}) |layout| {
inline for ([_]bool{ false, true }) |memory_file| {
inline for ([_]bool{ false, true }) |_trace_file| {
Expand Down
13 changes: 7 additions & 6 deletions src/vm/air_input_public.zig
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
const std = @import("std");
const Felt252 = @import("starknet").fields.Felt252;
const RelocatedTraceEntry = @import("trace_context.zig").RelocatedTraceEntry;
const RelocatedFelt252 = @import("trace_context.zig").RelocatedFelt252;
const HintProcessor = @import("../hint_processor/hint_processor_def.zig").CairoVMHintProcessor;

const Config = @import("config.zig").Config;
Expand Down Expand Up @@ -117,15 +118,15 @@ pub const PublicInput = struct {
// new - creating new PublicInput, all arguments caller is owner
pub fn new(
allocator: std.mem.Allocator,
memory: []const ?Felt252,
memory: []const RelocatedFelt252,
layout: []const u8,
public_memory_addresses: []const std.meta.Tuple(&.{ usize, usize }),
memory_segment_addresses: std.StringHashMap(std.meta.Tuple(&.{ usize, usize })),
trace: []const RelocatedTraceEntry,
rc_limits: std.meta.Tuple(&.{ isize, isize }),
) !Self {
const memory_entry = (struct {
fn func(mem: []const ?Felt252, addresses: std.meta.Tuple(&.{ usize, usize })) !PublicMemoryEntry {
fn func(mem: []const RelocatedFelt252, addresses: std.meta.Tuple(&.{ usize, usize })) !PublicMemoryEntry {
const address, const page = addresses;
return .{
.address = address,
Expand Down Expand Up @@ -181,7 +182,7 @@ pub const PublicMemoryEntry = struct {
address: usize,
value: struct {
/// using struct only for json parse abstraction
value: ?Felt252,
value: RelocatedFelt252,

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

return .{ .value = Felt252.fromInt(u256, val) };
return .{ .value = RelocatedFelt252.init(Felt252.fromInt(u256, val)) };
},
inline .null => return .{
.value = null,
.value = RelocatedFelt252.NONE,
},
else => return error.UnexpectedToken,
}
}

pub fn jsonStringify(self: @This(), out: anytype) !void {
if (self.value) |v| try out.print("\"0x{x}\"", .{v.toU256()}) else try out.write(null);
if (self.value.getValue()) |v| try out.print("\"0x{x}\"", .{v.toU256()}) else try out.write(null);
}
},
page: usize,
Expand Down
12 changes: 5 additions & 7 deletions src/vm/cairo_run.zig
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,11 @@ pub fn writeEncodedTrace(relocated_trace: []const RelocatedTraceEntry, dest: any
///
/// - `relocated_memory`: The post-execution memory, relocated.
/// - `dest`: The destination file that the memory is to be written.
pub fn writeEncodedMemory(relocated_memory: []?Felt252, dest: anytype) !void {
pub fn writeEncodedMemory(relocated_memory: []RelocatedFelt252, dest: anytype) !void {
var buf: [8]u8 = undefined;

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


try runner.vm.verifyAutoDeductions(allocator);

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


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

var reader = file.reader();
var relocated_memory = std.ArrayList(?Felt252).init(allocator);
var relocated_memory = std.ArrayList(RelocatedFelt252).init(allocator);
defer relocated_memory.deinit();

// Relocated addresses start at 1,
// it's the law.
try relocated_memory.append(null);
try relocated_memory.append(RelocatedFelt252.NONE);

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

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

try relocated_memory.insert(idx, Felt252.fromInt(u256, value));
try relocated_memory.insert(idx, RelocatedFelt252.init(Felt252.fromInt(u256, value)));
}

// now we have the shape of a bonafide relocated memory,
Expand Down
8 changes: 4 additions & 4 deletions src/vm/core.zig
Original file line number Diff line number Diff line change
Expand Up @@ -492,10 +492,10 @@ pub const CairoVM = struct {
try self.opcodeAssertions(instruction, operands_result);

// Constants for offset bit manipulation.
const OFFSET = 1 << 15;
const off_0 = instruction.off_0 + OFFSET;
const off_1 = instruction.off_1 + OFFSET;
const off_2 = instruction.off_2 + OFFSET;
const OFFSET: u16 = 1 << 15;
const off_0 = @as(isize, instruction.off_0) + OFFSET;
const off_1 = @as(isize, instruction.off_1) + OFFSET;
const off_2 = @as(isize, instruction.off_2) + OFFSET;

// Calculate and update relocation limits.
self.rc_limits = if (self.rc_limits) |limits| .{
Expand Down
7 changes: 4 additions & 3 deletions src/vm/instructions.zig
Original file line number Diff line number Diff line change
Expand Up @@ -136,15 +136,16 @@ pub const Instruction = struct {
/// Offset 0
///
/// In the range [-2**15, 2*15) = [-2**(OFFSET_BITS-1), 2**(OFFSET_BITS-1)).
off_0: isize = 0,
/// 16 bit signed integer
off_0: i16 = 0,
/// Offset 1
///
/// In the range [-2**15, 2*15) = [-2**(OFFSET_BITS-1), 2**(OFFSET_BITS-1)).
off_1: isize = 0,
off_1: i16 = 0,
/// Offset 2
///
/// In the range [-2**15, 2*15) = [-2**(OFFSET_BITS-1), 2**(OFFSET_BITS-1)).
off_2: isize = 0,
off_2: i16 = 0,
/// Destination register.
dst_reg: Register = .FP,
/// Operand 0 register.
Expand Down
Loading

0 comments on commit 55d83e6

Please sign in to comment.