Skip to content

Commit 211d038

Browse files
committed
librustc: Make ~Trait two words by storing the type descriptor in the vtable.
1 parent db518ef commit 211d038

File tree

4 files changed

+73
-53
lines changed

4 files changed

+73
-53
lines changed

src/librustc/middle/trans/common.rs

+1-2
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

+12-3
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

+60-47
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,25 +763,40 @@ 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
let hash_id = vtable_id(ccx, &origin);
763773
match ccx.vtables.find(&hash_id) {
764-
Some(&val) => val,
765-
None => match origin {
766-
typeck::vtable_static(id, substs, sub_vtables) => {
767-
make_impl_vtable(ccx, id, substs, sub_vtables)
774+
Some(&val) => val,
775+
None => {
776+
match origin {
777+
typeck::vtable_static(id, substs, sub_vtables) => {
778+
make_impl_vtable(ccx, id, self_ty, substs, sub_vtables)
779+
}
780+
_ => fail!("get_vtable: expected a static origin"),
781+
}
768782
}
769-
_ => fail!("get_vtable: expected a static origin")
770-
}
771783
}
772784
}
773785

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

811+
/// Generates a dynamic vtable for objects.
789812
pub fn make_impl_vtable(ccx: @CrateContext,
790813
impl_id: ast::def_id,
814+
self_ty: ty::t,
791815
substs: ~[ty::t],
792816
vtables: typeck::vtable_res)
793-
-> ValueRef {
817+
-> ValueRef {
794818
let _icx = ccx.insn_ctxt("impl::make_impl_vtable");
795819
let tcx = ccx.tcx;
796820

@@ -802,9 +826,13 @@ pub fn make_impl_vtable(ccx: @CrateContext,
802826

803827
let has_tps =
804828
!ty::lookup_item_type(ccx.tcx, impl_id).generics.type_param_defs.is_empty();
805-
make_vtable(ccx, ty::trait_method_def_ids(tcx, trt_id).map(|method_def_id| {
829+
830+
let trait_method_def_ids = ty::trait_method_def_ids(tcx, trt_id);
831+
let methods = do trait_method_def_ids.map |method_def_id| {
806832
let im = ty::method(tcx, *method_def_id);
807-
let fty = ty::subst_tps(tcx, substs, None,
833+
let fty = ty::subst_tps(tcx,
834+
substs,
835+
None,
808836
ty::mk_bare_fn(tcx, copy im.fty));
809837
if im.generics.has_type_params() || ty::type_has_self(fty) {
810838
debug!("(making impl vtable) method has self or type params: %s",
@@ -830,7 +858,13 @@ pub fn make_impl_vtable(ccx: @CrateContext,
830858
trans_external_path(ccx, m_id, fty)
831859
}
832860
}
833-
}))
861+
};
862+
863+
// Generate a type descriptor for the vtable.
864+
let tydesc = get_tydesc(ccx, self_ty);
865+
glue::lazily_emit_all_tydesc_glue(ccx, tydesc);
866+
867+
make_vtable(ccx, tydesc, methods)
834868
}
835869

836870
pub fn trans_trait_cast(bcx: block,
@@ -852,40 +886,19 @@ pub fn trans_trait_cast(bcx: block,
852886
let ccx = bcx.ccx();
853887
let v_ty = expr_ty(bcx, val);
854888

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

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

src/librustc/middle/trans/write_guard.rs

-1
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)