Manipulation of the execution context stack

# Ian Hickson (11 years ago)

8.5 Initialization step 4 says "Push newContext onto the execution context stack", and step 8 calls NextTask. 8.4.2 NextTask suspends the running execution context in step 2, then in step 3 asserts "The execution context stack is now empty". However, I can't find anything in the prose around suspension that actually pops the execution context stack. Am I missing something?

# Allen Wirfs-Brock (11 years ago)

On Jul 21, 2014, at 11:23 AM, Ian Hickson wrote:

8.5 Initialization step 4 says "Push newContext onto the execution context stack", and step 8 calls NextTask. 8.4.2 NextTask suspends the running execution context in step 2, then in step 3 asserts "The execution context stack is now empty". However, I can't find anything in the prose around suspension that actually pops the execution context stack. Am I missing something?

A job (task in the version you're looking at) Is always initialized (by NextJob) with an empty execution context stack. NextJob creates a root execution context and then transfers control (a goto, not a call) to the appropriate abstract operation that knows how to start the next job. When that new job eventually completes it will have returned to its initiating abstract operation with an empty execution context stack and its root exeuction context as the active context. Such job initiating abstract operations always end by chaining to another NextJob which suspends (and discards the previous job's root execution context) and starts the process over again for the next job.

The execution context stack for a job actually gets emptied by the normal evaluation of the ECMAScript code of the job. However deeply it calls into ES code it always either explicitly returns back up the stack or abnormal completions (typically exceptions) unwinds the stack back to the execution context of the abstract operation that initiated the job).

The reason that Initialization in 8.5 initially creates a Realm and an execution context is to put the ES environment into a configuration that matches what NextJob normally expects to find when we use it to transition to the next job. We are essentially faking up an initial current job state that NextJob can switch out of when scheduling the first real job.

# Ian Hickson (11 years ago)

On Mon, 21 Jul 2014, Allen Wirfs-Brock wrote:

On Jul 21, 2014, at 11:23 AM, Ian Hickson wrote:

8.5 Initialization step 4 says "Push newContext onto the execution context stack", and step 8 calls NextTask. 8.4.2 NextTask suspends the running execution context in step 2, then in step 3 asserts "The execution context stack is now empty". However, I can't find anything in the prose around suspension that actually pops the execution context stack. Am I missing something?

A job (task in the version you're looking at)

Is there a more up to date version I can look at? I couldn't quite work out what the canonical file to look at was. I've been using this:

people.mozilla.org/~jorendorff/es6-draft.html

is always initialized (by NextJob) with an empty execution context stack.

What step in NextJob does this? It seems that step 3 asserts it, but step 1 doesn't seem to affect the stack, and step 2 refers to the "suspend" prose, which seems mostly non-normative (I can't quite tell it's normative status -- there's no step-by-step algorithms, which seems to be the way the ES spec indications normativity, but there's no RFC2119-style prose either, so I can't tell the descriptive statements in that section from the prescriptive ones).

NextJob creates a root execution context and then transfers control (a goto, not a call)

As phrased it's more like a tail-call, but the three are black-box indistinguishable at the spec level, so that's somewhat academic.

[...] We are essentially faking up an initial current job state that NextJob can switch out of when scheduling the first real job.

I guess what I'm saying is that it's not clear to me where the "switch out" step happens. Do you have a pointer?

# Allen Wirfs-Brock (11 years ago)

On Jul 21, 2014, at 1:29 PM, Ian Hickson wrote:

On Mon, 21 Jul 2014, Allen Wirfs-Brock wrote:

On Jul 21, 2014, at 11:23 AM, Ian Hickson wrote:

8.5 Initialization step 4 says "Push newContext onto the execution context stack", and step 8 calls NextTask. 8.4.2 NextTask suspends the running execution context in step 2, then in step 3 asserts "The execution context stack is now empty". However, I can't find anything in the prose around suspension that actually pops the execution context stack. Am I missing something?

A job (task in the version you're looking at)

Is there a more up to date version I can look at? I couldn't quite work out what the canonical file to look at was. I've been using this:

I just release a new PDF draft Friday at harmony:specification_drafts#july_18_2014_draft_rev_26

people.mozilla.org/~jorendorff/es6-draft.html

Hopefully, Jason will soon have the HTML version ready

is always initialized (by NextJob) with an empty execution context stack.

What step in NextJob does this? It seems that step 3 asserts it, but step 1 doesn't seem to affect the stack, and step 2 refers to the "suspend" prose, which seems mostly non-normative (I can't quite tell it's normative status -- there's no step-by-step algorithms, which seems to be the way the ES spec indications normativity, but there's no RFC2119-style prose either, so I can't tell the descriptive statements in that section from the prescriptive ones).

It's because NextJob is only supposed to be used within an Job initiation abstract operation that is passed to EnqueueJob. So, since we start with an empty stack in 8.5 and each job each returns/unwinds to its starting context it flows like this

<empty stack>

create dummy root context 8.5 Initialization, does stuff returns/unwinds to dummy root context NextJob, deletes dummy root context, creates root context for first job runs the initialization abstract operation for first job returns/unwinds to first job root context NextJob deletes first job root context, creates root context for second job etc...

