More fixes

This commit is contained in:
Alexandros Naskos 2020-06-30 18:00:33 +03:00
parent 671318730a
commit b3006745a0
2 changed files with 82 additions and 51 deletions

View File

@ -89,17 +89,40 @@ pub fn init(base_allocator: *std.mem.Allocator, max_bytes: usize) DebugAllocator
.info = .{}, .info = .{},
.max_bytes = max_bytes, .max_bytes = max_bytes,
.allocator = .{ .allocator = .{
.reallocFn = realloc, .allocFn = alloc,
.shrinkFn = shrink, .resizeFn = resize,
}, },
}; };
} }
fn realloc(allocator: *std.mem.Allocator, old_mem: []u8, old_align: u29, new_size: usize, new_align: u29) ![]u8 { fn alloc(allocator: *std.mem.Allocator, len: usize, ptr_align: u29, len_align: u29) error{OutOfMemory}![]u8 {
const self = @fieldParentPtr(DebugAllocator, "allocator", allocator); const self = @fieldParentPtr(DebugAllocator, "allocator", allocator);
var data = try self.base_allocator.reallocFn(self.base_allocator, old_mem, old_align, new_size, new_align); const ptr = try self.base_allocator.callAllocFn(len, ptr_align, len_align);
self.info.allocation_stats.addSample(ptr.len);
const curr_allocs = self.info.currentlyAllocated();
if (self.max_bytes != 0 and curr_allocs >= self.max_bytes) {
std.debug.print("Exceeded maximum bytes {}, exiting.\n", .{self.max_bytes});
std.process.exit(1);
}
if (curr_allocs > self.info.peak_allocated) {
self.info.peak_allocated = curr_allocs;
}
return ptr;
}
fn resize(allocator: *std.mem.Allocator, old_mem: []u8, new_size: usize, len_align: u29) error{OutOfMemory}!usize {
const self = @fieldParentPtr(DebugAllocator, "allocator", allocator);
if (old_mem.len == 0) { if (old_mem.len == 0) {
self.info.allocation_stats.addSample(new_size); self.info.allocation_stats.addSample(new_size);
} else if (new_size == 0) {
if (self.info.allocation_stats.count == self.info.deallocation_count) {
@panic("error - too many calls to free, most likely double free");
}
self.info.deallocation_total += old_mem.len;
self.info.deallocation_count += 1;
} else if (new_size > old_mem.len) { } else if (new_size > old_mem.len) {
self.info.reallocation_stats.addSample(new_size - old_mem.len); self.info.reallocation_stats.addSample(new_size - old_mem.len);
} else if (new_size < old_mem.len) { } else if (new_size < old_mem.len) {
@ -115,21 +138,8 @@ fn realloc(allocator: *std.mem.Allocator, old_mem: []u8, old_align: u29, new_siz
if (curr_allocs > self.info.peak_allocated) { if (curr_allocs > self.info.peak_allocated) {
self.info.peak_allocated = curr_allocs; self.info.peak_allocated = curr_allocs;
} }
return data;
}
fn shrink(allocator: *std.mem.Allocator, old_mem: []u8, old_align: u29, new_size: usize, new_align: u29) []u8 { return self.base_allocator.callResizeFn(old_mem, new_size, len_align) catch |e| {
const self = @fieldParentPtr(DebugAllocator, "allocator", allocator); return e;
if (new_size == 0) { };
if (self.info.allocation_stats.count == self.info.deallocation_count) {
@panic("error - too many calls to free, most likely double free");
}
self.info.deallocation_total += old_mem.len;
self.info.deallocation_count += 1;
} else if (new_size < old_mem.len) {
self.info.shrink_stats.addSample(old_mem.len - new_size);
} else if (new_size > old_mem.len) {
@panic("error - trying to shrink to a bigger size");
}
return self.base_allocator.shrinkFn(self.base_allocator, old_mem, old_align, new_size, new_align);
} }

View File

@ -1033,6 +1033,8 @@ fn workspaceFoldersChangeHandler(arena: *std.heap.ArenaAllocator, id: types.Requ
fn openDocumentHandler(arena: *std.heap.ArenaAllocator, id: types.RequestId, req: requests.OpenDocument, config: Config) !void { fn openDocumentHandler(arena: *std.heap.ArenaAllocator, id: types.RequestId, req: requests.OpenDocument, config: Config) !void {
const handle = try document_store.openDocument(req.params.textDocument.uri, req.params.textDocument.text); const handle = try document_store.openDocument(req.params.textDocument.uri, req.params.textDocument.text);
try publishDiagnostics(arena, handle.*, configFromUriOr(req.params.textDocument.uri, config)); try publishDiagnostics(arena, handle.*, configFromUriOr(req.params.textDocument.uri, config));
try semanticTokensHandler(arena, id, .{ .params = .{ .textDocument = .{ .uri = req.params.textDocument.uri } } }, config);
} }
fn changeDocumentHandler(arena: *std.heap.ArenaAllocator, id: types.RequestId, req: requests.ChangeDocument, config: Config) !void { fn changeDocumentHandler(arena: *std.heap.ArenaAllocator, id: types.RequestId, req: requests.ChangeDocument, config: Config) !void {
@ -1046,7 +1048,7 @@ fn changeDocumentHandler(arena: *std.heap.ArenaAllocator, id: types.RequestId, r
try publishDiagnostics(arena, handle.*, local_config); try publishDiagnostics(arena, handle.*, local_config);
} }
fn saveDocumentHandler(arena: *std.heap.ArenaAllocator, id: types.RequestId, req: requests.SaveDocument, config: Config) !void { fn saveDocumentHandler(arena: *std.heap.ArenaAllocator, id: types.RequestId, req: requests.SaveDocument, config: Config) error{OutOfMemory}!void {
const handle = document_store.getHandle(req.params.textDocument.uri) orelse { const handle = document_store.getHandle(req.params.textDocument.uri) orelse {
std.log.debug(.main, "Trying to save non existent document {}", .{req.params.textDocument.uri}); std.log.debug(.main, "Trying to save non existent document {}", .{req.params.textDocument.uri});
return; return;
@ -1054,13 +1056,11 @@ fn saveDocumentHandler(arena: *std.heap.ArenaAllocator, id: types.RequestId, req
try document_store.applySave(handle); try document_store.applySave(handle);
} }
fn closeDocumentHandler(arena: *std.heap.ArenaAllocator, id: types.RequestId, req: requests.CloseDocument, config: Config) !void { fn closeDocumentHandler(arena: *std.heap.ArenaAllocator, id: types.RequestId, req: requests.CloseDocument, config: Config) error{}!void {
std.log.debug(.main, "CLOSING DOCUMENT!!!, id: {}\n", .{id});
document_store.closeDocument(req.params.textDocument.uri); document_store.closeDocument(req.params.textDocument.uri);
} }
fn semanticTokensHandler(arena: *std.heap.ArenaAllocator, id: types.RequestId, req: requests.SemanticTokens, config: Config) !void { fn semanticTokensHandler(arena: *std.heap.ArenaAllocator, id: types.RequestId, req: requests.SemanticTokens, config: Config) (error{OutOfMemory} || std.fs.File.WriteError)!void {
const this_config = configFromUriOr(req.params.textDocument.uri, config); const this_config = configFromUriOr(req.params.textDocument.uri, config);
if (this_config.enable_semantic_tokens) { if (this_config.enable_semantic_tokens) {
const handle = document_store.getHandle(req.params.textDocument.uri) orelse { const handle = document_store.getHandle(req.params.textDocument.uri) orelse {
@ -1262,6 +1262,12 @@ fn renameHandler(arena: *std.heap.ArenaAllocator, id: types.RequestId, req: requ
} }
} }
// Needed for the hack seen below.
fn extractErr(val: var) anyerror {
val catch |e| return e;
return error.HackDone;
}
fn processJsonRpc(arena: *std.heap.ArenaAllocator, parser: *std.json.Parser, json: []const u8, config: Config) !void { fn processJsonRpc(arena: *std.heap.ArenaAllocator, parser: *std.json.Parser, json: []const u8, config: Config) !void {
var tree = try parser.parse(json); var tree = try parser.parse(json);
defer tree.deinit(); defer tree.deinit();
@ -1305,28 +1311,34 @@ fn processJsonRpc(arena: *std.heap.ArenaAllocator, parser: *std.json.Parser, jso
.{ "textDocument/rename", requests.Rename, renameHandler }, .{ "textDocument/rename", requests.Rename, renameHandler },
}; };
// Hack to avoid `return`ing in the inline for, which causes bugs.
var done: ?anyerror = null;
inline for (method_map) |method_info| { inline for (method_map) |method_info| {
if (std.mem.eql(u8, method, method_info[0])) { if (done == null and std.mem.eql(u8, method, method_info[0])) {
if (method_info.len == 1) { if (method_info.len == 1) {
return; done = error.HackDone;
} else if (method_info[1] != void) { } else if (method_info[1] != void) {
const request_obj = requests.fromDynamicTree(arena, method_info[1], tree.root) catch |err| { const ReqT = method_info[1];
switch (err) { if (requests.fromDynamicTree(arena, ReqT, tree.root)) |request_obj| {
error.MalformedJson => { done = error.HackDone;
std.log.debug(.main, "Could not create request type {} from JSON {}\n", .{ @typeName(method_info[1]), json }); done = extractErr(method_info[2](arena, id, request_obj, config));
return try respondGeneric(id, null_result_response); } else |err| {
}, if (err == error.MalformedJson) {
error.OutOfMemory => return err, std.log.debug(.main, "Could not create request type {} from JSON {}\n", .{ @typeName(ReqT), json });
}
done = err;
} }
};
std.log.debug(.TEMPORARY, "{} {}\n", .{method, method_info[0]});
return try (method_info[2])(arena, id, request_obj, config);
} else { } else {
return try (method_info[2])(arena, id, config); done = error.HackDone;
(method_info[2])(arena, id, config) catch |err| { done = err; };
} }
} }
} }
if (done) |err| switch (err) {
error.MalformedJson => return try respondGeneric(id, null_result_response),
error.HackDone => return,
else => return err,
};
const unimplemented_map = std.ComptimeStringMap(void, .{ const unimplemented_map = std.ComptimeStringMap(void, .{
.{"textDocument/references"}, .{"textDocument/references"},
@ -1380,7 +1392,16 @@ pub fn main() anyerror!void {
// Read the configuration, if any. // Read the configuration, if any.
const config_parse_options = std.json.ParseOptions{ .allocator = allocator }; const config_parse_options = std.json.ParseOptions{ .allocator = allocator };
var config = Config{}; var config = Config{};
defer std.json.parseFree(Config, config, config_parse_options); var config_had_null_zig_path = config.zig_exe_path == null;
defer {
if (config_had_null_zig_path) {
if (config.zig_exe_path) |exe_path| {
allocator.free(exe_path);
config.zig_exe_path = null;
}
}
std.json.parseFree(Config, config, config_parse_options);
}
config_read: { config_read: {
const known_folders = @import("known-folders"); const known_folders = @import("known-folders");
@ -1437,7 +1458,7 @@ pub fn main() anyerror!void {
defer allocator.free(full_path); defer allocator.free(full_path);
var buf: [std.fs.MAX_PATH_BYTES]u8 = undefined; var buf: [std.fs.MAX_PATH_BYTES]u8 = undefined;
zig_exe_path = std.os.realpath(full_path, &buf) catch continue; zig_exe_path = try std.mem.dupe(allocator, u8, std.os.realpath(full_path, &buf) catch continue);
std.log.debug(.main, "Found zig in PATH: {}\n", .{zig_exe_path}); std.log.debug(.main, "Found zig in PATH: {}\n", .{zig_exe_path});
break :find_zig; break :find_zig;
} }