diff --git a/j/base.j b/j/base.j
index 24b000b01c3d2..b9f288ab944b2 100644
--- a/j/base.j
+++ b/j/base.j
@@ -1,5 +1,67 @@
 # important core definitions
 
+convert(T, x)               = convert_default(T, x, convert)
+convert(T::Tuple, x::Tuple) = convert_tuple(T, x, convert)
+
+type ErrorException <: Exception
+    msg::String
+end
+
+type SystemError <: Exception
+    prefix::String
+    errnum::Int32
+    SystemError(p::String, e::Integer) = new(p, int32(e))
+    SystemError(p::String) = new(p, errno())
+end
+
+type TypeError <: Exception
+    func::Symbol
+    context::String
+    expected::Type
+    got
+end
+
+type ParseError <: Exception
+    msg::String
+end
+
+type ArgumentError <: Exception
+    msg::String
+end
+
+type UnboundError <: Exception
+    var::Symbol
+end
+
+type KeyError <: Exception
+    key
+end
+
+type LoadError <: Exception
+    file::String
+    line::Int32
+    error
+end
+
+type MethodError <: Exception
+    f
+    args
+end
+
+type UnionTooComplexError <: Exception
+    types::Tuple
+end
+
+type BackTrace <: Exception
+    e
+    trace::Array{Any,1}
+end
+
+method_missing(f, args...) = throw(MethodError(f, args))
+
+ccall(:jl_get_system_hooks, Void, ())
+
+
 int(x) = convert(Int, x)
 int(x::Int) = x
 uint(x) = convert(Uint, x)
@@ -72,6 +134,9 @@ function compile_hint(f, args::Tuple)
     nothing
 end
 
+# we share Array with Base so we can add definitions to it
+const Array = eval(Base, :Array)
+
 Array{T}  (::Type{T}, d::(Integer,)) =
     ccall(:jl_alloc_array_1d, Array{T,1}, (Any,Int), Array{T,1},
           int(d[1]))
diff --git a/j/inference.j b/j/inference.j
index 6392f7e0526cb..a9df861dbbd1b 100644
--- a/j/inference.j
+++ b/j/inference.j
@@ -158,23 +158,27 @@ function static_convert(to::ANY, from::ANY)
         end
         # tuple conversion calls convert recursively
         if isseqtype(ce)
-            R = abstract_call_gf(convert, (), (Type{pe}, ce.parameters[1]), ())
+            #R = abstract_call_gf(convert, (), (Type{pe}, ce.parameters[1]), ())
+            R = static_convert(pe, ce.parameters[1])
             isType(R) && (R = R.parameters[1])
             result[i] = ...{R}
         else
-            R = abstract_call_gf(convert, (), (Type{pe}, ce), ())
+            #R = abstract_call_gf(convert, (), (Type{pe}, ce), ())
+            R = static_convert(pe, ce)
             isType(R) && (R = R.parameters[1])
             result[i] = R
         end
     end
     a2t(result)
 end
-t_func[:convert] =
-    (2, 2, (t,x)->(if isa(t,Tuple) && allp(isType,t)
-                       t = Type{map(t->t.parameters[1],t)}
-                   end;
-                   isType(t) ? static_convert(t.parameters[1],x) :
-                   Any))
+t_func[convert_default] =
+    (3, 3, (t,x,f)->(isType(t) ? static_convert(t.parameters[1],x) : Any))
+t_func[convert_tuple] =
+    (3, 3, (t,x,f)->(if isa(t,Tuple) && allp(isType,t)
+                         t = Type{map(t->t.parameters[1],t)}
+                     end;
+                     isType(t) ? static_convert(t.parameters[1],x) :
+                     Any))
 typeof_tfunc = function (t)
     if isType(t)
         t = t.parameters[1]
@@ -486,6 +490,9 @@ function abstract_call(f, fargs, argtypes, vtypes, sv::StaticVarInfo, e)
                 end
             end
         end
+        if !is(f,apply) && isa(e,Expr) && isa(f,Function)
+            e.head = :call1
+        end
         rt = builtin_tfunction(f, fargs, argtypes)
         #print("=> ", rt, "\n")
         return rt
@@ -497,8 +504,8 @@ function abstract_call(f, fargs, argtypes, vtypes, sv::StaticVarInfo, e)
     end
 end
 
-ft_tfunc(ft, argtypes) = ccall(:jl_func_type_tfunc, Any,
-                               (Any, Any), ft, argtypes)
+ft_tfunc(ft, argtypes) = ccall(:jl_func_type_tfunc, Any, (Any, Any),
+                               ft, argtypes)
 
 function abstract_eval_call(e, vtypes, sv::StaticVarInfo)
     fargs = a2t_butfirst(e.args)
@@ -828,10 +835,6 @@ end
 typeinf(linfo,atypes,sparams) = typeinf(linfo,atypes,sparams,linfo,true)
 typeinf(linfo,atypes,sparams,linfo) = typeinf(linfo,atypes,sparams,linfo,true)
 
-abstract RecPending{T}
-
-isRecPending(t) = isa(t, AbstractKind) && is(t.name, RecPending.name)
-
 ast_rettype(ast) = ast.args[3].typ
 
 # def is the original unspecialized version of a method. we aggregate all
@@ -840,8 +843,6 @@ function typeinf(linfo::LambdaStaticData,atypes::Tuple,sparams::Tuple, def, cop)
     #dbg = 
     #dotrace = true#is(linfo,sizestr)
     local ast::Expr
-    redo = false
-    curtype = None
     # check cached t-functions
     tf = def.tfunc
     while !is(tf,())
@@ -853,15 +854,9 @@ function typeinf(linfo::LambdaStaticData,atypes::Tuple,sparams::Tuple, def, cop)
             # if the frame above this one recurred, rerun type inf
             # here instead of returning, and update the cache, until the new
             # inferred type equals the cached type (fixed point)
-            rt = ast_rettype(tf[2])
-            if isRecPending(rt)
-                curtype = rt.parameters[1]
-                redo = true
-                ast = tf[2]
-                break
-            else
-                return (tf[2], rt)
-            end
+            ast = tf[2]
+            rt = ast_rettype(ast)
+            return (ast, rt)
         end
         tf = tf[3]
     end
@@ -893,12 +888,9 @@ function typeinf(linfo::LambdaStaticData,atypes::Tuple,sparams::Tuple, def, cop)
         f = f.prev
     end
 
-    rec = false
-
     #print("typeinf ", linfo.name, " ", atypes, "\n")
 
-    if redo
-    elseif cop
+    if cop
         sparams = append(sparams, linfo.sparams)
         ast = ccall(:jl_prepare_ast, Any, (Any,Any), linfo, sparams)::Expr
     else
@@ -910,8 +902,20 @@ function typeinf(linfo::LambdaStaticData,atypes::Tuple,sparams::Tuple, def, cop)
     locals = (ast.args[2].args[1].args)::Array{Any,1}
     vars = append(args, locals)
     body = (ast.args[3].args)::Array{Any,1}
-
     n = length(body)
+
+    # our stack frame
+    frame = CallStack(ast0, linfo.module, atypes, inference_stack)
+    inference_stack = frame
+    curtype = None
+    frame.result = curtype
+
+    local s, sv
+
+    while true
+
+    rec = false
+
     s = { () | i=1:n }
     recpts = IntSet(n+1)  # statements that depend recursively on our value
     W = IntSet(n+1)
@@ -958,11 +962,6 @@ function typeinf(linfo::LambdaStaticData,atypes::Tuple,sparams::Tuple, def, cop)
     end
     sv = StaticVarInfo(sparams, cenv)
 
-    # our stack frame
-    frame = CallStack(ast0, linfo.module, atypes, inference_stack)
-    frame.result = curtype
-    inference_stack = frame
-
     # exception handlers
     cur_hand = ()
     handler_at = { () | i=1:n }
@@ -1069,23 +1068,23 @@ function typeinf(linfo::LambdaStaticData,atypes::Tuple,sparams::Tuple, def, cop)
     end
     #print("\n",ast,"\n")
     #print("==> ", frame.result,"\n")
-    if redo && typeseq(curtype, frame.result)
-        rec = false
-    end
-    fulltree = type_annotate(ast, s, sv,
-                             rec ? RecPending{frame.result} : frame.result,
-                             vars)
-    if !rec
-        fulltree.args[3] = inlining_pass(fulltree.args[3], s[1])
-        tuple_elim_pass(fulltree)
-        linfo.inferred = true
-    end
-    if !redo
-        compressed = ccall(:jl_compress_ast, Any, (Any,), fulltree)
-        fulltree = compressed
-        #compressed = fulltree
-        def.tfunc = (atypes, compressed, def.tfunc)
-    end
+    if !rec || typeseq(curtype, frame.result)
+        break
+    end
+    curtype = frame.result
+    end # while
+    
+    fulltree = type_annotate(ast, s, sv, frame.result, vars)
+    
+    fulltree.args[3] = inlining_pass(fulltree.args[3], s[1])
+    tuple_elim_pass(fulltree)
+    linfo.inferred = true
+    
+    compressed = ccall(:jl_compress_ast, Any, (Any,), fulltree)
+    fulltree = compressed
+    #compressed = fulltree
+    def.tfunc = (atypes, compressed, def.tfunc)
+    
     inference_stack = (inference_stack::CallStack).prev
     return (fulltree, frame.result)
 end