NextJob creates a root execution context and then transfers control (a goto, not a call)

As phrased it's more like a tail-call, but the three are black-box indistinguishable at the spec level, so that's somewhat academic.

[...] We are essentially faking up an initial current job state that NextJob can switch out of when scheduling the first real job.

I guess what I'm saying is that it's not clear to me where the "switch out" step happens. Do you have a pointer?

Did this help. It essential to the process that jobs always unwind back to its root context.

# Ian Hickson (11 years ago)

On Mon, 21 Jul 2014, Allen Wirfs-Brock wrote:

Is there a more up to date version I can look at? I couldn't quite work out what the canonical file to look at was. I've been using this:

I just release a new PDF draft Friday at harmony:specification_drafts#july_18_2014_draft_rev_26

Ah, cool, thanks.

(Is there a URL that will always point to the very latest version, by any chance?)

is always initialized (by NextJob) with an empty execution context stack.

What step in NextJob does this? It seems that step 3 asserts it, but step 1 doesn't seem to affect the stack, and step 2 refers to the "suspend" prose, which seems mostly non-normative (I can't quite tell it's normative status -- there's no step-by-step algorithms, which seems to be the way the ES spec indications normativity, but there's no RFC2119-style prose either, so I can't tell the descriptive statements in that section from the prescriptive ones).

It's because NextJob is only supposed to be used within an Job initiation abstract operation that is passed to EnqueueJob. So, since we start with an empty stack in 8.5 and each job each returns/unwinds to its starting context it flows like this

<empty stack> create dummy root context 8.5 Initialization, does stuff

The "does stuff" in particular includes step 5, "Push newContext onto the execution context stack".

returns/unwinds to dummy root context

Where?

NextJob, deletes dummy root context

Where?

Step 3 of NextJob says "Assert: The execution context stack is now empty", but I don't see anything that undoes the effect of 8.5's step 5, which makes it not empty. I admit I haven't made an exhaustive search of all the algorithms directly and indirectly called by 8.5. I started trying to trace all the steps between 8.5:5 and NextJob:3 in this e-mail, but that's a lot of calls so it's probably not worth including here.

Do you have a precise pointer to the actual step that unwinds the stack?

# Allen Wirfs-Brock (11 years ago)

On Jul 21, 2014, at 2:35 PM, Ian Hickson wrote:

On Mon, 21 Jul 2014, Allen Wirfs-Brock wrote:

(Is there a URL that will always point to the very latest version, by any chance?)

harmony:specification_drafts

is always initialized (by NextJob) with an empty execution context stack.

What step in NextJob does this? It seems that step 3 asserts it, but step 1 doesn't seem to affect the stack, and step 2 refers to the "suspend" prose, which seems mostly non-normative (I can't quite tell it's normative status -- there's no step-by-step algorithms, which seems to be the way the ES spec indications normativity, but there's no RFC2119-style prose either, so I can't tell the descriptive statements in that section from the prescriptive ones).

It's because NextJob is only supposed to be used within an Job initiation abstract operation that is passed to EnqueueJob. So, since we start with an empty stack in 8.5 and each job each returns/unwinds to its starting context it flows like this

<empty stack> create dummy root context 8.5 Initialization, does stuff

The "does stuff" in particular includes step 5, "Push newContext onto the execution context stack".

yes

returns/unwinds to dummy root context

Where?

This is largely implicit in the ES spec. algorithm conventions (5.2). Abstract operations call each other in a strict call/return manner. Exceptional control flows (such an ES level throw or return statements) are modeled using completion records (6.2.2) that are returned as values from the abstract operations. The execution context stack (8.3) is used to track ES level function activations/returns but not specification level call/returns from abstract operations. Execution contexts are explicitly pushed on to the context stack by call-related abstract operations and explicitly removed at function boundaries for ES return statements and when propagating "throw" completion records past a ES function call boundary.

steps 2-5 of 8.5 establishes the dummy root context, it's the active context when InitializeFirstRealm is performed in step 6. If any thing performed by InitializeFirstRealm happens to create/push additional execution contexts they will be popped by the time we return to step 7 of 8.5.

Step 9 is a NextJob macro and step 2 of NextJob suspends the "running execution context" which in this case is the dummy root context created in steps 2-5. (I just added "and remove it from the execution context stack" to the text NewJob step 2 to make it explicit that suspending the running execution context also removes it from the stack. Steps 6-8 then creates a new root execution context for the next job...

NextJob, deletes dummy root context

Where?

step 2.

Step 3 of NextJob says "Assert: The execution context stack is now empty", but I don't see anything that undoes the effect of 8.5's step 5, which makes it not empty. I admit I haven't made an exhaustive search of all the algorithms directly and indirectly called by 8.5. I started trying to trace all the steps between 8.5:5 and NextJob:3 in this e-mail, but that's a lot of calls so it's probably not worth including here.

Does the text I added to step 2 clear this up?

# Ian Hickson (11 years ago)

On Mon, 21 Jul 2014, Allen Wirfs-Brock wrote:

I just added "and remove it from the execution context stack" to the text NewJob step 2 to make it explicit that suspending the running execution context also removes it from the stack.

Cool, thanks. That fixes the problem.