Skip to content

Commit

Permalink
Merge pull request #32 from JuliaDebug/teh/sigs
Browse files Browse the repository at this point in the history
More correctness fixes
  • Loading branch information
timholy authored Feb 15, 2019
2 parents 2af2cb4 + 8d24c64 commit e2f5344
Show file tree
Hide file tree
Showing 6 changed files with 101 additions and 34 deletions.
29 changes: 13 additions & 16 deletions src/JuliaInterpreter.jl
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,12 @@ Tuple{typeof(mymethod),Array{Float64,1}}
```
"""
function prepare_call(@nospecialize(f), allargs; enter_generated = false)
# Can happen for thunks created by generated functions
if isa(f, Core.Builtin) || isa(f, Core.IntrinsicFunction)
return nothing
elseif any(x->isa(x, Type) && x <: Vararg, allargs)
return nothing # https://github.com/JuliaLang/julia/issues/30995
end
argtypes = Tuple{map(_Typeof,allargs)...}
method = whichtt(argtypes)
if method === nothing
Expand Down Expand Up @@ -376,12 +382,6 @@ function determine_method_for_expr(expr; enter_generated = false)
kwargs = splice!(allargs, 2)
end
f, allargs = prepare_args(f, allargs, kwargs.args)
# Can happen for thunks created by generated functions
if isa(f, Core.Builtin) || isa(f, Core.IntrinsicFunction)
return nothing
elseif f === getproperty && allargs[2] isa Type && allargs[2] <: Vararg
return nothing # https://github.com/JuliaLang/julia/issues/30995
end
return prepare_call(f, allargs; enter_generated=enter_generated)
end

Expand Down Expand Up @@ -417,7 +417,11 @@ function extract_inner_call!(stmt, idx, once::Bool=false)
once |= stmt.head calllike
for (i, a) in enumerate(stmt.args)
isa(a, Expr) || continue
if stmt.head == :foreigncall && i == 1
# Make sure we don't "damage" special syntax that requires literals
if i == 1 && stmt.head == :foreigncall
continue
end
if i == 2 && stmt.head == :call && stmt.args[1] == :cglobal
continue
end
ret = extract_inner_call!(a, idx, once) # doing this first extracts innermost calls
Expand Down Expand Up @@ -497,15 +501,8 @@ function optimize!(code::CodeInfo, mod::Module)
if isa(stmt, GlobalRef)
code.code[i] = QuoteNode(getfield(stmt.mod, stmt.name))
elseif isa(stmt, Expr)
if stmt.head == :call && isa(stmt.args[1], GlobalRef)
# Special handling of cglobal, which requires constants for its arguments
r = stmt.args[1]::GlobalRef
f = getfield(r.mod, r.name)
if f === Base.cglobal
code.code[i] = QuoteNode(Core.eval(mod, stmt))
else
lookup_global_refs!(stmt)
end
if stmt.head == :call && stmt.args[1] == :cglobal # cglobal requires literals
continue
else
lookup_global_refs!(stmt)
end
Expand Down
14 changes: 14 additions & 0 deletions src/generate_builtins.jl
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,20 @@ function maybe_evaluate_builtin(frame, call_expr)
isdefined(Base, fsym) || (println("skipping ", fname); continue)
f = getfield(Base, fsym)
f isa Core.IntrinsicFunction || error("not an intrinsic")
if f == cglobal
print(io,
"""
elseif f === Base.cglobal
if nargs == 1
return Some{Any}(Core.eval(moduleof(frame), call_expr))
elseif nargs == 2
call_expr = copy(call_expr)
call_expr.args[3] = @lookup(frame, args[3])
return Some{Any}(Core.eval(moduleof(frame), call_expr))
end
""")
continue
end
id = reinterpret(Int32, f) + 1
f = isdefined(Base, fsym) ? "Base.$fsym" :
isdefined(Core, fsym) ? "Core.$fsym" : error("whoops on $f")
Expand Down
6 changes: 3 additions & 3 deletions src/interpret.jl
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ function evaluate_methoddef!(stack, frame, node, pc)
end
length(node.args) == 1 && return f
sig = @lookup(frame, node.args[2])::SimpleVector
body = @lookup(frame, node.args[3])::CodeInfo
body = @lookup(frame, node.args[3])
ccall(:jl_method_def, Cvoid, (Any, Any, Any), sig, body, moduleof(frame))
return nothing
end
Expand Down Expand Up @@ -303,8 +303,8 @@ function eval_rhs(stack, frame, node::Expr, pc)
elseif head == :foreigncall
return evaluate_foreigncall!(stack, frame, node, pc)
elseif head == :copyast
qn = node.args[1]::QuoteNode
return copy(qn.value::Expr)
val = (node.args[1]::QuoteNode).value
return isa(val, Expr) ? copy(val) : val
elseif head == :enter
return length(frame.exception_frames)
elseif head == :boundscheck
Expand Down
17 changes: 2 additions & 15 deletions src/localmethtable.jl
Original file line number Diff line number Diff line change
Expand Up @@ -48,22 +48,9 @@ function get_call_framecode(fargs, parentframe::JuliaFrameCode, idx::Int)
end
# We haven't yet encountered this argtype combination and need to look it up by dispatch
fargs[1] = f = to_function(fargs[1])
if isa(f, Core.Builtin)
# See TODO in optimize!
return f(fargs[2:end]...), nothing # for code that has a direct call to a builtin
end
if f === getproperty && isa(fargs[2], Type) && fargs[2] <: Vararg # https://github.com/JuliaLang/julia/issues/30995
return getproperty(fargs[2:end]...), nothing
end
# HACK: don't recurse into inference. Inference sometimes returns SSAValue objects and this
# seems to confuse lookup_var.
if f === Base._return_type
return Base._return_type(fargs[2:end]...), nothing
end
ret = prepare_call(f, fargs)
if isa(ret, Compiled)
return ret, nothing
end
ret === nothing && return f(fargs[2:end]...), nothing
isa(ret, Compiled) && return ret, nothing
framecode, args, env, argtypes = ret
# Store the results of the method lookup in the local method table
tme = ccall(:jl_new_struct_uninit, Any, (Any,), TypeMapEntry)::TypeMapEntry
Expand Down
40 changes: 40 additions & 0 deletions test/interpret.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ using JuliaInterpreter
using JuliaInterpreter: enter_call_expr
using Test

module Isolated end

function summer(A)
s = zero(eltype(A))
Expand Down Expand Up @@ -96,6 +97,8 @@ end
@test @interpret(Vararg.body.body.name) === Vararg.body.body.name
frame = JuliaInterpreter.prepare_toplevel(Main, :(Vararg.body.body.name))
@test JuliaInterpreter.finish_and_return!(JuliaStackFrame[], frame, true) === Vararg.body.body.name
frame = JuliaInterpreter.prepare_toplevel(Base, :(Union{AbstractChar,Tuple{Vararg{<:AbstractChar}},AbstractVector{<:AbstractChar},Set{<:AbstractChar}}))
@test JuliaInterpreter.finish_and_return!(JuliaStackFrame[], frame, true) isa Union

# issue #8
ex = quote
Expand Down Expand Up @@ -156,3 +159,40 @@ ex = quote
end
frame = JuliaInterpreter.prepare_toplevel(Main, ex)
@test JuliaInterpreter.finish_and_return!(JuliaStackFrame[], frame, true) == 1

# copyast
ex = quote
struct CodegenParams
cached::Cint

track_allocations::Cint
code_coverage::Cint
static_alloc::Cint
prefer_specsig::Cint

module_setup::Any
module_activation::Any
raise_exception::Any
emit_function::Any
emitted_function::Any

CodegenParams(;cached::Bool=true,
track_allocations::Bool=true, code_coverage::Bool=true,
static_alloc::Bool=true, prefer_specsig::Bool=false,
module_setup=nothing, module_activation=nothing, raise_exception=nothing,
emit_function=nothing, emitted_function=nothing) =
new(Cint(cached),
Cint(track_allocations), Cint(code_coverage),
Cint(static_alloc), Cint(prefer_specsig),
module_setup, module_activation, raise_exception,
emit_function, emitted_function)
end
end
frame = JuliaInterpreter.prepare_toplevel(Isolated, ex)
JuliaInterpreter.finish_and_return!(JuliaStackFrame[], frame, true)
@test Isolated.CodegenParams(cached=false).cached === Cint(false)

# cglobal
val = @interpret(BigInt())
@test isa(val, BigInt) && val == 0
@test isa(@interpret(Base.GMP.version()), VersionNumber)
29 changes: 29 additions & 0 deletions test/toplevel.jl
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,21 @@ module Toplevel end
@test Toplevel.Testing.JuliaStackFrame === JuliaStackFrame
end

@testset "Enum" begin
ex = quote
@enum MPFRRoundingMode begin
MPFRRoundNearest
MPFRRoundToZero
MPFRRoundUp
MPFRRoundDown
MPFRRoundFromZero
MPFRRoundFaithful
end
end
frame = JuliaInterpreter.prepare_toplevel(Toplevel, ex)
@test_broken JuliaInterpreter.finish_and_return!(JuliaStackFrame[], frame, true)
end

module LowerAnon
ret = Ref{Any}(nothing)
end
Expand All @@ -176,4 +191,18 @@ end
lower_incrementally(runtest, LowerAnon, ex2)
@test isa(LowerAnon.ret[], Vector{Int16})
LowerAnon.ret[] = nothing

ex3 = quote
const BitIntegerType = Union{map(T->Type{T}, Base.BitInteger_types)...}
end
lower_incrementally(runtest, LowerAnon, ex3)
@test isa(LowerAnon.BitIntegerType, Union)

ex4 = quote
y = 3
z = map(x->x^2+y, [1,2,3])
y = 4
end
lower_incrementally(runtest, LowerAnon, ex4)
@test LowerAnon.z == [4,7,12]
end

0 comments on commit e2f5344

Please sign in to comment.