@@ -1173,11 +1172,6 @@ function type_annotate(ast::Expr, states::Array{Any,1},
         end
     end
 
-    # do inference on inner functions
-    if isRecPending(rettype)
-        return ast
-    end
-
     for li in closures
         if !li.inferred
             a = li.ast
@@ -1286,6 +1280,15 @@ end
 function inlineable(f, e::Expr, vars)
     argexprs = a2t_butfirst(e.args)
     atypes = map(exprtype, argexprs)
+
+    if is(f, convert_default) && length(atypes)==3
+        # builtin case of convert. convert(T,x::S) => x, when S<:T
+        if isType(atypes[1]) && subtype(atypes[2],atypes[1].parameters[1])
+            # todo: if T expression has side effects??!
+            return e.args[3]
+        end
+    end
+
     meth = getmethods(f, atypes)
     if length(meth) != 1
         return NF
@@ -1297,13 +1300,6 @@ function inlineable(f, e::Expr, vars)
     if !subtype(atypes, meth[1])
         return NF
     end
-    if is(meth[3],:convert) && length(atypes)==2
-        # builtin case of convert. convert(T,x::S) => x, when S<:T
-        if isType(atypes[1]) && subtype(atypes[2],atypes[1].parameters[1])
-            # todo: if T expression has side effects??!
-            return e.args[3]
-        end
-    end
     if !isa(meth[3],LambdaStaticData) || !is(meth[4],())
         return NF
     end
diff --git a/j/show.j b/j/show.j
index 8621e4cf6331e..ef4bbc38b77e5 100644
--- a/j/show.j
+++ b/j/show.j
@@ -1,3 +1,8 @@
+# formerly built-in methods. can be replaced any time.
+print(a::Array{Uint8,1}) = ccall(:jl_print_array_uint8, Void, (Any,), a)
+print(s::Symbol) = ccall(:jl_print_symbol, Void, (Any,), s)
+show(x) = ccall(:jl_show_any, Void, (Any,), x)
+
 print(x) = show(x)
 showcompact(x) = show(x)
 show_to_string(x) = print_to_string(show, x)
@@ -7,7 +12,7 @@ show(s::Symbol) = print(s)
 show(tn::TypeName) = show(tn.name)
 show(::Nothing) = print("nothing")
 show(b::Bool) = print(b ? "true" : "false")
-show(n::Integer)  = show(int64(n))
+show(n::Integer)  = print(dec(int64(n)))
 
 function show_trailing_hex(n::Uint64, ndig::Integer)
     for s = ndig-1:-1:0
diff --git a/j/stage0.j b/j/stage0.j
index 572de5ba3a162..4fe88b5c13057 100644
--- a/j/stage0.j
+++ b/j/stage0.j
@@ -4,14 +4,17 @@ if false
     # simple print definitions for debugging. enable these if something
     # goes wrong during bootstrap before printing code is available.
     length(a::Array) = arraylen(a)
+    print(a::Array{Uint8,1}) = ccall(:jl_print_array_uint8, Void, (Any,), a)
+    print(s::Symbol) = ccall(:jl_print_symbol, Void, (Any,), s)
     print(s::ASCIIString) = print(s.data)
     print(x) = show(x)
     println(x) = (print(x);print("\n"))
+    show(x) = ccall(:jl_show_any, Void, (Any,), x)
     show(s::ASCIIString) = print(s.data)
     show(s::Symbol) = print(s)
     show(b::Bool) = print(b ? "true" : "false")
+    show(n::Int64) = ccall(:jl_print_int64, Void, (Int64,), n)
     show(n::Integer)  = show(int64(n))
-    show(n::Unsigned) = show(uint64(n))
     print(a...) = for x=a; print(x); end
     function show(e::Expr)
         print(e.head)
diff --git a/src/alloc.c b/src/alloc.c
index cc19fbdcc9d45..6e9923619baf0 100644
--- a/src/alloc.c
+++ b/src/alloc.c
@@ -32,7 +32,6 @@ jl_typename_t *jl_array_typename;
 jl_type_t *jl_array_uint8_type;
 jl_type_t *jl_array_any_type;
 jl_struct_type_t *jl_weakref_type;
-jl_tag_type_t *jl_string_type;
 jl_struct_type_t *jl_ascii_string_type;
 jl_struct_type_t *jl_utf8_string_type;
 jl_struct_type_t *jl_expr_type;
@@ -70,7 +69,7 @@ jl_sym_t *goto_sym;    jl_sym_t *goto_ifnot_sym;
 jl_sym_t *label_sym;   jl_sym_t *return_sym;
 jl_sym_t *lambda_sym;  jl_sym_t *assign_sym;
 jl_sym_t *null_sym;    jl_sym_t *body_sym;
-jl_sym_t *isbound_sym; jl_sym_t *macro_sym;
+jl_sym_t *macro_sym;
 jl_sym_t *locals_sym;  jl_sym_t *colons_sym;
 jl_sym_t *Any_sym;     jl_sym_t *method_sym;
 jl_sym_t *enter_sym;   jl_sym_t *leave_sym;
@@ -625,18 +624,6 @@ jl_typector_t *jl_new_type_ctor(jl_tuple_t *params, jl_type_t *body)
     return (jl_typector_t*)tc;
 }
 
-// struct constructors --------------------------------------------------------
-
-JL_CALLABLE(jl_weakref_ctor)
-{
-    if (nargs > 1) {
-        JL_NARGS(WeakRef, 1, 1);
-    }
-    if (nargs == 1)
-        return (jl_value_t*)jl_gc_new_weakref(args[0]);
-    return (jl_value_t*)jl_gc_new_weakref((jl_value_t*)jl_nothing);
-}
-
 // bits constructors ----------------------------------------------------------
 
 #define BOX_FUNC(typ,c_type,pfx,nw)             \
diff --git a/src/boot.j b/src/boot.j
index 4254d8d51d692..167bb0c9f2cbf 100644
--- a/src/boot.j
+++ b/src/boot.j
@@ -149,96 +149,45 @@ else
     const boxuint = boxui32
 end
 
-type WeakRef
-    value
-end
+abstract Exception
+
+type BoundsError        <: Exception end
+type DivideByZeroError  <: Exception end
+type MemoryError        <: Exception end
+type IOError            <: Exception end
+type StackOverflowError <: Exception end
+type EOFError           <: Exception end
+type UndefRefError      <: Exception end
+type InterruptException <: Exception end
 
 abstract String
 abstract DirectIndexString <: String
 
-type ASCIIString <: DirectIndexString
-    data::Array{Uint8,1}
-end
-type UTF8String <: String
-    data::Array{Uint8,1}
-end
-
-typealias ByteString Union(ASCIIString,UTF8String)
-
 abstract Associative
 
+# simple convert for use by constructors of types in Base
+convert(T, x) = convert_default(T, x, convert)
+
 type SymbolNode
     name::Symbol
     typ
+    SymbolNode(name::Symbol, t::ANY) = new(name, t)
 end
 
-abstract Exception
-
-type ErrorException <: Exception
-    msg::String
-end
-
-type SystemError <: Exception
-    prefix::String
-    errnum::Int32
-    SystemError(p::String, e::Integer) = new(p, int32(e))
-    SystemError(p::String) = new(p, errno())
-end
-
-type TypeError <: Exception
-    func::Symbol
-    context::String
-    expected::Type
-    got
-end
-
-type ParseError <: Exception
-    msg::String
-end
-
-type ArgumentError <: Exception
-    msg::String
-end
-
-type BoundsError <: Exception
-end
-
-type UnboundError <: Exception
-    var::Symbol
-end
-
-type KeyError <: Exception
-    key
-end
-
-type LoadError <: Exception
-    file::String
-    line::Int32
-    error
-end
-
-type MethodError <: Exception
-    f
-    args
+type WeakRef
+    value
+    WeakRef() = WeakRef(nothing)
+    WeakRef(v::ANY) = ccall(:jl_gc_new_weakref, WeakRef, (Any,), v)
 end
 
-type DivideByZeroError  <: Exception end
-type MemoryError        <: Exception end
-type IOError            <: Exception end
-type StackOverflowError <: Exception end
-type EOFError           <: Exception end
-type UndefRefError      <: Exception end
-type InterruptException <: Exception end
-
-type UnionTooComplexError <: Exception
-    types::Tuple
+type ASCIIString <: DirectIndexString
+    data::Array{Uint8,1}
 end
 
-type BackTrace <: Exception
-    e
-    trace::Array{Any,1}
+type UTF8String <: String
+    data::Array{Uint8,1}
 end
 
-method_missing(f, args...) = throw(MethodError(f, args))
+typealias ByteString Union(ASCIIString,UTF8String)
 
 load(fname::ByteString) = ccall(:jl_load, Void, (Ptr{Uint8},), fname)
