Skip to content

Commit

Permalink
throw exceptions with arguments without creating a GC frame
Browse files Browse the repository at this point in the history
  • Loading branch information
yuyichao committed May 17, 2015
1 parent 1b2f4fa commit 45260c8
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 0 deletions.
14 changes: 14 additions & 0 deletions base/base.jl
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@ convert{T}(::Type{Tuple{Vararg{T}}}, x::Tuple) = cnvt_all(T, x...)
cnvt_all(T) = ()
cnvt_all(T, x, rest...) = tuple(convert(T,x), cnvt_all(T, rest...)...)

macro _meta(args...)
Expr(:meta, args...)
end

macro generated(f)
isa(f, Expr) || error("invalid syntax; @generated must be used with a function definition")
if is(f.head, :function) || isdefined(:length) && is(f.head, :(=)) && length(f.args) == 2 && f.args[1].head == :call
Expand Down Expand Up @@ -159,6 +163,16 @@ type AssertionError <: Exception
AssertionError(msg) = new(msg)
end

throw_with_args(typ::ANY) = (@_meta(noinline); throw(typ()))
throw_with_args(typ::ANY, arg1) = (@_meta(noinline); throw(typ(arg1)))
throw_with_args(typ::ANY, arg1, arg2) =
(@_meta(noinline); throw(typ(arg1, arg2)))
throw_with_args(typ::ANY, arg1, arg2, arg3) =
(@_meta(noinline); throw(typ(arg1, arg2, arg3)))
throw_with_args(typ::ANY, arg1, arg2, arg3, arg4) =
(@_meta(noinline); throw(typ(arg1, arg2, arg3, arg4)))
throw_with_args(typ::ANY, args...) = throw(typ(args...))

# For passing constants through type inference
immutable Val{T}
end
Expand Down
14 changes: 14 additions & 0 deletions base/inference.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2200,6 +2200,20 @@ function inlineable(f::ANY, e::Expr, atype::ANY, sv::StaticVarInfo, enclosing_as
end
end
end
# Special case for throw. Use push the construction of the exception into
# a helper function to avoid creating a GC frame. This hack can be removed
# when codegen is smarter on inserting GC frames or if creating GC frames
# no longer affect performance.
if is(f, throw) && length(atypes) == 1 && isa(argexprs[1], Expr)
throw_expr::Expr = argexprs[1]
throw_args = throw_expr.args
if !is(throw_expr.head, :new)
return NF
end
expr = Expr(:call, TopNode(:throw_with_args), throw_args...)
expr.typ = Bottom
return (expr, ())
end
if isa(f,IntrinsicFunction)
return NF
end
Expand Down

0 comments on commit 45260c8

Please sign in to comment.