diff --git a/.travis.yml b/.travis.yml index 680f4b1..8112997 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,8 +3,9 @@ language: julia os: - linux julia: - - 0.7 - 1.0 + - 1.1 + - 1.2 - nightly matrix: allow_failures: diff --git a/src/overdub.jl b/src/overdub.jl index 7e8698f..404aa93 100644 --- a/src/overdub.jl +++ b/src/overdub.jl @@ -261,7 +261,7 @@ function overdub_pass!(reflection::Reflection, i >= original_code_start_index || return nothing stmt = Base.Meta.isexpr(x, :(=)) ? x.args[2] : x Base.Meta.isexpr(stmt, :replaceglobalref) && return 1 - if isa(stmt, Expr) # Base.Meta.isexpr(stmt, :call) || Base.Meta.isexpr(stmt, :new) || Base.Meta.isexpr(stmt, :return) + if isa(stmt, Expr) count = 0 for arg in stmt.args if Base.Meta.isexpr(arg, :replaceglobalref) @@ -280,7 +280,7 @@ function overdub_pass!(reflection::Reflection, globalref = stmt.args[2] name = QuoteNode(globalref.name) result = Expr(:call, Expr(:nooverdub, GlobalRef(Cassette, :tagged_globalref)), overdub_ctx_slot, tagmodssa, name, globalref) - elseif isa(stmt, Expr) # Base.Meta.isexpr(stmt, :call) || Base.Meta.isexpr(stmt, :new) || Base.Meta.isexpr(stmt, :return) + elseif isa(stmt, Expr) result = Expr(stmt.head) for arg in stmt.args if Base.Meta.isexpr(arg, :replaceglobalref) @@ -350,11 +350,13 @@ function overdub_pass!(reflection::Reflection, ]) end - #=== replace `Expr(:new, ...)` with `Expr(:call, :tagged_new)` if tagging is enabled ===# + #=== replace `Expr(:new, ...)`/`Expr(:splatnew, ...)` with ===# + #=== `Expr(:call, :tagged_new)`/`Expr(:call, :tagged_splatnew)` if tagging is enabled ===# if istaggingenabled && !iskwfunc - replace_match!(x -> Base.Meta.isexpr(x, :new), overdubbed_code) do x - return Expr(:call, Expr(:nooverdub, GlobalRef(Cassette, :tagged_new)), overdub_ctx_slot, x.args...) + replace_match!(x -> Base.Meta.isexpr(x, :new) || Base.Meta.isexpr(x, :splatnew), overdubbed_code) do x + tagged_version = x.head == :new ? :tagged_new : :tagged_splatnew + return Expr(:call, Expr(:nooverdub, GlobalRef(Cassette, tagged_version)), overdub_ctx_slot, x.args...) end end @@ -569,6 +571,7 @@ If `Cassette.hastagging(typeof(context))`, then a number of additional passes ar order to accomodate tagged value propagation: - `Expr(:new)` is replaced with a call to `Cassette.tagged_new` +- `Expr(:splatnew)` is replaced with a call to `Cassette.tagged_splatnew` - conditional values passed to `Expr(:gotoifnot)` are untagged - arguments to `Expr(:foreigncall)` are untagged - load/stores to external module bindings are intercepted by the tagging system diff --git a/src/tagging.jl b/src/tagging.jl index 13f5ae6..42361b4 100644 --- a/src/tagging.jl +++ b/src/tagging.jl @@ -460,9 +460,9 @@ destructstate(ctx, state) = untag(state, ctx) Base.iterate(t::Tagged) = destructstate(t.context, overdub(t.context, iterate, t)) Base.iterate(t::Tagged, state) = destructstate(t.context, overdub(t.context, iterate, t, state)) -################ -# `tagged_new` # -################ +################################## +# `tagged_new`/`tagged_splatnew` # +################################## @generated function tagged_new(context::C, ::Type{T}, args...) where {C<:Context,T} argmetaexprs = Any[] @@ -493,6 +493,8 @@ Base.iterate(t::Tagged, state) = destructstate(t.context, overdub(t.context, ite end end +@inline tagged_splatnew(context::Context, T::Type, args) = tagged_new(context, T, args...) + @generated function tagged_new_array(context::C, ::Type{T}, args...) where {C<:Context,T<:Array} untagged_args = [:(untag(args[$i], context)) for i in 1:nfields(args)] return quote