diff --git a/src/builtin_proto.h b/src/builtin_proto.h
index 2fc1ea22c9204..a818c7c8cb5ad 100644
--- a/src/builtin_proto.h
+++ b/src/builtin_proto.h
@@ -5,7 +5,6 @@
 
 JL_CALLABLE(jl_f_new_expr);
 JL_CALLABLE(jl_f_new_box);
-JL_CALLABLE(jl_weakref_ctor);
 JL_CALLABLE(jl_f_throw);
 JL_CALLABLE(jl_f_is);
 JL_CALLABLE(jl_f_no_function);
@@ -27,14 +26,10 @@ 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_convert);
+JL_CALLABLE(jl_f_convert_default);
 JL_CALLABLE(jl_f_convert_tuple);
-JL_CALLABLE(jl_f_print_array_uint8);
-JL_CALLABLE(jl_f_show_int64);
-JL_CALLABLE(jl_f_show_uint64);
 JL_CALLABLE(jl_f_show_linfo);
 JL_CALLABLE(jl_f_show_any);
-JL_CALLABLE(jl_f_print_symbol);
 JL_CALLABLE(jl_trampoline);
 JL_CALLABLE(jl_f_new_struct_type);
 JL_CALLABLE(jl_f_new_struct_fields);
diff --git a/src/builtins.c b/src/builtins.c
index c61f7446765c8..05f62f375dbdb 100644
--- a/src/builtins.c
+++ b/src/builtins.c
@@ -17,7 +17,7 @@
 #include "julia.h"
 #include "builtin_proto.h"
 
-// --- exceptions ---
+// exceptions -----------------------------------------------------------------
 
 DLLEXPORT char *julia_home = NULL;
 
@@ -112,7 +112,7 @@ void jl_pop_handler(int n)
     }
 }
 
