Skip to content

Commit

Permalink
make eval and method_exists no longer builtins
Browse files Browse the repository at this point in the history
switch `arraylen` from builtin to intrinsic
  • Loading branch information
JeffBezanson committed Oct 25, 2015
1 parent 37dad15 commit f1664bc
Show file tree
Hide file tree
Showing 19 changed files with 64 additions and 99 deletions.
11 changes: 7 additions & 4 deletions base/boot.jl
Original file line number Diff line number Diff line change
Expand Up @@ -147,15 +147,15 @@ export
Expr, GotoNode, LabelNode, LineNumberNode, QuoteNode, SymbolNode, TopNode,
GlobalRef, NewvarNode, GenSym,
# object model functions
fieldtype, getfield, setfield!, nfields, throw, tuple, is, ===, isdefined,
# arraylen, arrayref, arrayset, arraysize,
fieldtype, getfield, setfield!, nfields, throw, tuple, is, ===, isdefined, eval,
# arrayref, arrayset, arraysize,
# _apply, kwcall,
# sizeof # not exported, to avoid conflicting with Base.sizeof
# type reflection
issubtype, typeof, isa,
# typeassert, apply_type,
# method reflection
applicable, invoke, method_exists,
applicable, invoke,
# constants
nothing, Main,
# intrinsics module
Expand All @@ -174,7 +174,7 @@ export
#mul_int, ne_float, ne_int, neg_float, neg_int, not_int, or_int, rem_float,
#sdiv_int, shl_int, sitofp, sle_int, slt_int, smod_int,
#srem_int, sub_float, sub_int, trunc_int, udiv_int, uitofp,
#ule_int, ult_int, unbox, urem_int, xor_int, sext_int, zext_int
#ule_int, ult_int, unbox, urem_int, xor_int, sext_int, zext_int, arraylen


const (===) = is
Expand Down Expand Up @@ -260,6 +260,9 @@ typealias ByteString Union{ASCIIString,UTF8String}

include(fname::ByteString) = ccall(:jl_load_, Any, (Any,), fname)

eval(e::ANY) = eval(Main, e)
eval(m::Module, e::ANY) = ccall(:jl_toplevel_eval_in, Any, (Any, Any), m, e)

# constructors for built-in types

type WeakRef
Expand Down
2 changes: 1 addition & 1 deletion base/coreimg.jl
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# This file is a part of Julia. License is MIT: https://julialang.org/license

