diff --git a/src/regex/lib_pcre2.cr b/src/regex/lib_pcre2.cr index 71a0fd4b6639..6aac03da9f47 100644 --- a/src/regex/lib_pcre2.cr +++ b/src/regex/lib_pcre2.cr @@ -241,18 +241,20 @@ lib LibPCRE2 CONFIG_TABLES_LENGTH = 15 type Code = Void - type CompileContext = Void type MatchData = Void type GeneralContext = Void + type CompileContext = Void + type MatchContext = Void + + fun general_context_create = pcre2_general_context_create_8(private_malloc : (LibC::SizeT, Void*) -> Void*, private_free : (Void*, Void*) -> Void, memory_data : Void*) : GeneralContext* + fun compile_context_create = pcre2_compile_context_create_8(gcontext : GeneralContext*) : CompileContext* + fun match_context_create = pcre2_match_context_create_8(gcontext : GeneralContext*) : MatchContext* fun get_error_message = pcre2_get_error_message_8(errorcode : Int, buffer : UInt8*, bufflen : LibC::SizeT) : Int fun compile = pcre2_compile_8(pattern : UInt8*, length : LibC::SizeT, options : UInt32, errorcode : Int*, erroroffset : LibC::SizeT*, ccontext : CompileContext*) : Code* fun code_free = pcre2_code_free_8(code : Code*) : Void - type MatchContext = Void* - fun match_context_create = pcre2_match_context_create_8(gcontext : Void*) : MatchContext* - fun jit_compile = pcre2_jit_compile_8(code : Code*, options : UInt32) : Int type JITStack = Void diff --git a/src/regex/pcre2.cr b/src/regex/pcre2.cr index 19416723af24..4dca61e395b7 100644 --- a/src/regex/pcre2.cr +++ b/src/regex/pcre2.cr @@ -45,7 +45,7 @@ module Regex::PCRE2 end protected def self.compile(source, options, &) - if res = LibPCRE2.compile(source, source.bytesize, options, out errorcode, out erroroffset, nil) + if res = LibPCRE2.compile(source, source.bytesize, options, out errorcode, out erroroffset, compile_context) res else message = get_error_message(errorcode) @@ -153,8 +153,6 @@ module Regex::PCRE2 return error_message end - LibPCRE2.code_free code - nil end @@ -225,11 +223,22 @@ module Regex::PCRE2 end class_getter match_context : LibPCRE2::MatchContext* do - match_context = LibPCRE2.match_context_create(nil) + match_context = LibPCRE2.match_context_create(general_context) LibPCRE2.jit_stack_assign(match_context, ->(_data) { Regex::PCRE2.jit_stack }, nil) match_context end + class_getter compile_context : LibPCRE2::CompileContext* do + LibPCRE2.compile_context_create(general_context) + end + + # Context for all memory allocations done by PCRE2. + # + # Use our GC for allocation, so deallocation and finalizers are no longer necessary. + class_getter general_context : LibPCRE2::GeneralContext* do + LibPCRE2.general_context_create(->(size, data) { GC.malloc(size) }, ->(ptr, data) {}, nil) + end + # Returns a JIT stack that's shared in the current thread. # # Only a single `match` function can run per thread at any given time, so there @@ -238,7 +247,7 @@ module Regex::PCRE2 def self.jit_stack @@jit_stack.get do - LibPCRE2.jit_stack_create(32_768, 1_048_576, nil) || raise "Error allocating JIT stack" + LibPCRE2.jit_stack_create(32_768, 1_048_576, general_context) || raise "Error allocating JIT stack" end end @@ -250,15 +259,8 @@ module Regex::PCRE2 private def match_data @match_data.get do - LibPCRE2.match_data_create_from_pattern(@re, nil) - end - end - - def finalize - @match_data.consume_each do |match_data| - LibPCRE2.match_data_free(match_data) + LibPCRE2.match_data_create_from_pattern(@re, Regex::PCRE2.general_context) end - LibPCRE2.code_free @re end private def match_data(str, byte_index, options)