Skip to content

Commit

Permalink
Keep StackPool as main interface (now storing Fiber::Stack)
Browse files Browse the repository at this point in the history
  • Loading branch information
ysbaddaden committed Feb 10, 2025
1 parent 9d9d079 commit aae3498
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 27 deletions.
4 changes: 2 additions & 2 deletions src/compiler/crystal/interpreter/context.cr
Original file line number Diff line number Diff line change
Expand Up @@ -106,10 +106,10 @@ class Crystal::Repl::Context
# Once the block returns, the stack is returned to the pool.
# The stack is not cleared after or before it's used.
def checkout_stack(& : UInt8* -> _)
stack, _ = @stack_pool.checkout
stack = @stack_pool.checkout

begin
yield stack.as(UInt8*)
yield stack.pointer.as(UInt8*)
ensure
@stack_pool.release(stack)
end
Expand Down
11 changes: 9 additions & 2 deletions src/fiber.cr
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,14 @@ class Fiber
#
# *name* is an optional and used only as an internal reference.
def self.new(name : String? = nil, &proc : ->)
new(name, Stack.new, &proc)
stack =
{% if flag?(:interpreted) %}
# the interpreter is managing the stacks
Stack.new(Pointer(Void).null, 0)
{% else %}
Crystal::Scheduler.stack_pool.checkout
{% end %}
new(name, stack, &proc)
end

# :nodoc:
Expand Down Expand Up @@ -159,7 +166,7 @@ class Fiber

@alive = false
{% unless flag?(:interpreted) %}
@stack.release
Crystal::Scheduler.stack_pool.release(@stack)
{% end %}
Fiber.suspend
end
Expand Down
23 changes: 9 additions & 14 deletions src/fiber/stack.cr
Original file line number Diff line number Diff line change
Expand Up @@ -2,29 +2,24 @@ class Fiber
# :nodoc:
struct Stack
getter pointer : Void*
getter bottom : Void*
getter bytesize : Int32
getter? reusable : Bool

def self.new : self
{% if flag?(:interpreted) %}
new Pointer(Void).null, Pointer(Void).null
{% else %}
stack, stack_bottom = Crystal::Scheduler.stack_pool.checkout
new(stack, stack_bottom, reusable: true)
{% end %}
def initialize(@pointer, bottom : Void*, *, @reusable = false)
@bytesize = (bottom - @pointer).to_i32
end

def initialize(@pointer, @bottom, *, @reusable = false)
def initialize(@pointer, @bytesize, *, @reusable = false)
end

def bottom : Void*
@pointer + @bytesize
end

def first_addressable_pointer : Void**
ptr = @bottom # stacks grow down
ptr = bottom # stacks grow down
ptr -= sizeof(Void*) # point to first addressable pointer
Pointer(Void*).new(ptr.address & ~15_u64) # align to 16 bytes
end

def release : Nil
Crystal::Scheduler.stack_pool.release(@pointer) if @reusable
end
end
end
19 changes: 10 additions & 9 deletions src/fiber/stack_pool.cr
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@ class Fiber
# Interpreter stacks grow upwards (pushing values increases the stack
# pointer value) rather than downwards, so *protect* must be false.
def initialize(@protect : Bool = true)
@deque = Deque(Void*).new
@deque = Deque(Stack).new
end

def finalize
@deque.each do |stack|
Crystal::System::Fiber.free_stack(stack, STACK_SIZE)
Crystal::System::Fiber.free_stack(stack.pointer, stack.bytesize)
end
end

Expand All @@ -26,7 +26,7 @@ class Fiber
def collect(count = lazy_size // 2) : Nil
count.times do
if stack = @deque.shift?
Crystal::System::Fiber.free_stack(stack, STACK_SIZE)
Crystal::System::Fiber.free_stack(stack.pointer, stack.bytesize)
else
return
end
Expand All @@ -41,18 +41,19 @@ class Fiber
end

# Removes a stack from the bottom of the pool, or allocates a new one.
def checkout : {Void*, Void*}
def checkout : Stack
if stack = @deque.pop?
Crystal::System::Fiber.reset_stack(stack, STACK_SIZE, @protect)
Crystal::System::Fiber.reset_stack(stack.pointer, stack.bytesize, @protect)
stack
else
stack = Crystal::System::Fiber.allocate_stack(STACK_SIZE, @protect)
pointer = Crystal::System::Fiber.allocate_stack(STACK_SIZE, @protect)
Stack.new(pointer, STACK_SIZE)
end
{stack, stack + STACK_SIZE}
end

# Appends a stack to the bottom of the pool.
def release(stack) : Nil
@deque.push(stack)
def release(stack : Stack) : Nil
@deque.push(stack) if stack.reusable?
end

# Returns the approximated size of the pool. It may be equal or slightly
Expand Down

0 comments on commit aae3498

Please sign in to comment.