Main.Core.eval(Main.Core, :(baremodule Inference
using Core: Intrinsics, arraylen, arrayref, arrayset, arraysize, _expr,
using Core: Intrinsics, arrayref, arrayset, arraysize, _expr,
kwcall, _apply, typeassert, apply_type, svec
ccall(:jl_set_istopmod, Void, (Bool,), false)

Expand Down
1 change: 1 addition & 0 deletions base/exports.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1084,6 +1084,7 @@ export
isgeneric,
isinteractive,
less,
method_exists,
methods,
methodswith,
module_name,
Expand Down
5 changes: 2 additions & 3 deletions base/inference.jl
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ cmp_tfunc = (x,y)->Bool
isType(t::ANY) = isa(t,DataType) && is((t::DataType).name,Type.name)

const IInf = typemax(Int) # integer infinity
const n_ifunc = reinterpret(Int32,llvmcall)+1
const n_ifunc = reinterpret(Int32,arraylen)+1
const t_ifunc = Array{Tuple{Int,Int,Function},1}(n_ifunc)
const t_ffunc_key = Array{Function,1}(0)
const t_ffunc_val = Array{Tuple{Int,Int,Function},1}(0)
Expand Down Expand Up @@ -162,16 +162,15 @@ add_tfunc(eval(Core.Intrinsics,:cglobal), 1, 2,
add_tfunc(eval(Core.Intrinsics,:select_value), 3, 3,
# TODO: return Bottom if cnd is definitely not a Bool
(cnd, x, y)->Union{x,y})
add_tfunc(eval(Core.Intrinsics,:arraylen), 1, 1, x->Int)
add_tfunc(is, 2, 2, cmp_tfunc)
add_tfunc(issubtype, 2, 2, cmp_tfunc)
add_tfunc(isa, 2, 2, cmp_tfunc)
add_tfunc(isdefined, 1, IInf, (args...)->Bool)
add_tfunc(Core.sizeof, 1, 1, x->Int)
add_tfunc(nfields, 1, 1, x->Int)
add_tfunc(_expr, 1, IInf, (args...)->Expr)
add_tfunc(method_exists, 2, 2, cmp_tfunc)
add_tfunc(applicable, 1, IInf, (f, args...)->Bool)
add_tfunc(arraylen, 1, 1, x->Int)
#add_tfunc(arrayref, 2,IInf,(a,i...)->(isa(a,DataType) && a<:Array ?
# a.parameters[1] : Any))
#add_tfunc(arrayset, 3, IInf, (a,v,i...)->a)
Expand Down
11 changes: 11 additions & 0 deletions base/reflection.jl
Original file line number Diff line number Diff line change
Expand Up @@ -345,3 +345,14 @@ function function_module(f, types::ANY)
end
m[1].func.code.module
end

function method_exists(f::ANY, t::ANY)
t = to_tuple_type(t)
if !isa(f,Function)
t = Tuple{isa(f,Type) ? Type{f} : typeof(f), t.parameters...}
f = call
elseif !isgeneric(f)
throw(ArgumentError("argument is not a generic function"))
end
return ccall(:jl_method_exists, Cint, (Any, Any), f.env, t) != 0
end
2 changes: 1 addition & 1 deletion base/sysimg.jl
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import Core.Intrinsics.ccall

baremodule Base

using Core: Intrinsics, arraylen, arrayref, arrayset, arraysize, _expr,
using Core: Intrinsics, arrayref, arrayset, arraysize, _expr,
kwcall, _apply, typeassert, apply_type, svec
ccall(:jl_set_istopmod, Void, (Bool,), true)

Expand Down
7 changes: 0 additions & 7 deletions src/array.c
Original file line number Diff line number Diff line change
Expand Up @@ -404,13 +404,6 @@ DLLEXPORT size_t jl_array_len_(jl_array_t *a)
}
#endif

JL_CALLABLE(jl_f_arraylen)
{
JL_NARGS(arraylen, 1, 1);
JL_TYPECHK(arraylen, array, args[0]);
return jl_box_long(jl_array_len((jl_array_t*)args[0]));
}

JL_CALLABLE(jl_f_arraysize)
{
JL_NARGS(arraysize, 2, 2);
Expand Down
3 changes: 0 additions & 3 deletions src/builtin_proto.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,20 +18,17 @@ JL_CALLABLE(jl_f_isa);
JL_CALLABLE(jl_f_typeassert);
JL_CALLABLE(jl_f_apply);
JL_CALLABLE(jl_f_kwcall);
JL_CALLABLE(jl_f_top_eval);
JL_CALLABLE(jl_f_isdefined);
JL_CALLABLE(jl_f_tuple);
JL_CALLABLE(jl_f_svec);
JL_CALLABLE(jl_f_get_field);
JL_CALLABLE(jl_f_set_field);
JL_CALLABLE(jl_f_field_type);
JL_CALLABLE(jl_f_arraylen);
JL_CALLABLE(jl_f_arrayref);
JL_CALLABLE(jl_f_arrayset);
JL_CALLABLE(jl_f_arraysize);
JL_CALLABLE(jl_f_instantiate_type);
JL_CALLABLE(jl_f_typevar);
JL_CALLABLE(jl_f_methodexists);
JL_CALLABLE(jl_f_applicable);
JL_CALLABLE(jl_f_invoke);
JL_CALLABLE(jl_f_new_expr);
Expand Down
70 changes: 18 additions & 52 deletions src/builtins.c
Original file line number Diff line number Diff line change
Expand Up @@ -543,7 +543,12 @@ JL_CALLABLE(jl_f_kwcall)

extern int jl_lineno;

DLLEXPORT jl_value_t *jl_toplevel_eval_in(jl_module_t *m, jl_value_t *ex, int delay_warn)
DLLEXPORT jl_value_t *jl_toplevel_eval_in(jl_module_t *m, jl_value_t *ex)
{
return jl_toplevel_eval_in_warn(m, ex, 0);
}

DLLEXPORT jl_value_t *jl_toplevel_eval_in_warn(jl_module_t *m, jl_value_t *ex, int delay_warn)
{
static int jl_warn_on_eval = 0;
int last_delay_warn = jl_warn_on_eval;
Expand Down Expand Up @@ -587,23 +592,6 @@ DLLEXPORT jl_value_t *jl_toplevel_eval_in(jl_module_t *m, jl_value_t *ex, int de
return v;
}

JL_CALLABLE(jl_f_top_eval)
{
jl_module_t *m;
jl_value_t *ex;
if (nargs == 1) {
m = jl_main_module;
ex = args[0];
}
else {
JL_NARGS(eval, 2, 2);
JL_TYPECHK(eval, module, args[0]);
m = (jl_module_t*)args[0];
ex = args[1];
}
return jl_toplevel_eval_in(m, ex, 0);
}

JL_CALLABLE(jl_f_isdefined)
{
jl_module_t *m = jl_current_module;
Expand Down Expand Up @@ -1057,29 +1045,6 @@ static void jl_check_type_tuple(jl_value_t *t, jl_sym_t *name, const char *ctx)
jl_type_error_rt(name->name, ctx, (jl_value_t*)jl_type_type, t);
}

JL_CALLABLE(jl_f_methodexists)
{
JL_NARGS(method_exists, 2, 2);
JL_TYPECHK(method_exists, function, args[0]);
if (!jl_is_gf(args[0]))
jl_error("method_exists: not a generic function");
jl_value_t *argtypes = args[1];
JL_GC_PUSH1(&argtypes);
if (jl_is_tuple(args[1])) {
// TODO: maybe deprecation warning, better checking
argtypes = (jl_value_t*)jl_apply_tuple_type_v((jl_value_t**)jl_data_ptr(argtypes),
jl_nfields(argtypes));
}
else {
jl_check_type_tuple(args[1], jl_gf_name(args[0]), "method_exists");
}
jl_value_t *res = jl_method_lookup_by_type(jl_gf_mtable(args[0]),
(jl_tupletype_t*)argtypes,0,0)!=jl_bottom_func ?
jl_true : jl_false;
JL_GC_POP();
return res;
}

JL_CALLABLE(jl_f_applicable)
{
JL_NARGSV(applicable, 1);
Expand Down Expand Up @@ -1228,30 +1193,31 @@ void jl_init_primitives(void)
add_builtin_func("issubtype", jl_f_subtype);
add_builtin_func("isa", jl_f_isa);
add_builtin_func("typeassert", jl_f_typeassert);
add_builtin_func("_apply", jl_f_apply);
add_builtin_func("kwcall", jl_f_kwcall);
add_builtin_func("throw", jl_f_throw);
add_builtin_func("tuple", jl_f_tuple);
add_builtin_func("svec", jl_f_svec);
add_builtin_func("method_exists", jl_f_methodexists);
add_builtin_func("applicable", jl_f_applicable);
add_builtin_func("invoke", jl_f_invoke);
add_builtin_func("eval", jl_f_top_eval);
add_builtin_func("isdefined", jl_f_isdefined);

// functions for internal use
// field access
add_builtin_func("getfield", jl_f_get_field);
add_builtin_func("setfield!", jl_f_set_field);
add_builtin_func("fieldtype", jl_f_field_type);
add_builtin_func("nfields", jl_f_nfields);
add_builtin_func("_expr", jl_f_new_expr);
add_builtin_func("isdefined", jl_f_isdefined);

add_builtin_func("arraylen", jl_f_arraylen);
// array primitives
add_builtin_func("arrayref", jl_f_arrayref);
add_builtin_func("arrayset", jl_f_arrayset);
add_builtin_func("arraysize", jl_f_arraysize);

// method table utils
add_builtin_func("applicable", jl_f_applicable);
add_builtin_func("invoke", jl_f_invoke);

// internal functions
add_builtin_func("apply_type", jl_f_instantiate_type);
add_builtin_func("_apply", jl_f_apply);
add_builtin_func("kwcall", jl_f_kwcall);
add_builtin_func("_expr", jl_f_new_expr);
add_builtin_func("svec", jl_f_svec);

// builtin types
add_builtin("Any", (jl_value_t*)jl_any_type);
Expand Down
14 changes: 0 additions & 14 deletions src/codegen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2374,17 +2374,6 @@ static bool emit_known_call(jl_cgval_t *ret, jl_value_t *ff,
return true;
}

else if (f->fptr == &jl_f_arraylen && nargs==1) {
jl_value_t *aty = expr_type(args[1], ctx); rt1 = aty;
if (jl_is_array_type(aty)) {
// todo: also allow e.g. Union of several array types
jl_cgval_t arg1 = emit_expr(args[1], ctx);
*ret = mark_julia_type(emit_arraylen(arg1, args[1], ctx), false, jl_long_type);
JL_GC_POP();
return true;
}
}

else if (f->fptr == &jl_f_arraysize && nargs==2) {
jl_value_t *aty = expr_type(args[1], ctx); rt1 = aty;
jl_value_t *ity = expr_type(args[2], ctx); rt2 = ity;
Expand Down Expand Up @@ -5535,17 +5524,14 @@ static void init_julia_llvm_env(Module *m)
builtin_func_map[jl_f_throw] = jlcall_func_to_llvm("jl_f_throw", (void*)&jl_f_throw, m);
builtin_func_map[jl_f_tuple] = jlcall_func_to_llvm("jl_f_tuple", (void*)&jl_f_tuple, m);
builtin_func_map[jl_f_svec] = jlcall_func_to_llvm("jl_f_svec", (void*)&jl_f_svec, m);
builtin_func_map[jl_f_methodexists] = jlcall_func_to_llvm("jl_f_methodexists", (void*)&jl_f_methodexists, m);
builtin_func_map[jl_f_applicable] = jlcall_func_to_llvm("jl_f_applicable", (void*)&jl_f_applicable, m);
builtin_func_map[jl_f_invoke] = jlcall_func_to_llvm("jl_f_invoke", (void*)&jl_f_invoke, m);
builtin_func_map[jl_f_top_eval] = jlcall_func_to_llvm("jl_f_top_eval", (void*)&jl_f_top_eval, m);
builtin_func_map[jl_f_isdefined] = jlcall_func_to_llvm("jl_f_isdefined", (void*)&jl_f_isdefined, m);
builtin_func_map[jl_f_get_field] = jlcall_func_to_llvm("jl_f_get_field", (void*)&jl_f_get_field, m);
builtin_func_map[jl_f_set_field] = jlcall_func_to_llvm("jl_f_set_field", (void*)&jl_f_set_field, m);
builtin_func_map[jl_f_field_type] = jlcall_func_to_llvm("jl_f_field_type", (void*)&jl_f_field_type, m);
builtin_func_map[jl_f_nfields] = jlcall_func_to_llvm("jl_f_nfields", (void*)&jl_f_nfields, m);
builtin_func_map[jl_f_new_expr] = jlcall_func_to_llvm("jl_f_new_expr", (void*)&jl_f_new_expr, m);
builtin_func_map[jl_f_arraylen] = jlcall_func_to_llvm("jl_f_arraylen", (void*)&jl_f_arraylen, m);
builtin_func_map[jl_f_arrayref] = jlcall_func_to_llvm("jl_f_arrayref", (void*)&jl_f_arrayref, m);
builtin_func_map[jl_f_arrayset] = jlcall_func_to_llvm("jl_f_arrayset", (void*)&jl_f_arrayset, m);
builtin_func_map[jl_f_arraysize] = jlcall_func_to_llvm("jl_f_arraysize", (void*)&jl_f_arraysize, m);
Expand Down
10 changes: 4 additions & 6 deletions src/dump.c
Original file line number Diff line number Diff line change
Expand Up @@ -70,13 +70,11 @@ static htable_t fptr_to_id;
// (reverse of fptr_to_id)
static jl_fptr_t id_to_fptrs[] = {
NULL, NULL,
jl_f_throw, jl_f_is, jl_f_no_function, jl_f_typeof,
jl_f_subtype, jl_f_isa, jl_f_typeassert, jl_f_apply,
jl_f_top_eval, jl_f_isdefined, jl_f_tuple, jl_f_svec,
jl_f_throw, jl_f_is, jl_f_no_function, jl_f_typeof, jl_f_subtype, jl_f_isa,
jl_f_typeassert, jl_f_apply, jl_f_isdefined, jl_f_tuple, jl_f_svec,
jl_f_get_field, jl_f_set_field, jl_f_field_type, jl_f_nfields,
jl_f_arraylen, jl_f_arrayref, jl_f_arrayset, jl_f_arraysize,
jl_f_instantiate_type, jl_f_kwcall, jl_trampoline,
jl_f_methodexists, jl_f_applicable, jl_f_invoke,
jl_f_arrayref, jl_f_arrayset, jl_f_arraysize, jl_f_instantiate_type,
jl_f_kwcall, jl_trampoline, jl_f_applicable, jl_f_invoke,
jl_apply_generic, jl_unprotect_stack, jl_f_sizeof, jl_f_new_expr,
jl_f_intrinsic_call,
NULL };
Expand Down
7 changes: 6 additions & 1 deletion src/gf.c
Original file line number Diff line number Diff line change
Expand Up @@ -966,7 +966,7 @@ DLLEXPORT jl_function_t *jl_instantiate_staged(jl_methlist_t *m, jl_tupletype_t
}
ex = oldast;
}
func = (jl_function_t*)jl_toplevel_eval_in(m->func->linfo->module, (jl_value_t*)ex, 1); // need to eval macros in the right module, but not give a warning for the `eval` call unless that results in a call to `eval`
func = (jl_function_t*)jl_toplevel_eval_in_warn(m->func->linfo->module, (jl_value_t*)ex, 1); // need to eval macros in the right module, but not give a warning for the `eval` call unless that results in a call to `eval`
func->linfo->name = m->func->linfo->name;
JL_GC_POP();
return func;
Expand Down Expand Up @@ -1416,6 +1416,11 @@ jl_function_t *jl_method_lookup_by_type(jl_methtable_t *mt, jl_tupletype_t *type
return sf;
}

DLLEXPORT int jl_method_exists(jl_methtable_t *mt, jl_tupletype_t *types)
{
return jl_method_lookup_by_type(mt, types, 0, 0) != jl_bottom_func;
}

jl_function_t *jl_method_lookup(jl_methtable_t *mt, jl_value_t **args, size_t nargs, int cache)
{
jl_function_t *sf = jl_method_table_assoc_exact(mt, args, nargs);
Expand Down
2 changes: 0 additions & 2 deletions src/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -594,8 +594,6 @@ void _julia_init(JL_IMAGE_SEARCH rel)
if (jl_base_module != NULL) {
jl_add_standard_imports(jl_main_module);
}
// eval() uses Main by default, so Main.eval === Core.eval
jl_module_import(jl_main_module, jl_core_module, jl_symbol("eval"));
jl_current_module = jl_main_module;
jl_root_task->current_module = jl_current_module;

Expand Down
3 changes: 3 additions & 0 deletions src/intrinsics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -920,6 +920,9 @@ static jl_cgval_t emit_intrinsic(intrinsic f, jl_value_t **args, size_t nargs,
case ccall: return emit_ccall(args, nargs, ctx);
case cglobal: return emit_cglobal(args, nargs, ctx);
case llvmcall: return emit_llvmcall(args, nargs, ctx);
case arraylen:
return mark_julia_type(emit_arraylen(emit_expr(args[1], ctx), args[1], ctx), false,
jl_long_type);
#if 0 // this section enables runtime-intrinsics (e.g. for testing), and disables their llvm counterparts
default:
int ldepth = ctx->gc.argDepth;
Expand Down
2 changes: 2 additions & 0 deletions src/intrinsics.h
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,8 @@
ALIAS(ccall, ccall) \
ALIAS(cglobal, cglobal) \
ALIAS(llvmcall, llvmcall) \
/* object access */ \
ADD_I(arraylen, 1) \
/* hidden intrinsics */ \
ADD_HIDDEN(fptoui_auto, 1) \
ADD_HIDDEN(fptosi_auto, 1)
Expand Down
3 changes: 2 additions & 1 deletion src/julia.h
Original file line number Diff line number Diff line change
Expand Up @@ -1249,7 +1249,8 @@ DLLEXPORT const char *jl_lookup_soname(const char *pfx, size_t n);
// compiler
void jl_compile(jl_function_t *f);
DLLEXPORT jl_value_t *jl_toplevel_eval(jl_value_t *v);
DLLEXPORT jl_value_t *jl_toplevel_eval_in(jl_module_t *m, jl_value_t *ex, int delay_warn);
DLLEXPORT jl_value_t *jl_toplevel_eval_in(jl_module_t *m, jl_value_t *ex);
DLLEXPORT jl_value_t *jl_toplevel_eval_in_warn(jl_module_t *m, jl_value_t *ex, int delay_warn);
jl_value_t *jl_eval_global_var(jl_module_t *m, jl_sym_t *e);
DLLEXPORT jl_value_t *jl_load(const char *fname, size_t len);
jl_value_t *jl_parse_eval_all(const char *fname, size_t len);
Expand Down
3 changes: 1 addition & 2 deletions src/julia_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -317,8 +317,7 @@ DLLEXPORT jl_value_t *jl_copysign_float(jl_value_t *a, jl_value_t *b);
DLLEXPORT jl_value_t *jl_flipsign_int(jl_value_t *a, jl_value_t *b);

DLLEXPORT jl_value_t *jl_select_value(jl_value_t *isfalse, jl_value_t *a, jl_value_t *b);


DLLEXPORT jl_value_t *jl_arraylen(jl_value_t *a);

#ifdef __cplusplus
}
Expand Down
5 changes: 5 additions & 0 deletions src/runtime_intrinsics.c
Original file line number Diff line number Diff line change
Expand Up @@ -931,3 +931,8 @@ DLLEXPORT jl_value_t *jl_select_value(jl_value_t *isfalse, jl_value_t *a, jl_val
JL_TYPECHK(isfalse, bool, isfalse);
return (isfalse == jl_false ? b : a);
}

DLLEXPORT jl_value_t *jl_arraylen(jl_value_t *a)
{
return jl_box_long(jl_array_len((jl_array_t*)a));
}
2 changes: 0 additions & 2 deletions src/toplevel.c
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,6 @@ jl_module_t *jl_new_main_module(void)
(jl_value_t*)jl_main_module);
jl_current_task->current_module = jl_main_module;

jl_module_import(jl_main_module, jl_core_module, jl_symbol("eval"));

return old_main;
}

Expand Down

0 comments on commit f1664bc

Please sign in to comment.