Skip to content

Commit 27106d1

Browse files
committed
librustc: Make ~Trait two words by storing the type descriptor in the vtable.
1 parent 3d08e2a commit 27106d1

File tree

4 files changed

+73
-53
lines changed

4 files changed

+73
-53
lines changed

src/librustc/middle/trans/common.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1089,8 +1089,7 @@ pub fn T_opaque_trait(cx: @CrateContext, store: ty::TraitStore) -> TypeRef {
10891089
}
10901090
ty::UniqTraitStore => {
10911091
T_struct(~[T_ptr(cx.tydesc_type),
1092-
T_unique_ptr(T_unique(cx, T_i8())),
1093-
T_ptr(cx.tydesc_type)],
1092+
T_unique_ptr(T_unique(cx, T_i8()))],
10941093
false)
10951094
}
10961095
ty::RegionTraitStore(_) => {

src/librustc/middle/trans/glue.rs

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -545,9 +545,18 @@ pub fn make_drop_glue(bcx: block, v0: ValueRef, t: ty::t) {
545545
}
546546
ty::ty_trait(_, _, ty::UniqTraitStore, _) => {
547547
let lluniquevalue = GEPi(bcx, v0, [0, abi::trt_field_box]);
548-
let lltydesc = Load(bcx, GEPi(bcx, v0, [0, abi::trt_field_tydesc]));
549-
call_tydesc_glue_full(bcx, lluniquevalue, lltydesc,
550-
abi::tydesc_field_free_glue, None);
548+
let llvtable = Load(bcx, GEPi(bcx, v0, [0, abi::trt_field_vtable]));
549+
550+
// Cast the vtable to a pointer to a pointer to a tydesc.
551+
let llvtable = PointerCast(bcx,
552+
llvtable,
553+
T_ptr(T_ptr(ccx.tydesc_type)));
554+
let lltydesc = Load(bcx, llvtable);
555+
call_tydesc_glue_full(bcx,
556+
lluniquevalue,
557+
lltydesc,
558+
abi::tydesc_field_free_glue,
559+
None);
551560
bcx
552561
}
553562
ty::ty_opaque_closure_ptr(ck) => {

src/librustc/middle/trans/meth.rs

Lines changed: 60 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,13 @@ for non-monomorphized methods only. Other methods will
3939
be generated once they are invoked with specific type parameters,
4040
see `trans::base::lval_static_fn()` or `trans::base::monomorphic_fn()`.
4141
*/
42-
pub fn trans_impl(ccx: @CrateContext, path: path, name: ast::ident,
43-
methods: &[@ast::method], generics: &ast::Generics,
44-
self_ty: Option<ty::t>, id: ast::node_id) {
42+
pub fn trans_impl(ccx: @CrateContext,
43+
path: path,
44+
name: ast::ident,
45+
methods: &[@ast::method],
46+
generics: &ast::Generics,
47+
self_ty: Option<ty::t>,
48+
id: ast::node_id) {
4549
let _icx = ccx.insn_ctxt("impl::trans_impl");
4650
let tcx = ccx.tcx;
4751

@@ -718,7 +722,10 @@ pub fn trans_trait_callee_from_llval(bcx: block,
718722
// Load the function from the vtable and cast it to the expected type.
719723
debug!("(translating trait callee) loading method");
720724
let llcallee_ty = type_of_fn_from_ty(ccx, callee_ty);
721-
let mptr = Load(bcx, GEPi(bcx, llvtable, [0u, n_method]));
725+
726+
// Plus one in order to skip past the type descriptor.
727+
let mptr = Load(bcx, GEPi(bcx, llvtable, [0u, n_method + 1]));
728+
722729
let mptr = PointerCast(bcx, mptr, T_ptr(llcallee_ty));
723730

724731
return Callee {
@@ -756,26 +763,41 @@ pub fn vtable_id(ccx: @CrateContext,
756763
}
757764
}
758765

766+
/// Creates a returns a dynamic vtable for the given type and vtable origin.
767+
/// This is used only for objects.
759768
pub fn get_vtable(ccx: @CrateContext,
769+
self_ty: ty::t,
760770
origin: typeck::vtable_origin)
761-
-> ValueRef {
771+
-> ValueRef {
762772
// XXX: Bad copy.
763773
let hash_id = vtable_id(ccx, copy origin);
764774
match ccx.vtables.find(&hash_id) {
765-
Some(&val) => val,
766-
None => match origin {
767-
typeck::vtable_static(id, substs, sub_vtables) => {
768-
make_impl_vtable(ccx, id, substs, sub_vtables)
775+
Some(&val) => val,
776+
None => {
777+
match origin {
778+
typeck::vtable_static(id, substs, sub_vtables) => {
779+
make_impl_vtable(ccx, id, self_ty, substs, sub_vtables)
780+
}
781+
_ => fail!("get_vtable: expected a static origin"),
782+
}
769783
}
770-
_ => fail!("get_vtable: expected a static origin")
771-
}
772784
}
773785
}
774786

775-
pub fn make_vtable(ccx: @CrateContext, ptrs: ~[ValueRef]) -> ValueRef {
787+
/// Helper function to declare and initialize the vtable.
788+
pub fn make_vtable(ccx: @CrateContext,
789+
tydesc: @mut tydesc_info,
790+
ptrs: &[ValueRef])
791+
-> ValueRef {
776792
unsafe {
777793
let _icx = ccx.insn_ctxt("impl::make_vtable");
778-
let tbl = C_struct(ptrs);
794+
795+
let mut components = ~[ tydesc.tydesc ];
796+
for ptrs.each |&ptr| {
797+
components.push(ptr)
798+
}
799+
800+
let tbl = C_struct(components);
779801
let vtable = ccx.sess.str_of((ccx.names)("vtable"));
780802
let vt_gvar = do str::as_c_str(*vtable) |buf| {
781803
llvm::LLVMAddGlobal(ccx.llmod, val_ty(tbl), buf)
@@ -787,11 +809,13 @@ pub fn make_vtable(ccx: @CrateContext, ptrs: ~[ValueRef]) -> ValueRef {
787809
}
788810
}
789811

812+
/// Generates a dynamic vtable for objects.
790813
pub fn make_impl_vtable(ccx: @CrateContext,
791814
impl_id: ast::def_id,
815+
self_ty: ty::t,
792816
substs: ~[ty::t],
793817
vtables: typeck::vtable_res)
794-
-> ValueRef {
818+
-> ValueRef {
795819
let _icx = ccx.insn_ctxt("impl::make_impl_vtable");
796820
let tcx = ccx.tcx;
797821

@@ -800,9 +824,13 @@ pub fn make_impl_vtable(ccx: @CrateContext,
800824

801825
let has_tps =
802826
!ty::lookup_item_type(ccx.tcx, impl_id).generics.type_param_defs.is_empty();
803-
make_vtable(ccx, ty::trait_method_def_ids(tcx, trt_id).map(|method_def_id| {
827+
828+
let trait_method_def_ids = ty::trait_method_def_ids(tcx, trt_id);
829+
let methods = do trait_method_def_ids.map |method_def_id| {
804830
let im = ty::method(tcx, *method_def_id);
805-
let fty = ty::subst_tps(tcx, substs, None,
831+
let fty = ty::subst_tps(tcx,
832+
substs,
833+
None,
806834
ty::mk_bare_fn(tcx, copy im.fty));
807835
if im.generics.has_type_params() || ty::type_has_self(fty) {
808836
debug!("(making impl vtable) method has self or type params: %s",
@@ -828,7 +856,13 @@ pub fn make_impl_vtable(ccx: @CrateContext,
828856
trans_external_path(ccx, m_id, fty)
829857
}
830858
}
831-
}))
859+
};
860+
861+
// Generate a type descriptor for the vtable.
862+
let tydesc = get_tydesc(ccx, self_ty);
863+
glue::lazily_emit_all_tydesc_glue(ccx, tydesc);
864+
865+
make_vtable(ccx, tydesc, methods)
832866
}
833867

834868
pub fn trans_trait_cast(bcx: block,
@@ -850,40 +884,19 @@ pub fn trans_trait_cast(bcx: block,
850884
let ccx = bcx.ccx();
851885
let v_ty = expr_ty(bcx, val);
852886

853-
match store {
854-
ty::RegionTraitStore(_) | ty::BoxTraitStore => {
855-
let mut llboxdest = GEPi(bcx, lldest, [0u, abi::trt_field_box]);
856-
// Just store the pointer into the pair. (Region/borrowed
857-
// and boxed trait objects are represented as pairs, and
858-
// have no type descriptor field.)
859-
llboxdest = PointerCast(bcx,
860-
llboxdest,
861-
T_ptr(type_of(bcx.ccx(), v_ty)));
862-
bcx = expr::trans_into(bcx, val, SaveIn(llboxdest));
863-
}
864-
ty::UniqTraitStore => {
865-
// Translate the uniquely-owned value in the
866-
// triple. (Unique trait objects are represented as
867-
// triples.)
868-
let mut llvaldest = GEPi(bcx, lldest, [0, abi::trt_field_box]);
869-
llvaldest = PointerCast(bcx,
870-
llvaldest,
871-
T_ptr(type_of(bcx.ccx(), v_ty)));
872-
bcx = expr::trans_into(bcx, val, SaveIn(llvaldest));
873-
874-
// Get the type descriptor of the wrapped value and store
875-
// it in the triple as well.
876-
let tydesc = get_tydesc(bcx.ccx(), v_ty);
877-
glue::lazily_emit_all_tydesc_glue(bcx.ccx(), tydesc);
878-
let lltydescdest = GEPi(bcx, lldest, [0, abi::trt_field_tydesc]);
879-
Store(bcx, tydesc.tydesc, lltydescdest);
880-
}
881-
}
887+
let mut llboxdest = GEPi(bcx, lldest, [0u, abi::trt_field_box]);
888+
// Just store the pointer into the pair. (Region/borrowed
889+
// and boxed trait objects are represented as pairs, and
890+
// have no type descriptor field.)
891+
llboxdest = PointerCast(bcx,
892+
llboxdest,
893+
T_ptr(type_of(bcx.ccx(), v_ty)));
894+
bcx = expr::trans_into(bcx, val, SaveIn(llboxdest));
882895

883896
// Store the vtable into the pair or triple.
884897
let orig = /*bad*/copy ccx.maps.vtable_map.get(&id)[0];
885898
let orig = resolve_vtable_in_fn_ctxt(bcx.fcx, orig);
886-
let vtable = get_vtable(bcx.ccx(), orig);
899+
let vtable = get_vtable(bcx.ccx(), v_ty, orig);
887900
Store(bcx, vtable, PointerCast(bcx,
888901
GEPi(bcx, lldest, [0u, abi::trt_field_vtable]),
889902
T_ptr(val_ty(vtable))));

src/librustc/middle/trans/write_guard.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ use middle::trans::common::*;
2323
use middle::trans::datum::*;
2424
use middle::trans::expr;
2525
use middle::ty;
26-
use driver::session;
2726
use syntax::codemap::span;
2827
use syntax::ast;
2928

0 commit comments

Comments
 (0)