示例#1
0
void lift_builtins(World& world) {
    // This must be run first
    lift_pipeline(world);

    while (true) {
        Continuation* cur = nullptr;
        Scope::for_each(world, [&] (const Scope& scope) {
            if (cur) return;
            for (auto n : scope.f_cfg().post_order()) {
                if (n->continuation()->order() <= 1)
                    continue;
                if (is_passed_to_accelerator(n->continuation(), false)) {
                    cur = n->continuation();
                    break;
                }
            }
        });

        if (!cur) break;

        static const int inline_threshold = 4;
        if (is_passed_to_intrinsic(cur, Intrinsic::Vectorize)) {
            Scope scope(cur);
            force_inline(scope, inline_threshold);
        }

        Scope scope(cur);

        // remove all continuations - they should be top-level functions and can thus be ignored
        std::vector<const Def*> defs;
        for (auto param : free_defs(scope)) {
            if (!param->isa_continuation()) {
                assert(param->order() == 0 && "creating a higher-order function");
                defs.push_back(param);
            }
        }

        auto lifted = lift(scope, defs);
        for (auto use : cur->copy_uses()) {
            if (auto ucontinuation = use->isa_continuation()) {
                if (auto callee = ucontinuation->callee()->isa_continuation()) {
                    if (callee->is_intrinsic()) {
                        auto old_ops = ucontinuation->ops();
                        Array<const Def*> new_ops(old_ops.size() + defs.size());
                        std::copy(defs.begin(), defs.end(), std::copy(old_ops.begin(), old_ops.end(), new_ops.begin()));    // old ops + former free defs
                        assert(old_ops[use.index()] == cur);
                        new_ops[use.index()] = world.global(lifted, false, lifted->debug());                                // update to new lifted continuation

                        // jump to new top-level dummy function with new args
                        auto fn_type = world.fn_type(Array<const Type*>(new_ops.size()-1, [&] (auto i) { return new_ops[i+1]->type(); }));
                        auto ncontinuation = world.continuation(fn_type, callee->cc(), callee->intrinsic(), callee->debug());
                        ucontinuation->jump(ncontinuation, new_ops.skip_front(), ucontinuation->jump_debug());
                    }
                }
            }
        }

        world.cleanup();
    }
}
示例#2
0
文件: control.cpp 项目: 8l/llambda
ReturnValues<AnyCell>* llbase_call_with_current_continuation(World &world, TypedProcedureCell<ReturnValues<AnyCell>*, ProcedureCell*> *proc)
{
	using dynamic::Continuation;
	using dynamic::EscapeProcedureCell;

	// This is the procedure we're calling
	alloc::StrongRef<TypedProcedureCell<ReturnValues<AnyCell>*, ProcedureCell*>> procRef(world, proc);

	// Create the escape procedure and its args
	// We build this first as there's no way to GC root a continuation at the moment. This also make sure the 
	// continuation stays rooted in the resume path so we can access cont->passedValue(). Otherwise switching dynamic
	// states back to the original continuation could free the the continuation.
	alloc::StrongRef<EscapeProcedureCell> escapeRef(world, EscapeProcedureCell::createInstance(world, nullptr));

	// Capture the current continuation
	Continuation *cont = Continuation::capture(world);
	
	if (ProperList<AnyCell> *passedValues = cont->takePassedValues())
	{
		// We're the result of a continuation being invoked
		return passedValues;
	}
	else
	{
		// We're the original code flow path 
		// Set the continuation on the escape proc - this will make the continuation reachable from GC
		escapeRef->setContinuation(cont);
	
		// Invoke the procedure passing in the escape proc
		// If it returns without invoking the escape proc we'll return through here
		return procRef->apply(world, escapeRef);
	}
}
示例#3
0
 void invoke_continuation(Func& func, Future& future, Continuation& cont,
     boost::mpl::false_)
 {
     try {
         cont.set_data(func(std::move(future)));
     }
     catch (...) {
         cont.set_exception(boost::current_exception());
     }
 }
示例#4
0
 void invoke_continuation(Func& func, Future && future, Continuation& cont,
     std::false_type)
 {
     try {
         cont.set_value(func(std::forward<Future>(future)));
     }
     catch (...) {
         cont.set_exception(std::current_exception());
     }
 }
 void invoke_continuation(Func& func, Future& future, Continuation& cont,
     boost::mpl::true_)
 {
     try {
         func(std::move(future));
         cont.set_value(util::unused);
     }
     catch (...) {
         cont.set_exception(boost::current_exception());
     }
 }
示例#6
0
    typename boost::enable_if<
        traits::is_future<typename util::result_of<Func(Future)>::type>
    >::type invoke_continuation(Func& func, Future& future, Continuation& cont)
    {
        try {
            typedef
                typename util::result_of<Func(Future)>::type
                inner_future;
            typedef
                typename shared_state_ptr_for<inner_future>::type
                inner_shared_state_ptr;

            // take by value, as the future may go away immediately
            inner_shared_state_ptr inner_state =
                future_access::get_shared_state(func(std::move(future)));

            if (inner_state.get() == 0)
            {
                HPX_THROW_EXCEPTION(no_state,
                    "invoke_continuation",
                    "the inner future has no valid shared state");
            }

            // Bind an on_completed handler to this future which will transfer
            // its result to the new future.
            boost::intrusive_ptr<Continuation> cont_(&cont);
            inner_state->set_on_completed(util::bind(
                transfer_result<inner_future>(),
                inner_state, cont_));
        }
        catch (...) {
            cont.set_exception(boost::current_exception());
        }
     }
示例#7
0
    typename std::enable_if<
        traits::detail::is_unique_future<
            typename util::invoke_result<Func, Future>::type
        >::value
    >::type
    invoke_continuation(Func& func, Future && future, Continuation& cont)
    {
        try {
            typedef
                typename util::invoke_result<Func, Future>::type
                inner_future;
            typedef
                typename traits::detail::shared_state_ptr_for<inner_future>::type
                inner_shared_state_ptr;

            // take by value, as the future may go away immediately
            inner_shared_state_ptr inner_state =
                traits::detail::get_shared_state(func(std::forward<Future>(future)));
            typename inner_shared_state_ptr::element_type* ptr =
                inner_state.get();

            if (ptr == nullptr)
            {
                HPX_THROW_EXCEPTION(no_state,
                    "invoke_continuation",
                    "the inner future has no valid shared state");
            }

            // Bind an on_completed handler to this future which will transfer
            // its result to the new future.
            boost::intrusive_ptr<Continuation> cont_(&cont);
            ptr->execute_deferred();
            ptr->set_on_completed(
                util::deferred_call(transfer_result<inner_future>(),
                    std::move(inner_state), std::move(cont_)));
        }
        catch (...) {
            cont.set_exception(std::current_exception());
        }
     }