Skip to content

Commit 6423cc7

Browse files
committed
Comments and cleanup, in preparation for more work on issue #702.
1 parent f4eacbb commit 6423cc7

File tree

1 file changed

+56
-19
lines changed

1 file changed

+56
-19
lines changed

src/comp/middle/trans.rs

+56-19
Original file line numberDiff line numberDiff line change
@@ -6482,23 +6482,42 @@ fn trans_fn(cx: @local_ctxt, sp: &span, f: &ast::_fn, llfndecl: ValueRef,
64826482
}
64836483

64846484
// process_fwding_mthd: Create the forwarding function that appears in a
6485-
// vtable slot for method calls that "fall through" to an inner object. A
6485+
// vtable slot for method calls that need to forward to another object. A
64866486
// helper function for create_vtbl.
6487+
//
6488+
// We use forwarding functions in two situations:
6489+
//
6490+
// (1) Forwarding: For method calls that fall through to an inner object, For
6491+
// example, suppose an inner object has method foo and we extend it with
6492+
// a method bar. The only version of 'foo' we have is on the inner
6493+
// object, but we would like to be able to call outer.foo(). So we use a
6494+
// forwarding function to make the foo method available on the outer
6495+
// object. It takes all the same arguments as the foo method on the
6496+
// inner object does, calls inner.foo() with those arguments, and then
6497+
// returns the value returned from that call. (The inner object won't
6498+
// exist until run-time, but we know its type statically.)
6499+
//
6500+
// (2) Backwarding: For method calls that dispatch back through an outer
6501+
// object. For example, suppose an inner object has methods foo and bar,
6502+
// and bar contains the call self.foo(). We extend that object with a
6503+
// foo method that overrides the inner foo. Now, a call to outer.bar()
6504+
// should send us to to inner.bar() via a normal forwarding function, and
6505+
// then to self.foo(). But inner.bar() was already compiled under the
6506+
// assumption that self.foo() is inner.foo(), when we really want to
6507+
// reach outer.foo(). So, we give 'self' a vtable of backwarding
6508+
// functions, one for each method on inner, each of which takes all the
6509+
// same arguments as the corresponding method on inner does, calls that
6510+
// method on outer, and returns the value returned from that call.
6511+
64876512
fn process_fwding_mthd(cx: @local_ctxt, sp: &span, m: @ty::method,
6488-
ty_params: &ast::ty_param[], inner_obj_ty: ty::t,
6513+
ty_params: &ast::ty_param[], target_obj_ty: ty::t,
64896514
backwarding_vtbl: option::t[ValueRef],
64906515
additional_field_tys: &ty::t[]) -> ValueRef {
64916516

6492-
6493-
// The method m is being called on the outer object, but the outer object
6494-
// doesn't have that method; only the inner object does. So what we have
6495-
// to do is synthesize that method on the outer object. It has to take
6496-
// all the same arguments as the method on the inner object does, then
6497-
// call m with those arguments on the inner object, and then return the
6498-
// value returned from that call. It's like an eta-expansion around m,
6499-
// except we also have to pass the inner object that m should be called
6500-
// on. That object won't exist until run-time, but we know its type
6501-
// statically.
6517+
// NB: target_obj_ty is the type of the object being forwarded to.
6518+
// Depending on whether this is a forwarding or backwarding function, it
6519+
// will be either the inner obj's type or the outer obj's type,
6520+
// respectively.
65026521

65036522
// Create a local context that's aware of the name of the method we're
65046523
// creating.
@@ -6534,16 +6553,24 @@ fn process_fwding_mthd(cx: @local_ctxt, sp: &span, m: @ty::method,
65346553

65356554
// Do backwarding if necessary.
65366555
alt (backwarding_vtbl) {
6537-
none. { /* fall through */ }
6556+
none. {
6557+
// NB: As before, this means that we are processing a backwarding fn
6558+
// right now.
6559+
}
65386560
some(bv) {
6539-
// Grab the vtable out of the self-object.
6561+
// NB: As before, this means that we are processing a forwarding fn
6562+
// right now.
6563+
6564+
// Grab the vtable out of the self-object and replace it with the
6565+
// backwarding vtable.
65406566
let llself_obj_vtbl =
65416567
bcx.build.GEP(llself_obj_ptr, ~[C_int(0),
65426568
C_int(abi::obj_field_vtbl)]);
6543-
6544-
// And replace it with the backwarding vtbl.
65456569
let llbv = bcx.build.PointerCast(bv, T_ptr(T_empty_struct()));
65466570
bcx.build.Store(llbv, llself_obj_vtbl);
6571+
6572+
// NB: llself_obj is now a freakish combination of outer object body
6573+
// and backwarding (inner-object) vtable.
65476574
}
65486575
}
65496576

@@ -6595,6 +6622,15 @@ fn process_fwding_mthd(cx: @local_ctxt, sp: &span, m: @ty::method,
65956622

65966623
// Tuple type for body:
65976624
// [tydesc, [typaram, ...], [field, ...], inner_obj]
6625+
6626+
// NB: When we're creating a forwarding fn, target_obj_ty is indeed the
6627+
// type of the inner object, so it makes sense to have 'target_obj_ty'
6628+
// appear here. When we're creating a backwarding fn, though,
6629+
// target_obj_ty is the outer object's type, so instead, we need to use
6630+
// the extra inner type we passed along.
6631+
6632+
let inner_obj_ty = target_obj_ty;
6633+
65986634
let body_ty: ty::t =
65996635
ty::mk_imm_tup(cx.ccx.tcx,
66006636
~[tydesc_ty, typarams_ty, fields_ty, inner_obj_ty]);
@@ -6621,14 +6657,14 @@ fn process_fwding_mthd(cx: @local_ctxt, sp: &span, m: @ty::method,
66216657

66226658
// Get the index of the method we want.
66236659
let ix: uint = 0u;
6624-
alt ty::struct(bcx_tcx(bcx), inner_obj_ty) {
6660+
alt ty::struct(bcx_tcx(bcx), target_obj_ty) {
66256661
ty::ty_obj(methods) {
66266662
ix = ty::method_idx(cx.ccx.sess, sp, m.ident, methods);
66276663
}
66286664
_ {
66296665
// Shouldn't happen.
66306666
cx.ccx.sess.bug("process_fwding_mthd(): non-object type passed \
6631-
as inner_obj_ty");
6667+
as target_obj_ty");
66326668
}
66336669
}
66346670

@@ -6652,7 +6688,8 @@ fn process_fwding_mthd(cx: @local_ctxt, sp: &span, m: @ty::method,
66526688

66536689
// Set up the three implicit arguments to the original method we'll need
66546690
// to call.
6655-
let llorig_mthd_args: ValueRef[] = ~[llretptr, fcx.lltaskptr, llself_obj];
6691+
let self_arg = llself_obj;
6692+
let llorig_mthd_args: ValueRef[] = ~[llretptr, fcx.lltaskptr, self_arg];
66566693

66576694
// Copy the explicit arguments that are being passed into the forwarding
66586695
// function (they're in fcx.llargs) to llorig_mthd_args.

0 commit comments

Comments
 (0)