-// --- primitives ---
+// primitives -----------------------------------------------------------------
 
 JL_CALLABLE(jl_f_is)
 {
@@ -231,7 +231,7 @@ jl_value_t *jl_eval_module_expr(jl_expr_t *ex, volatile size_t *plineno)
     if (name == jl_current_module->name) {
         jl_errorf("module name %s conflicts with enclosing module", name->name);
     }
-    jl_binding_t *b = jl_get_binding(jl_current_module, name);
+    jl_binding_t *b = jl_get_binding_wr(jl_current_module, name);
     jl_declare_constant(b);
     if (b->value != NULL) {
         ios_printf(ios_stderr, "Warning: redefinition of module %s ignored\n",
@@ -275,8 +275,8 @@ jl_value_t *jl_eval_module_expr(jl_expr_t *ex, volatile size_t *plineno)
 
 static int is_intrinsic(jl_sym_t *s)
 {
-    jl_value_t **bp = jl_get_bindingp(jl_current_module, s);
-    return (*bp != NULL && jl_typeof(*bp)==(jl_type_t*)jl_intrinsic_type);
+    jl_value_t *v = jl_get_global(jl_current_module, s);
+    return (v != NULL && jl_typeof(v)==(jl_type_t*)jl_intrinsic_type);
 }
 
 static int has_intrinsics(jl_expr_t *e)
@@ -325,6 +325,8 @@ static int eval_with_compiler_p(jl_expr_t *expr, int compileloops)
 
 jl_value_t *jl_new_closure_internal(jl_lambda_info_t *li, jl_value_t *env);
 
+extern int jl_in_inference;
+
 jl_value_t *jl_toplevel_eval_flex(jl_value_t *e, int fast,
                                   volatile size_t *plineno)
 {
@@ -334,8 +336,7 @@ jl_value_t *jl_toplevel_eval_flex(jl_value_t *e, int fast,
         return jl_interpret_toplevel_expr(e);
 
     jl_expr_t *ex = (jl_expr_t*)e;
-    if (ex->head == null_sym || ex->head == isbound_sym ||
-        ex->head == error_sym) {
+    if (ex->head == null_sym || ex->head == error_sym) {
         // expression types simple enough not to need expansion
         return jl_interpret_toplevel_expr(e);
     }
@@ -387,6 +388,9 @@ jl_value_t *jl_toplevel_eval_flex(jl_value_t *e, int fast,
 
     if (ewc) {
         thunk = jl_new_closure_internal(thk, (jl_value_t*)jl_null);
+        if (fast && !jl_in_inference) {
+            jl_type_infer(thk, jl_tuple_type, thk);
+        }
         result = jl_apply((jl_function_t*)thunk, NULL, 0);
     }
     else {
@@ -645,7 +649,16 @@ JL_CALLABLE(jl_f_field_type)
     return jl_tupleref(st->types, i);
 }
 
-// --- conversions ---
+// conversion -----------------------------------------------------------------
+
+static jl_value_t *convert(jl_type_t *to, jl_value_t *x, jl_function_t *conv_f)
+{
+    jl_value_t *args[2];
+    if (jl_subtype(x, (jl_value_t*)to, 1))
+        return x;
+    args[0] = (jl_value_t*)to; args[1] = x;
+    return jl_apply(conv_f, args, 2);
+}
 
 JL_CALLABLE(jl_f_convert_tuple)
 {
@@ -658,6 +671,7 @@ JL_CALLABLE(jl_f_convert_tuple)
     JL_GC_PUSH(&out);
     jl_value_t *ce, *pe=NULL;
     int pseq=0;
+    jl_function_t *f = (jl_function_t*)args[2];
     for(i=0; i < cl; i++) {
         ce = jl_tupleref(x,i);
         if (pseq) {
@@ -674,7 +688,7 @@ JL_CALLABLE(jl_f_convert_tuple)
             break;
         }
         assert(pe != NULL);
-        jl_tupleset(out, i, jl_convert((jl_type_t*)pe, ce));
+        jl_tupleset(out, i, convert((jl_type_t*)pe, ce, f));
     }
     JL_GC_POP();
     if (out == NULL)
@@ -682,23 +696,12 @@ JL_CALLABLE(jl_f_convert_tuple)
     return (jl_value_t*)out;
 }
 
-jl_function_t *jl_convert_gf;
-
-jl_value_t *jl_convert(jl_type_t *to, jl_value_t *x)
-{
-    jl_value_t *args[2];
-    args[0] = (jl_value_t*)to; args[1] = x;
-    return jl_apply(jl_convert_gf, args, 2);
-}
-
-JL_CALLABLE(jl_f_convert)
+JL_CALLABLE(jl_f_convert_default)
 {
-    JL_NARGS(convert, 2, 2);
-    JL_TYPECHK(convert, type, args[0]);
     jl_type_t *to = (jl_type_t*)args[0];
     jl_value_t *x = args[1];
     if (!jl_subtype(x, (jl_value_t*)to, 1)) {
-        jl_no_method_error(jl_convert_gf, args, 2);
+        jl_no_method_error((jl_function_t*)args[2], args, 2);
     }
     return x;
 }
@@ -713,21 +716,23 @@ DLLEXPORT void *jl_array_ptr(jl_array_t *a)
     return a->data;
 }
 
-// --- printing ---
+// printing -------------------------------------------------------------------
 
-JL_CALLABLE(jl_f_print_array_uint8)
+DLLEXPORT void jl_print_array_uint8(jl_array_t *b)
 {
-    ios_t *s = jl_current_output_stream();
-    jl_array_t *b = (jl_array_t*)args[0];
-    ios_write(s, (char*)b->data, b->length);
-    return (jl_value_t*)jl_nothing;
+    ios_write(jl_current_output_stream(), (char*)b->data, b->length);
 }
 
-JL_CALLABLE(jl_f_print_symbol)
+DLLEXPORT void jl_print_symbol(jl_sym_t *sym)
+{
+    ios_puts(sym->name, jl_current_output_stream());
+}
+
+// for bootstrap
+DLLEXPORT void jl_print_int64(int64_t i)
 {
     ios_t *s = jl_current_output_stream();
-    ios_puts(((jl_sym_t*)args[0])->name, s);
-    return (jl_value_t*)jl_nothing;
+    ios_printf(s, "%lld", i);
 }
 
 DLLEXPORT
@@ -752,13 +757,18 @@ int jl_strtof(char *str, float *out)
     return 0;
 }
 
-// --- showing ---
+// showing --------------------------------------------------------------------
 
-jl_function_t *jl_show_gf;
+static jl_function_t *jl_show_gf=NULL;
 
 void jl_show(jl_value_t *v)
 {
-    jl_apply(jl_show_gf, &v, 1);
+    if (jl_system_module) {
+        if (jl_show_gf == NULL) {
+            jl_show_gf = (jl_function_t*)jl_get_global(jl_system_module, jl_symbol("show"));
+        }
+        jl_apply(jl_show_gf, &v, 1);
+    }
 }
 
 // comma_one prints a comma for 1 element, e.g. "(x,)"
@@ -847,26 +857,10 @@ static void show_type(jl_value_t *t)
     }
 }
 
-JL_CALLABLE(jl_f_show_int64)
-{
-    ios_t *s = jl_current_output_stream();
-    ios_printf(s, "%lld", *(int64_t*)jl_bits_data(args[0]));
-    return (jl_value_t*)jl_nothing;
-}
-
-JL_CALLABLE(jl_f_show_uint64)
+DLLEXPORT void jl_show_any(jl_value_t *v)
 {
-    ios_t *s = jl_current_output_stream();
-    ios_printf(s, "%llu", *(uint64_t*)jl_bits_data(args[0]));
-    return (jl_value_t*)jl_nothing;
-}
-
-JL_CALLABLE(jl_f_show_any)
-{
-    JL_NARGS(print, 1, 1);
     // fallback for printing some other builtin types
     ios_t *s = jl_current_output_stream();
-    jl_value_t *v = args[0];
     if (jl_is_tuple(v)) {
         show_tuple((jl_tuple_t*)v, '(', ')', 1);
     }
@@ -881,11 +875,7 @@ JL_CALLABLE(jl_f_show_any)
     }
     else {
         jl_value_t *t = (jl_value_t*)jl_typeof(v);
-        if (jl_is_bits_type(t)) {
-            jl_no_method_error(jl_show_gf, args, 1);
-        }
-        else {
-            assert(jl_is_struct_type(t));
+        if (jl_is_struct_type(t)) {
             jl_struct_type_t *st = (jl_struct_type_t*)t;
             ios_puts(st->name->name->name, s);
             ios_putc('(', s);
@@ -899,23 +889,21 @@ JL_CALLABLE(jl_f_show_any)
             ios_putc(')', s);
         }
     }
-    return (jl_value_t*)jl_nothing;
 }
 
-// --- RTS primitives ---
-
-extern int jl_in_inference;
+// internal functions ---------------------------------------------------------
 
 JL_CALLABLE(jl_trampoline)
 {
     jl_function_t *f = (jl_function_t*)jl_t0(env);
     assert(jl_is_func(f));
     assert(f->linfo != NULL);
+    /* // to run inference on all thunks. slows down loading files.
     if (f->linfo->inferred == jl_false) {
         if (!jl_in_inference) {
             jl_type_infer(f->linfo, jl_tuple_type, f->linfo);
         }
-    }
+    }*/
     jl_compile(f);
     assert(f->fptr == &jl_trampoline);
     jl_generate_fptr(f);
@@ -965,8 +953,7 @@ static int all_typevars(jl_tuple_t *p)
 
 static void check_supertype(jl_value_t *super, char *name)
 {
-    if (!(/*jl_is_struct_type(super) || */jl_is_tag_type(super)) ||
-        super == (jl_value_t*)jl_sym_type ||
+    if (!jl_is_tag_type(super) || super == (jl_value_t*)jl_sym_type ||
         super == (jl_value_t*)jl_undef_type ||
         jl_subtype(super,(jl_value_t*)jl_type_type,0) ||
         jl_subtype(super,(jl_value_t*)jl_array_type,0)) {
@@ -1013,28 +1000,11 @@ JL_CALLABLE(jl_f_new_struct_fields)
         return (jl_value_t*)jl_nothing;
     }
     check_type_tuple(ftypes, st->name->name, "type definition");
-    jl_tuple_t *fnames = st->names;
 
     check_supertype(super, st->name->name->name);
     st->super = (jl_tag_type_t*)super;
-    if (jl_is_struct_type(super)) {
-        // UNUSED
-        assert(0);
-        st->names = jl_tuple_append(((jl_struct_type_t*)super)->names,
-                                    fnames);
-    }
-    else {
-        assert(jl_is_tag_type(super));
-    }
+    assert(jl_is_tag_type(super));
 
-    /*
-    if (jl_is_struct_type(super))
-        pft = ((jl_struct_type_t*)super)->types;
-    else if (jl_is_tag_type(super))
-        pft = jl_null;
-    else
-        assert(0);
-    */
     st->types = ftypes;
     jl_add_constructors(st);
     return (jl_value_t*)jl_nothing;
@@ -1150,7 +1120,7 @@ JL_CALLABLE(jl_f_union)
     return u;
 }
 
-// --- method definition ---
+// method definition ----------------------------------------------------------
 
 static void check_type_tuple(jl_tuple_t *t, jl_sym_t *name, const char *ctx)
 {
@@ -1195,7 +1165,7 @@ jl_value_t *jl_method_def(jl_sym_t *name, jl_value_t **bp, jl_binding_t *bnd,
     return gf;
 }
 
-// --- generic function reflection ---
+// generic function reflection ------------------------------------------------
 
 JL_CALLABLE(jl_f_methodexists)
 {
@@ -1255,11 +1225,11 @@ jl_value_t *jl_closure_linfo(jl_function_t *f)
     return (jl_value_t*)f->linfo;
 }
 
-// --- eq hash table ---
+// eq hash table --------------------------------------------------------------
 
 #include "table.c"
 
-// --- hashing ---
+// hashing --------------------------------------------------------------------
 
 DLLEXPORT uptrint_t jl_hash_symbol(jl_sym_t *s)
 {
@@ -1271,12 +1241,7 @@ DLLEXPORT uptrint_t jl_uid(jl_value_t *v)
     return (uptrint_t)v;
 }
 
-// --- init ---
-
-static void add_builtin_method1(jl_function_t *gf, jl_type_t *t, jl_fptr_t f)
-{
-    jl_add_method(gf, jl_tuple1(t), jl_new_closure(f, NULL));
-}
+// init -----------------------------------------------------------------------
 
 static void add_builtin(const char *name, jl_value_t *v)
 {
@@ -1307,6 +1272,8 @@ void jl_init_primitives(void)
     add_builtin_func("yieldto", jl_f_yieldto);
     
     // functions for internal use
+    add_builtin_func("convert_default", jl_f_convert_default);
+    add_builtin_func("convert_tuple", jl_f_convert_tuple);
     add_builtin_func("tupleref",  jl_f_tupleref);
     add_builtin_func("tuplelen",  jl_f_tuplelen);
     add_builtin_func("getfield",  jl_f_get_field);
@@ -1375,31 +1342,3 @@ void jl_init_primitives(void)
 
     add_builtin("ANY", jl_ANY_flag);
 }
-
-void jl_init_builtins(void)
-{
-    jl_function_t *jl_print_gf = jl_new_generic_function(jl_symbol("print"));
-
-    add_builtin_method1(jl_print_gf,
-                        (jl_type_t*)jl_array_uint8_type,
-                        jl_f_print_array_uint8);
-    add_builtin_method1(jl_print_gf, (jl_type_t*)jl_sym_type,
-                        jl_f_print_symbol);
-
-    jl_show_gf = jl_new_generic_function(jl_symbol("show"));
-
-    add_builtin_method1(jl_show_gf, (jl_type_t*)jl_any_type,         jl_f_show_any);
-    add_builtin_method1(jl_show_gf, (jl_type_t*)jl_int64_type,       jl_f_show_int64);
-
-    jl_convert_gf = jl_new_generic_function(jl_symbol("convert"));
-    jl_add_method(jl_convert_gf,
-                  jl_tuple2(jl_any_type, jl_any_type),
-                  jl_new_closure(jl_f_convert, NULL));
-    jl_add_method(jl_convert_gf,
-                  jl_tuple2(jl_tuple_type, jl_tuple_type),
-                  jl_new_closure(jl_f_convert_tuple, NULL));
-
-    add_builtin("print",    (jl_value_t*)jl_print_gf);
-    add_builtin("show",     (jl_value_t*)jl_show_gf);
-    add_builtin("convert",  (jl_value_t*)jl_convert_gf);
-}
diff --git a/src/codegen.cpp b/src/codegen.cpp
index 7b18a00efc51f..0178c34ea0d23 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -94,7 +94,6 @@ static Function *jlerror_func;
 static Function *jluniniterror_func;
 static Function *jldiverror_func;
 static Function *jltypeerror_func;
-static Function *jlgetbindingp_func;
 static Function *jlcheckassign_func;
 static Function *jldeclareconst_func;
 static Function *jltuple_func;
@@ -248,18 +247,15 @@ static bool is_constant(jl_value_t *ex, jl_codectx_t *ctx, bool sparams=true)
                     }
                 }
             }
-            if (jl_boundp(ctx->module, sym)) {
-                jl_binding_t *b = jl_get_binding(ctx->module, sym);
-                if (b->constp)
-                    return true;
-            }
+            if (jl_is_const(ctx->module, sym))
+                return true;
         }
         return false;
     }
     if (jl_is_topnode(ex)) {
         jl_binding_t *b = jl_get_binding(ctx->module,
                                          (jl_sym_t*)jl_fieldref(ex,0));
-        if (b->constp && b->value)
+        if (b && b->constp && b->value)
             return true;
     }
     if (jl_is_bits_type(jl_typeof(ex)))
@@ -822,14 +818,14 @@ static Value *emit_call(jl_value_t **args, size_t arglen, jl_codectx_t *ctx,
     if (jl_is_symbol(a0) && is_global((jl_sym_t*)a0, ctx) &&
         jl_boundp(ctx->module, (jl_sym_t*)a0)) {
         b = jl_get_binding(ctx->module, (jl_sym_t*)a0);
-        if (!b->constp)
+        if (!b || !b->constp)
             b = NULL;
     }
     if (jl_is_topnode(a0)) {
         headIsGlobal = true;
         // (top x) is also global
         b = jl_get_binding(ctx->module, (jl_sym_t*)jl_fieldref(a0,0));
-        if (b->value==NULL || !b->constp)
+        if (!b || b->value==NULL || !b->constp)
             b = NULL;
     }
     jl_value_t *f = NULL;
@@ -906,28 +902,9 @@ static bool isBoxed(char *varname, jl_codectx_t *ctx)
     return (*ctx->isAssigned)[varname] && (*ctx->isCaptured)[varname];
 }
 
-static Value *globalvar_binding_pointer(jl_sym_t *s, jl_binding_t **pbnd,
-                                        jl_codectx_t *ctx)
-{
-    jl_value_t **bp;
-    if (pbnd) {
-        *pbnd = jl_get_binding(ctx->module, s);
-        bp = &(*pbnd)->value;
-    }
-    else {
-        bp = jl_get_bindingp(ctx->module, s);
-    }
-    return literal_pointer_val(bp, jl_ppvalue_llvmt);
-    /*
-    return builder.CreateCall2(jlgetbindingp_func,
-                               literal_pointer_val(ctx->module, T_pint8),
-                               literal_pointer_val(s, T_pint8));
-    */
-}
-
 // yields a jl_value_t** giving the binding location of a variable
 static Value *var_binding_pointer(jl_sym_t *s, jl_binding_t **pbnd,
-                                  jl_codectx_t *ctx)
+                                  bool assign, jl_codectx_t *ctx)
 {
     if (jl_is_symbolnode(s))
         s = jl_symbolnode_sym(s);
@@ -947,7 +924,15 @@ static Value *var_binding_pointer(jl_sym_t *s, jl_binding_t **pbnd,
         }
         return l;
     }
