fn check_should_inline_func(
        &mut self,
        has_exc: bool,
        callee: MuID,
        caller: MuID,
        vm: &VM
    ) -> bool {
        // recursive call, do not inline
        if callee == caller {
            return false;
        }

        let funcs_guard = vm.funcs().read().unwrap();
        let func = match funcs_guard.get(&callee) {
            Some(func) => func.read().unwrap(),
            None => panic!("callee {} is undeclared", callee)
        };
        let fv_id = match func.cur_ver {
            Some(fv_id) => fv_id,
            None => {
                // the funtion is not defined
                info!("the function is undefined, we cannot inline it. ");
                return false;
            }
        };

        // if we have checked this callee before, we use the same result
        // (this is not optimal though. The inline criteria we use at the moment
        // do not take caller size growth into consideration, so we will
        // get the same result anyway. )
        match self.should_inline.get(&fv_id) {
            Some(flag) => {
                trace!("func {} should be inlined (checked before)", callee);
                return *flag;
            }
            None => {}
        }

        let fv_guard = vm.func_vers().read().unwrap();
        let fv = fv_guard.get(&fv_id).unwrap().read().unwrap();

        // if the function is forced inline, we inline it
        if fv.force_inline {
            trace!("func {} is forced as inline function", callee);
            return true;
        }

        // some heuristics here to decide if we should inline the function
        let n_insts = estimate_insts(&fv);
        let could_throw = fv.could_throw();
        let has_tailcall = fv.has_tailcall();

        // simple heuristic here:
        // * estimated machine insts are fewer than 10 insts
        // * leaf in call graph (no out calls)
        // * no throw (otherwise we will need to rearrange catch)
        let should_inline = n_insts <= 25 && !(has_exc && could_throw) && !has_tailcall;

        trace!("func {} has {} insts (estimated)", callee, n_insts);
        trace!(
            "     has exception clause? {}, could throw? {}",
            has_exc,
            could_throw
        );
        trace!("SO func should be inlined? {}", should_inline);

        self.should_inline.insert(callee, should_inline);

        should_inline
    }
/// checks whether we should inline the caller into the callee
checks whether we should inline the caller into the callee
checks whether we should inline the caller into the callee
fn check_should_inline_func(
        &mut self,
        has_exc: bool,
        callee: MuID,
        caller: MuID,
        vm: &VM
    ) -> bool {
        // recursive call, do not inline
        if callee == caller {
            return false;
        }
        let funcs_guard = vm.funcs().read().unwrap();
        let func = match funcs_guard.get(&callee) {
            Some(func) => func.read().unwrap(),
            None => panic!("callee {} is undeclared", callee)
        };
        let fv_id = match func.cur_ver {
            Some(fv_id) => fv_id,
            None => {
                // the funtion is not defined
                info!("the function is undefined, we cannot inline it. ");
                return false;
            }
        };
        // if we have checked this callee before, we use the same result
        // (this is not optimal though. The inline criteria we use at the moment
        // do not take caller size growth into consideration, so we will
        // get the same result anyway. )
        match self.should_inline.get(&fv_id) {
            Some(flag) => {
                trace!("func {} should be inlined (checked before)", callee);
                return *flag;
            }
            None => {}
        }
        let fv_guard = vm.func_vers().read().unwrap();
        let fv = fv_guard.get(&fv_id).unwrap().read().unwrap();
        // if the function is forced inline, we inline it
        if fv.force_inline {
            trace!("func {} is forced as inline function", callee);
            return true;
        }
        // some heuristics here to decide if we should inline the function
        let n_insts = estimate_insts(&fv);
        let could_throw = fv.could_throw();
        let has_tailcall = fv.has_tailcall();
        // simple heuristic here:
        // * estimated machine insts are fewer than 10 insts
        // * leaf in call graph (no out calls)
        // * no throw (otherwise we will need to rearrange catch)
        let should_inline = n_insts <= 25 && !(has_exc && could_throw) && !has_tailcall;
        trace!("func {} has {} insts (estimated)", callee, n_insts);
        trace!(
            "     has exception clause? {}, could throw? {}",
            has_exc,
            could_throw
        );
        trace!("SO func should be inlined? {}", should_inline);
        self.should_inline.insert(callee, should_inline);
        should_inline
    }
fn check_should_inline_func ( & mut self , has_exc : bool , callee : MuID , caller : MuID , vm : & VM ) -> bool { // recursive call, do not inline if callee == caller { return false ; } let funcs_guard = vm . funcs ( ) . read ( ) . unwrap ( ) ; let func = match funcs_guard . get ( & callee ) { Some ( func ) => func . read ( ) . unwrap ( ) , None => panic ! ( " " callee ) } ; let fv_id = match func . cur_ver { Some ( fv_id ) => fv_id , None => { // the funtion is not defined info ! ( " " ) ; return false ; } } ; // if we have checked this callee before, we use the same result // (this is not optimal though. The inline criteria we use at the moment // do not take caller size growth into consideration, so we will // get the same result anyway. ) match self . should_inline . get ( & fv_id ) { Some ( flag ) => { trace ! ( " " callee ) ; return * flag ; } None => { } } let fv_guard = vm . func_vers ( ) . read ( ) . unwrap ( ) ; let fv = fv_guard . get ( & fv_id ) . unwrap ( ) . read ( ) . unwrap ( ) ; // if the function is forced inline, we inline it if fv . force_inline { trace ! ( " " callee ) ; return true ; } // some heuristics here to decide if we should inline the function let n_insts = estimate_insts ( & fv ) ; let could_throw = fv . could_throw ( ) ; let has_tailcall = fv . has_tailcall ( ) ; // simple heuristic here: // * estimated machine insts are fewer than 10 insts // * leaf in call graph (no out calls) // * no throw (otherwise we will need to rearrange catch) let should_inline = n_insts <= 25 && ! ( has_exc && could_throw ) && ! has_tailcall ; trace ! ( " " callee n_insts ) ; trace ! ( " " has_exc could_throw ) ; trace ! ( " " should_inline ) ; self . should_inline . insert ( callee , should_inline ) ; should_inline }
checks whether we should inline the caller into the callee
checks whether we should inline the caller into the callee
&mut self
has_exc
bool
callee
MuID
caller
MuID
vm
&VM
&mut self
has_exc
bool
callee
MuID
caller
MuID
vm
&VM