301ff0c2df
Two unfortunate allocations were wrapping a proc() in a proc() with GreenTask::build_start_wrapper, and then boxing this proc in a ~proc() inside of Context::new(). Both of these allocations were a direct result from two conditions: 1. The Context::new() function has a nice api of taking a procedure argument to start up a new context with. This inherently required an allocation by build_start_wrapper because extra code needed to be run around the edges of a user-provided proc() for a new task. 2. The initial bootstrap code only understood how to pass one argument to the next function. By modifying the assembly and entry points to understand more than one argument, more information is passed through in registers instead of allocating a pointer-sized context. This is sadly where I end up throwing mips under a bus because I have no idea what's going on in the mips context switching code and don't know how to modify it. Closes #7767 cc #11389
45 lines
1.5 KiB
Rust
45 lines
1.5 KiB
Rust
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
|
|
// file at the top-level directory of this distribution and at
|
|
// http://rust-lang.org/COPYRIGHT.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
|
// option. This file may not be copied, modified, or distributed
|
|
// except according to those terms.
|
|
|
|
// Coroutines represent nothing more than a context and a stack
|
|
// segment.
|
|
|
|
use context::Context;
|
|
use stack::{StackPool, Stack};
|
|
|
|
/// A coroutine is nothing more than a (register context, stack) pair.
|
|
pub struct Coroutine {
|
|
/// The segment of stack on which the task is currently running or
|
|
/// if the task is blocked, on which the task will resume
|
|
/// execution.
|
|
///
|
|
/// Servo needs this to be public in order to tell SpiderMonkey
|
|
/// about the stack bounds.
|
|
current_stack_segment: Stack,
|
|
|
|
/// Always valid if the task is alive and not running.
|
|
saved_context: Context
|
|
}
|
|
|
|
impl Coroutine {
|
|
pub fn empty() -> Coroutine {
|
|
Coroutine {
|
|
current_stack_segment: unsafe { Stack::dummy_stack() },
|
|
saved_context: Context::empty()
|
|
}
|
|
}
|
|
|
|
/// Destroy coroutine and try to reuse std::stack segment.
|
|
pub fn recycle(self, stack_pool: &mut StackPool) {
|
|
let Coroutine { current_stack_segment, .. } = self;
|
|
stack_pool.give_stack(current_stack_segment);
|
|
}
|
|
}
|