-    return globalvar_binding_pointer(s, pbnd, ctx);
+    jl_binding_t *b=NULL;
+    if (!assign)
+        b = jl_get_binding(ctx->module, s);
+    // if b is NULL, this might be a global that is not set yet but will be,
+    // so get a pointer for writing even when not assigning.
+    if (assign || b==NULL)
+        b = jl_get_binding_wr(ctx->module, s);
+    if (pbnd) *pbnd = b;
+    return literal_pointer_val(&b->value, jl_ppvalue_llvmt);
 }
 
 static int is_var_closed(jl_sym_t *s, jl_codectx_t *ctx)
@@ -996,7 +981,7 @@ static Value *emit_var(jl_sym_t *sym, jl_value_t *ty, jl_codectx_t *ctx)
             }
         }
     }
-    Value *bp = var_binding_pointer(sym, NULL, ctx);
+    Value *bp = var_binding_pointer(sym, NULL, false, ctx);
     Value *arg = (*ctx->arguments)[sym->name];
     // arguments are always defined
     if (arg != NULL ||
@@ -1017,7 +1002,7 @@ static void emit_assignment(jl_value_t *l, jl_value_t *r, jl_codectx_t *ctx)
     else
         assert(false);
     jl_binding_t *bnd=NULL;
-    Value *bp = var_binding_pointer(s, &bnd, ctx);
+    Value *bp = var_binding_pointer(s, &bnd, true, ctx);
     if (bnd) {
         builder.CreateCall2(jlcheckassign_func,
                             literal_pointer_val((void*)bnd),
@@ -1079,8 +1064,10 @@ static Value *emit_expr(jl_value_t *expr, jl_codectx_t *ctx, bool value)
     else if (jl_is_topnode(expr)) {
         jl_sym_t *var = (jl_sym_t*)jl_fieldref(expr,0);
         jl_value_t *etype = jl_fieldref(expr,1);
-        jl_binding_t *b;
-        Value *bp = globalvar_binding_pointer(var, &b, ctx);
+        jl_binding_t *b = jl_get_binding(ctx->module, var);
+        if (b == NULL)
+            b = jl_get_binding_wr(ctx->module, var);
+        Value *bp = literal_pointer_val(&b->value, jl_ppvalue_llvmt);
         if ((b->constp && b->value!=NULL) ||
             (etype!=(jl_value_t*)jl_any_type &&
              !jl_subtype((jl_value_t*)jl_undef_type, etype, 0))) {
@@ -1165,7 +1152,7 @@ static Value *emit_expr(jl_value_t *expr, jl_codectx_t *ctx, bool value)
         int last_depth = ctx->argDepth;
         Value *name = literal_pointer_val(mn);
         jl_binding_t *bnd = NULL;
-        Value *bp = var_binding_pointer((jl_sym_t*)mn, &bnd, ctx);
+        Value *bp = var_binding_pointer((jl_sym_t*)mn, &bnd, true, ctx);
         Value *a1 = emit_expr(args[1], ctx, true);
         make_gcroot(boxed(a1), ctx);
         Value *a2 = emit_expr(args[2], ctx, true);
@@ -1175,39 +1162,10 @@ static Value *emit_expr(jl_value_t *expr, jl_codectx_t *ctx, bool value)
         ctx->argDepth = last_depth;
         return m;
     }
-    else if (ex->head == isbound_sym) {
-        jl_sym_t *sy=NULL;
-        jl_value_t *a = args[0];
-        if (jl_is_symbol(a))
-            sy = (jl_sym_t*)a;
-        else if (jl_is_symbolnode(a))
-            sy = jl_symbolnode_sym(a);
-        else
-            assert(false);
-        Value *bp = var_binding_pointer(sy, NULL, ctx);
-        if (bp->getType()->getContainedType(0) != jl_pvalue_llvmt) {
-            // unboxed vars will never be referenced undefined
-            return ConstantInt::get(T_int1, 1);
-        }
-        jl_value_t *st = expr_type(args[0]);
-        if (st == (jl_value_t*)jl_undef_type) {
-            // type==Undef => definitely not assigned
-            return ConstantInt::get(T_int1, 0);
-        }
-        if (ctx->linfo->specTypes != NULL &&
-            !is_var_closed(sy, ctx) &&
-            !jl_subtype((jl_value_t*)jl_undef_type, st, 0)) {
-            // Undef ⊄ expr_type => definitely assigned
-            return ConstantInt::get(T_int1, 1);
-        }
-        Value *v = builder.CreateLoad(bp, false);
-        Value *isbnd = builder.CreateICmpNE(v, V_null);
-        return isbnd;
-    }
     else if (ex->head == const_sym) {
         jl_sym_t *sym = (jl_sym_t*)args[0];
         jl_binding_t *bnd = NULL;
-        (void)var_binding_pointer(sym, &bnd, ctx);
+        (void)var_binding_pointer(sym, &bnd, true, ctx);
         if (bnd) {
             builder.CreateCall(jldeclareconst_func,
                                literal_pointer_val((void*)bnd));
@@ -1885,16 +1843,6 @@ static void init_julia_llvm_env(Module *m)
     jl_ExecutionEngine->addGlobalMapping(jltypeerror_func,
                                          (void*)&jl_type_error_rt);
 
-    std::vector<Type *> args2(0);
-    args2.push_back(T_pint8);
-    args2.push_back(T_pint8);
-    jlgetbindingp_func =
-        Function::Create(FunctionType::get(jl_ppvalue_llvmt, args2, false),
-                         Function::ExternalLinkage,
-                         "jl_get_bindingp", jl_Module);
-    jl_ExecutionEngine->addGlobalMapping(jlgetbindingp_func,
-                                         (void*)&jl_get_bindingp);
-
     std::vector<Type *> args_2ptrs(0);
     args_2ptrs.push_back(T_pint8);
     args_2ptrs.push_back(jl_pvalue_llvmt);
diff --git a/src/dump.c b/src/dump.c
index d306b4d03e899..35f549b999f27 100644
--- a/src/dump.c
+++ b/src/dump.c
@@ -344,7 +344,12 @@ static void jl_serialize_value_(ios_t *s, jl_value_t *v)
         jl_lambda_info_t *li = (jl_lambda_info_t*)v;
         jl_serialize_value(s, li->ast);
         jl_serialize_value(s, (jl_value_t*)li->sparams);
-        jl_serialize_value(s, (jl_value_t*)li->tfunc);
+        // don't save cached type info for code in the Base module, because
+        // it might reference types in the old System module.
+        if (li->module == jl_base_module)
+            jl_serialize_value(s, (jl_value_t*)jl_null);
+        else
+            jl_serialize_value(s, (jl_value_t*)li->tfunc);
         jl_serialize_value(s, (jl_value_t*)li->name);
         jl_serialize_value(s, (jl_value_t*)li->specTypes);
         jl_serialize_value(s, (jl_value_t*)li->specializations);
@@ -704,7 +709,7 @@ static jl_value_t *jl_deserialize_value(ios_t *s)
             jl_value_t *name = jl_deserialize_value(s);
             if (name == NULL)
                 break;
-            jl_binding_t *b = jl_get_binding(m, (jl_sym_t*)name);
+            jl_binding_t *b = jl_get_binding_wr(m, (jl_sym_t*)name);
             b->value = jl_deserialize_value(s);
             b->type = (jl_type_t*)jl_deserialize_value(s);
             b->constp = read_int8(s);
@@ -817,7 +822,7 @@ void jl_save_system_image(char *fname, char *startscriptname)
         // loaded and we are loading an updated copy in a separate module.
 
         // step 1: set Base.System = current_module
-        jl_binding_t *b = jl_get_binding(jl_base_module, jl_symbol("System"));
+        jl_binding_t *b = jl_get_binding_wr(jl_base_module, jl_symbol("System"));
         b->value = (jl_value_t*)jl_current_module;
         assert(b->constp);
 
@@ -825,12 +830,12 @@ void jl_save_system_image(char *fname, char *startscriptname)
         jl_set_const(jl_current_module, jl_symbol("Base"), (jl_value_t*)jl_base_module);
 
         // step 3: current_module.System = current_module
-        b = jl_get_binding(jl_current_module, jl_symbol("System"));
+        b = jl_get_binding_wr(jl_current_module, jl_symbol("System"));
         b->value = (jl_value_t*)jl_current_module;
         assert(b->constp);
 
         // step 4: remove current_module.current_module
-        b = jl_get_binding(jl_current_module, jl_current_module->name);
+        b = jl_get_binding_wr(jl_current_module, jl_current_module->name);
         b->value = NULL; b->constp = 0;
 
         // step 5: rename current_module to System
@@ -868,6 +873,7 @@ void jl_save_system_image(char *fname, char *startscriptname)
 extern jl_function_t *jl_typeinf_func;
 extern int jl_boot_file_loaded;
 extern void jl_get_builtin_hooks(void);
+extern void jl_get_system_hooks(void);
 
 DLLEXPORT
 void jl_restore_system_image(char *fname)
@@ -921,12 +927,10 @@ void jl_restore_system_image(char *fname)
     }
 
     jl_get_builtin_hooks();
+    jl_get_system_hooks();
     jl_boot_file_loaded = 1;
-    jl_typeinf_func =
-        (jl_function_t*)*(jl_get_bindingp(jl_system_module,
-                                          jl_symbol("typeinf_ext")));
-    jl_show_gf = (jl_function_t*)jl_get_global(jl_system_module,jl_symbol("show"));
-    jl_convert_gf = (jl_function_t*)jl_get_global(jl_system_module,jl_symbol("convert"));
+    jl_typeinf_func = (jl_function_t*)jl_get_global(jl_system_module,
+                                                    jl_symbol("typeinf_ext"));
     jl_init_box_caches();
 
     //jl_deserialize_finalizers(&f);
@@ -1133,7 +1137,7 @@ void jl_init_serializer(void)
     VALUE_TAGS = (ptrint_t)ptrhash_get(&ser_tag, jl_null);
 
     void *fptrs[] = { jl_f_new_expr, jl_f_new_box,
-                      jl_weakref_ctor, jl_f_throw, jl_f_is, 
+                      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, 
@@ -1143,10 +1147,8 @@ void jl_init_serializer(void)
                       jl_f_set_field, jl_f_field_type, 
                       jl_f_arraylen, jl_f_arrayref, 
                       jl_f_arrayset, jl_f_arraysize, 
-                      jl_f_instantiate_type, jl_f_convert, 
-                      jl_f_convert_tuple, jl_f_print_array_uint8, 
-                      jl_f_show_int64, jl_f_show_uint64, 
-                      jl_f_show_any, jl_f_print_symbol, 
+                      jl_f_instantiate_type,
+                      jl_f_convert_default, jl_f_convert_tuple,
                       jl_trampoline, jl_f_new_struct_type, 
                       jl_f_new_struct_fields, jl_f_new_type_constructor, 
                       jl_f_new_tag_type, jl_f_new_tag_type_super, 
diff --git a/src/gc.c b/src/gc.c
index 49530871d6817..1e76a3df7234e 100644
--- a/src/gc.c
+++ b/src/gc.c
@@ -130,7 +130,7 @@ void jl_gc_unpreserve(void)
     (void)arraylist_pop(&preserved_values);
 }
 
-jl_weakref_t *jl_gc_new_weakref(jl_value_t *value)
+DLLEXPORT jl_weakref_t *jl_gc_new_weakref(jl_value_t *value)
 {
     jl_weakref_t *wr = (jl_weakref_t*)alloc_2w();
     wr->type = (jl_type_t*)jl_weakref_type;
diff --git a/src/init.c b/src/init.c
index 660b0085ea74b..8de6b1fd29572 100644
--- a/src/init.c
+++ b/src/init.c
@@ -129,7 +129,6 @@ void julia_init(char *imageFile)
         jl_load_boot_j();
         jl_get_builtin_hooks();
         jl_boot_file_loaded = 1;
-        jl_init_builtins();
         jl_init_box_caches();
     }
 
@@ -246,12 +245,12 @@ DLLEXPORT void jl_enable_inference(void)
     if (jl_boundp(jl_system_module, jl_symbol("typeinf_ext"))) {
         //clear_method_caches();
         jl_typeinf_func =
-            (jl_function_t*)*(jl_get_bindingp(jl_system_module,
-                                              jl_symbol("typeinf_ext")));
+            (jl_function_t*)jl_get_global(jl_system_module,
+                                          jl_symbol("typeinf_ext"));
         // warm up type inference to put the latency up front
         jl_value_t *one = jl_box_long(1);
-        jl_apply((jl_function_t*)*(jl_get_bindingp(jl_system_module,
-                                                   jl_symbol("+"))),
+        jl_apply((jl_function_t*)jl_get_global(jl_system_module,
+                                               jl_symbol("+")),
                  &one, 1);
         /*
           cached t-functions and inferred ASTs need to be cleared at
@@ -279,60 +278,66 @@ DLLEXPORT void jl_enable_inference(void)
     }
 }
 
-static jl_value_t *global(char *name)
+static jl_value_t *base(char *name)
 {
-    return *jl_get_bindingp(jl_base_module, jl_symbol(name));
+    return jl_get_global(jl_base_module, jl_symbol(name));
+}
+
+static jl_value_t *sysmod(char *name)
+{
+    return jl_get_global(jl_system_module, jl_symbol(name));
 }
 
-JL_CALLABLE(jl_weakref_ctor);
 jl_function_t *jl_method_missing_func=NULL;
 
 // fetch references to things defined in boot.j
 void jl_get_builtin_hooks(void)
 {
-    jl_nothing      = global("nothing");
+    jl_nothing      = base("nothing");
     jl_root_task->tls = jl_nothing;
 
-    jl_char_type    = (jl_bits_type_t*)global("Char");
-    jl_int8_type    = (jl_bits_type_t*)global("Int8");
-    jl_uint8_type   = (jl_bits_type_t*)global("Uint8");
-    jl_int16_type   = (jl_bits_type_t*)global("Int16");
-    jl_uint16_type  = (jl_bits_type_t*)global("Uint16");
-    jl_uint32_type  = (jl_bits_type_t*)global("Uint32");
-    jl_uint64_type  = (jl_bits_type_t*)global("Uint64");
-
-    jl_float32_type = (jl_bits_type_t*)global("Float32");
-    jl_float64_type = (jl_bits_type_t*)global("Float64");
-
-    jl_weakref_type = (jl_struct_type_t*)global("WeakRef");
-    jl_weakref_type->fptr = jl_weakref_ctor;
-    jl_weakref_type->env = NULL;
-    jl_weakref_type->linfo = NULL;
-    jl_string_type = (jl_tag_type_t*)global("String");
-    jl_ascii_string_type = (jl_struct_type_t*)global("ASCIIString");
-    jl_utf8_string_type = (jl_struct_type_t*)global("UTF8String");
-    jl_errorexception_type = (jl_struct_type_t*)global("ErrorException");
-    jl_typeerror_type = (jl_struct_type_t*)global("TypeError");
-    jl_loaderror_type = (jl_struct_type_t*)global("LoadError");
-    jl_uniontoocomplex_type = (jl_struct_type_t*)global("UnionTooComplexError");
-    jl_backtrace_type = (jl_struct_type_t*)global("BackTrace");
-    jl_symbolnode_type = (jl_struct_type_t*)global("SymbolNode");
+    jl_char_type    = (jl_bits_type_t*)base("Char");
+    jl_int8_type    = (jl_bits_type_t*)base("Int8");
+    jl_uint8_type   = (jl_bits_type_t*)base("Uint8");
+    jl_int16_type   = (jl_bits_type_t*)base("Int16");
+    jl_uint16_type  = (jl_bits_type_t*)base("Uint16");
+    jl_uint32_type  = (jl_bits_type_t*)base("Uint32");
+    jl_uint64_type  = (jl_bits_type_t*)base("Uint64");
+
+    jl_float32_type = (jl_bits_type_t*)base("Float32");
+    jl_float64_type = (jl_bits_type_t*)base("Float64");
 
     jl_stackovf_exception =
-        jl_apply((jl_function_t*)global("StackOverflowError"), NULL, 0);
+        jl_apply((jl_function_t*)base("StackOverflowError"), NULL, 0);
     jl_divbyzero_exception =
-        jl_apply((jl_function_t*)global("DivideByZeroError"), NULL, 0);
+        jl_apply((jl_function_t*)base("DivideByZeroError"), NULL, 0);
     jl_undefref_exception =
-        jl_apply((jl_function_t*)global("UndefRefError"),NULL,0);
+        jl_apply((jl_function_t*)base("UndefRefError"),NULL,0);
     jl_interrupt_exception =
-        jl_apply((jl_function_t*)global("InterruptException"),NULL,0);
+        jl_apply((jl_function_t*)base("InterruptException"),NULL,0);
     jl_memory_exception =
-        jl_apply((jl_function_t*)global("MemoryError"),NULL,0);
+        jl_apply((jl_function_t*)base("MemoryError"),NULL,0);
 
-    jl_method_missing_func = (jl_function_t*)global("method_missing");
+    jl_weakref_type = (jl_struct_type_t*)base("WeakRef");
+    jl_ascii_string_type = (jl_struct_type_t*)base("ASCIIString");
+    jl_utf8_string_type = (jl_struct_type_t*)base("UTF8String");
+    jl_symbolnode_type = (jl_struct_type_t*)base("SymbolNode");
 
     jl_array_uint8_type =
         (jl_type_t*)jl_apply_type((jl_value_t*)jl_array_type,
                                   jl_tuple2(jl_uint8_type,
                                             jl_box_long(1)));
 }
+
+DLLEXPORT void jl_get_system_hooks(void)
+{
+    if (jl_method_missing_func) return; // only do this once
+
+    jl_errorexception_type = (jl_struct_type_t*)sysmod("ErrorException");
+    jl_typeerror_type = (jl_struct_type_t*)sysmod("TypeError");
+    jl_loaderror_type = (jl_struct_type_t*)sysmod("LoadError");
+    jl_uniontoocomplex_type = (jl_struct_type_t*)sysmod("UnionTooComplexError");
+    jl_backtrace_type = (jl_struct_type_t*)sysmod("BackTrace");
+
+    jl_method_missing_func = (jl_function_t*)sysmod("method_missing");
+}
diff --git a/src/interpreter.c b/src/interpreter.c
index 17b0fa718c23a..865abffa73cc3 100644
--- a/src/interpreter.c
+++ b/src/interpreter.c
@@ -61,30 +61,29 @@ static jl_value_t *do_call(jl_function_t *f, jl_value_t **args, size_t nargs,
 
 jl_value_t *jl_eval_global_var(jl_module_t *m, jl_sym_t *e)
 {
-    jl_value_t **bp = jl_get_bindingp(m, e);
-    if (*bp == NULL)
+    jl_value_t *v = jl_get_global(m, e);
+    if (v == NULL)
         jl_errorf("%s not defined", e->name);
-    return *bp;
-}
-
-static jl_value_t **var_bp(jl_sym_t *s, jl_value_t **locals, size_t nl)
-{
-    size_t i;
-    for(i=0; i < nl; i++) {
-        if (locals[i*2] == (jl_value_t*)s) {
-            return &locals[i*2+1];
-        }
-    }
-    return jl_get_bindingp(jl_current_module, s);
+    return v;
 }
 
 static jl_value_t *eval(jl_value_t *e, jl_value_t **locals, size_t nl)
 {
     if (jl_is_symbol(e)) {
-        jl_value_t **bp = var_bp((jl_sym_t*)e, locals, nl);
-        if (*bp == NULL)
+        jl_value_t *v;
+        size_t i;
+        for(i=0; i < nl; i++) {
+            if (locals[i*2] == e) {
+                v = locals[i*2+1];
+                break;
+            }
+        }
+        if (i >= nl) {
+            v = jl_get_global(jl_current_module, (jl_sym_t*)e);
+        }
+        if (v == NULL)
             jl_errorf("%s not defined", ((jl_sym_t*)e)->name);
-        return *bp;
+        return v;
     }
     if (jl_is_symbolnode(e)) {
         return eval((jl_value_t*)jl_symbolnode_sym(e), locals, nl);
@@ -93,11 +92,11 @@ static jl_value_t *eval(jl_value_t *e, jl_value_t **locals, size_t nl)
         return jl_fieldref(e,0);
     }
     if (jl_is_topnode(e)) {
-        jl_value_t **bp = jl_get_bindingp(jl_current_module,
-                                          (jl_sym_t*)jl_fieldref(e,0));
-        if (*bp == NULL)
+        jl_value_t *v = jl_get_global(jl_current_module,
+                                      (jl_sym_t*)jl_fieldref(e,0));
+        if (v == NULL)
             jl_errorf("%s not defined", ((jl_sym_t*)jl_fieldref(e,0))->name);
-        return *bp;
+        return v;
     }
     if (!jl_is_expr(e)) {
         if (jl_is_lambda_info(e)) {
@@ -123,7 +122,7 @@ static jl_value_t *eval(jl_value_t *e, jl_value_t **locals, size_t nl)
                 return (locals[i*2+1] = eval(args[1], locals, nl));
             }
         }
-        jl_binding_t *b = jl_get_binding(jl_current_module, (jl_sym_t*)sym);
+        jl_binding_t *b = jl_get_binding_wr(jl_current_module, (jl_sym_t*)sym);
         jl_value_t *rhs = eval(args[1], locals, nl);
         jl_checked_assignment(b, rhs);
         return rhs;
@@ -142,10 +141,6 @@ static jl_value_t *eval(jl_value_t *e, jl_value_t **locals, size_t nl)
     else if (ex->head == body_sym) {
         return eval_body(ex->args, locals, nl, 0);
     }
-    else if (ex->head == isbound_sym) {
-        jl_value_t **bp = var_bp((jl_sym_t*)args[0], locals, nl);
-        return (*bp == NULL) ? jl_false : jl_true;
-    }
     else if (ex->head == exc_sym) {
         return jl_exception_in_transit;
     }
@@ -164,7 +159,7 @@ static jl_value_t *eval(jl_value_t *e, jl_value_t **locals, size_t nl)
             }
         }
         if (bp == NULL) {
-            b = jl_get_binding(jl_current_module, fname);
+            b = jl_get_binding_wr(jl_current_module, fname);
             bp = &b->value;
         }
         jl_value_t *atypes=NULL, *meth=NULL;
@@ -184,7 +179,7 @@ static jl_value_t *eval(jl_value_t *e, jl_value_t **locals, size_t nl)
                 return (jl_value_t*)jl_nothing;
             }
         }
-        jl_binding_t *b = jl_get_binding(jl_current_module, (jl_sym_t*)sym);
+        jl_binding_t *b = jl_get_binding_wr(jl_current_module, (jl_sym_t*)sym);
         jl_declare_constant(b);
         return (jl_value_t*)jl_nothing;
     }
diff --git a/src/jltypes.c b/src/jltypes.c
index c6d671ce2a979..94a5d4d036169 100644
--- a/src/jltypes.c
+++ b/src/jltypes.c
@@ -2556,7 +2556,6 @@ void jl_init_types(void)
     module_sym = jl_symbol("module");
     assign_sym = jl_symbol("=");
     null_sym = jl_symbol("null");
-    isbound_sym = jl_symbol("isbound");
     body_sym = jl_symbol("body");
     locals_sym = jl_symbol("locals");
     colons_sym = jl_symbol("::");
diff --git a/src/julia.expmap b/src/julia.expmap
index eb96dbd60ad5b..b89c0878dc841 100644
--- a/src/julia.expmap
+++ b/src/julia.expmap
@@ -132,6 +132,8 @@
     jl_gc_enable;
     jl_gc_disable;
     jl_gc_is_enabled;
+    jl_gc_new_weakref;
+    jl_get_system_hooks;
     jl_errno;
     jl_strerror;
     jl_environ;
@@ -166,7 +168,10 @@
     jl_enter_handler;
     jl_exception_in_transit;
     jl_show;
-    jl_show_float;
+    jl_show_any;
+    jl_print_array_uint8;
+    jl_print_symbol;
+    jl_print_int64;
     jl_pgcstack;
     jl_symbol;
     jl_system_module;
diff --git a/src/julia.h b/src/julia.h
index f8ef5ae8d2c59..bb3af408b7b57 100644
--- a/src/julia.h
+++ b/src/julia.h
@@ -275,7 +275,6 @@ extern jl_tag_type_t *jl_abstractarray_type;
 extern jl_struct_type_t *jl_array_type;
 extern jl_typename_t *jl_array_typename;
 extern jl_struct_type_t *jl_weakref_type;
-extern jl_tag_type_t *jl_string_type;
 extern jl_struct_type_t *jl_ascii_string_type;
 extern jl_struct_type_t *jl_utf8_string_type;
 extern jl_struct_type_t *jl_errorexception_type;
@@ -329,8 +328,6 @@ DLLEXPORT extern jl_value_t *jl_nothing;
 
 extern jl_func_type_t *jl_any_func;
 
-extern jl_function_t *jl_show_gf;
-extern jl_function_t *jl_convert_gf;
 extern jl_function_t *jl_bottom_func;
 extern jl_function_t *jl_method_missing_func;
 extern jl_function_t *jl_unprotect_stack_func;
@@ -353,7 +350,7 @@ extern jl_sym_t *goto_sym;    extern jl_sym_t *goto_ifnot_sym;
 extern jl_sym_t *label_sym;   extern jl_sym_t *return_sym;
 extern jl_sym_t *lambda_sym;  extern jl_sym_t *assign_sym;
 extern jl_sym_t *null_sym;    extern jl_sym_t *body_sym;
-extern jl_sym_t *isbound_sym; extern jl_sym_t *macro_sym;
+extern jl_sym_t *macro_sym;
 extern jl_sym_t *locals_sym;  extern jl_sym_t *colons_sym;
 extern jl_sym_t *Any_sym;     extern jl_sym_t *method_sym;
 extern jl_sym_t *enter_sym;   extern jl_sym_t *leave_sym;
@@ -443,7 +440,6 @@ void *allocb_permanent(size_t sz);
 #define jl_is_ascii_string(v) jl_typeis(v,jl_ascii_string_type)
 #define jl_is_utf8_string(v) jl_typeis(v,jl_utf8_string_type)
 #define jl_is_byte_string(v) (jl_is_ascii_string(v) || jl_is_utf8_string(v))
-#define jl_is_string(v)      jl_subtype(v,(jl_value_t*)jl_string_type,1)
 #define jl_is_cpointer(v)    jl_is_cpointer_type(jl_typeof(v))
 #define jl_is_pointer(v)     jl_is_cpointer_type(jl_typeof(v))
 #define jl_is_gf(f)          (((jl_function_t*)(f))->fptr==jl_apply_generic)
@@ -686,7 +682,6 @@ void jl_init_box_caches(void);
 void jl_init_frontend(void);
 void jl_shutdown_frontend(void);
 void jl_init_primitives(void);
-void jl_init_builtins(void);
 void jl_init_codegen(void);
 void jl_init_intrinsic_functions(void);
 void jl_init_tasks(void *stack, size_t ssize);
@@ -705,16 +700,18 @@ jl_lambda_info_t *jl_wrap_expr(jl_value_t *expr);
 
 // some useful functions
 DLLEXPORT void jl_show(jl_value_t *v);
-jl_value_t *jl_convert(jl_type_t *to, jl_value_t *x);
 
 // modules
 extern jl_module_t *jl_base_module;
 extern DLLEXPORT jl_module_t *jl_system_module;
 extern jl_module_t *jl_current_module;
 jl_module_t *jl_new_module(jl_sym_t *name);
+// get binding for reading
 jl_binding_t *jl_get_binding(jl_module_t *m, jl_sym_t *var);
-jl_value_t **jl_get_bindingp(jl_module_t *m, jl_sym_t *var);
+// get binding for assignment
+jl_binding_t *jl_get_binding_wr(jl_module_t *m, jl_sym_t *var);
 DLLEXPORT int jl_boundp(jl_module_t *m, jl_sym_t *var);
+DLLEXPORT int jl_is_const(jl_module_t *m, jl_sym_t *var);
 DLLEXPORT jl_value_t *jl_get_global(jl_module_t *m, jl_sym_t *var);
 DLLEXPORT void jl_set_global(jl_module_t *m, jl_sym_t *var, jl_value_t *val);
 DLLEXPORT void jl_set_const(jl_module_t *m, jl_sym_t *var, jl_value_t *val);
diff --git a/src/module.c b/src/module.c
index 7821dd0aa5f92..5d5aea7f1dcdf 100644
--- a/src/module.c
+++ b/src/module.c
@@ -32,19 +32,12 @@ jl_module_t *jl_new_module(jl_sym_t *name)
     return m;
 }
 
-jl_binding_t *jl_get_binding(jl_module_t *m, jl_sym_t *var)
+// get binding for assignment
+jl_binding_t *jl_get_binding_wr(jl_module_t *m, jl_sym_t *var)
 {
     jl_binding_t **bp = (jl_binding_t**)ptrhash_bp(&m->bindings, var);
     jl_binding_t *b;
     if (*bp == HT_NOTFOUND) {
-        if (jl_base_module && m != jl_base_module) {
-            // for now, always chain to Base module.
-            // todo: imports/exports, maybe separate rules for read/write
-            b = (jl_binding_t*)ptrhash_get(&jl_base_module->bindings, var);
-            if (b != HT_NOTFOUND) {
-                return b;
-            }
-        }
         b = (jl_binding_t*)allocb(sizeof(jl_binding_t));
         b->name = var;
         b->value = NULL;
@@ -59,7 +52,7 @@ jl_binding_t *jl_get_binding(jl_module_t *m, jl_sym_t *var)
             if (varlist_binding == NULL) {
                 varlist_binding = jl_get_binding(jl_system_module, jl_symbol("VARIABLES"));
             }
-            if (varlist_binding->value != NULL &&
+            if (varlist_binding && varlist_binding->value != NULL &&
                 jl_typeis(varlist_binding->value, jl_array_any_type)) {
                 jl_array_t *a = (jl_array_t*)varlist_binding->value;
                 jl_cell_1d_push(a, (jl_value_t*)var);
@@ -69,31 +62,36 @@ jl_binding_t *jl_get_binding(jl_module_t *m, jl_sym_t *var)
     return *bp;
 }
 
-int jl_boundp(jl_module_t *m, jl_sym_t *var)
-{
-    jl_binding_t *b = (jl_binding_t*)ptrhash_get(&m->bindings, var);
-    if (b == HT_NOTFOUND && jl_base_module && m != jl_base_module) {
-        return jl_boundp(jl_base_module, var);
-    }
-    return (b != HT_NOTFOUND && b->value != NULL);
-}
-
-jl_value_t *jl_get_global(jl_module_t *m, jl_sym_t *var)
+// get binding for reading. might return NULL for unbound.
+jl_binding_t *jl_get_binding(jl_module_t *m, jl_sym_t *var)
 {
     if (m == NULL) return NULL;
     jl_binding_t *b = (jl_binding_t*)ptrhash_get(&m->bindings, var);
     if (b == HT_NOTFOUND) {
         if (jl_base_module && m != jl_base_module) {
-            return jl_get_global(jl_base_module, var);
+            return jl_get_binding(jl_base_module, var);
         }
         return NULL;
     }
+    return b;
+}
+
+int jl_boundp(jl_module_t *m, jl_sym_t *var)
+{
+    jl_binding_t *b = jl_get_binding(m, var);
+    return b && (b->value != NULL);
+}
+
+jl_value_t *jl_get_global(jl_module_t *m, jl_sym_t *var)
+{
+    jl_binding_t *b = jl_get_binding(m, var);
+    if (b == NULL) return NULL;
     return b->value;
 }
 
 void jl_set_global(jl_module_t *m, jl_sym_t *var, jl_value_t *val)
 {
-    jl_binding_t *bp = jl_get_binding(m, var);
+    jl_binding_t *bp = jl_get_binding_wr(m, var);
     if (!bp->constp) {
         bp->value = val;
     }
@@ -101,7 +99,7 @@ void jl_set_global(jl_module_t *m, jl_sym_t *var, jl_value_t *val)
 
 void jl_set_const(jl_module_t *m, jl_sym_t *var, jl_value_t *val)
 {
-    jl_binding_t *bp = jl_get_binding(m, var);
+    jl_binding_t *bp = jl_get_binding_wr(m, var);
     if (!bp->constp) {
         bp->value = val;
         bp->constp = 1;
@@ -111,8 +109,8 @@ void jl_set_const(jl_module_t *m, jl_sym_t *var, jl_value_t *val)
 DLLEXPORT int jl_is_const(jl_module_t *m, jl_sym_t *var)
 {
     if (m == NULL) m = jl_current_module;
-    jl_binding_t *bp = jl_get_binding(m, var);
-    return bp->constp;
+    jl_binding_t *b = jl_get_binding(m, var);
+    return b && b->constp;
 }
 
 void jl_checked_assignment(jl_binding_t *b, jl_value_t *rhs)
@@ -140,12 +138,6 @@ jl_module_t *jl_add_module(jl_module_t *m, jl_module_t *child);
 jl_module_t *jl_get_module(jl_module_t *m, jl_sym_t *name);
 jl_module_t *jl_import_module(jl_module_t *to, jl_module_t *from);
 
-jl_value_t **jl_get_bindingp(jl_module_t *m, jl_sym_t *var)
-{
-    jl_binding_t *b = jl_get_binding(m, var);
-    return &b->value;
-}
-
 jl_function_t *jl_get_expander(jl_module_t *m, jl_sym_t *macroname)
 {
     jl_function_t *f = (jl_function_t*)ptrhash_get(&m->macros, macroname);
diff --git a/ui/repl.c b/ui/repl.c
index f5fc93008fd1b..8b9cb5ed7dab6 100644
--- a/ui/repl.c
+++ b/ui/repl.c
@@ -302,12 +302,12 @@ int true_main(int argc, char *argv[])
     }
 
     jl_array_t *args = jl_alloc_cell_1d(argc);
-    jl_set_global(jl_base_module, jl_symbol("ARGS"), (jl_value_t*)args);
+    jl_set_global(jl_current_module, jl_symbol("ARGS"), (jl_value_t*)args);
     int i;
     for (i=0; i < argc; i++) {
         jl_arrayset(args, i, (jl_value_t*)jl_cstr_to_string(argv[i]));
     }
-    jl_set_const(jl_base_module, jl_symbol("JULIA_HOME"),
+    jl_set_const(jl_current_module, jl_symbol("JULIA_HOME"),
                  jl_cstr_to_string(julia_home));
 
     // run program if specified, otherwise enter REPL