<commit_before>// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

#include "runtime.h"
#include "arch_GOARCH.h"
#include "stack.h"
#include "malloc.h"

// Code related to defer, panic and recover.

uint32 runtime·panicking;
static Lock paniclk;

enum
{
	DeferChunkSize = 2048
};

// Allocate a Defer, usually as part of the larger frame of deferred functions.
// Each defer must be released with both popdefer and freedefer.
static Defer*
newdefer(int32 siz)
{
	int32 total;
	DeferChunk *c;
	Defer *d;
	
	c = g->dchunk;
	total = sizeof(*d) + ROUND(siz, sizeof(uintptr)) - sizeof(d->args);
	if(c == nil || total > DeferChunkSize - c->off) {
		if(total > DeferChunkSize / 2) {
			// Not worth putting in any chunk.
			// Allocate a separate block.
			d = runtime·malloc(total);
			d->siz = siz;
			d->special = 1;
			d->free = 1;
			d->link = g->defer;
			g->defer = d;
			return d;
		}

		// Cannot fit in current chunk.
		// Switch to next chunk, allocating if necessary.
		c = g->dchunknext;
		if(c == nil)
			c = runtime·malloc(DeferChunkSize);
		c->prev = g->dchunk;
		c->off = sizeof(*c);
		g->dchunk = c;
		g->dchunknext = nil;
	}

	d = (Defer*)((byte*)c + c->off);
	c->off += total;
	d->siz = siz;
	d->special = 0;
	d->free = 0;
	d->link = g->defer;
	g->defer = d;
	return d;	
}

// Pop the current defer from the defer stack.
// Its contents are still valid until the goroutine begins executing again.
// In particular it is safe to call reflect.call(d->fn, d->argp, d->siz) after
// popdefer returns.
static void
popdefer(void)
{
	Defer *d;
	DeferChunk *c;
	int32 total;
	
	d = g->defer;
	if(d == nil)
		runtime·throw("runtime: popdefer nil");
	g->defer = d->link;
	if(d->special) {
		// Nothing else to do.
		return;
	}
	total = sizeof(*d) + ROUND(d->siz, sizeof(uintptr)) - sizeof(d->args);
	c = g->dchunk;
	if(c == nil || (byte*)d+total != (byte*)c+c->off)
		runtime·throw("runtime: popdefer phase error");
	c->off -= total;
	if(c->off == sizeof(*c)) {
		// Chunk now empty, so pop from stack.
		// Save in dchunknext both to help with pingponging between frames
		// and to make sure d is still valid on return.
		if(g->dchunknext != nil)
			runtime·free(g->dchunknext);
		g->dchunknext = c;
		g->dchunk = c->prev;
	}
}

// Free the given defer.
// For defers in the per-goroutine chunk this just clears the saved arguments.
// For large defers allocated on the heap, this frees them.
// The defer cannot be used after this call.
static void
freedefer(Defer *d)
{
	int32 total;

	if(d->special) {
		if(d->free)
			runtime·free(d);
	} else {
		// Wipe out any possible pointers in argp/pc/fn/args.
		total = sizeof(*d) + ROUND(d->siz, sizeof(uintptr)) - sizeof(d->args);
		runtime·memclr((byte*)d, total);
	}
}

// Create a new deferred function fn with siz bytes of arguments.
// The compiler turns a defer statement into a call to this.
// Cannot split the stack because it assumes that the arguments
// are available sequentially after &fn; they would not be
// copied if a stack split occurred.  It's OK for this to call
// functions that split the stack.
#pragma textflag 7
uintptr
runtime·deferproc(int32 siz, FuncVal *fn, ...)
{
	Defer *d;

	d = newdefer(siz);
	d->fn = fn;
	d->pc = runtime·getcallerpc(&siz);
	if(thechar == '5')
		d->argp = (byte*)(&fn+2);  // skip caller's saved link register
	else
		d->argp = (byte*)(&fn+1);
	runtime·memmove(d->args, d->argp, d->siz);

	// deferproc returns 0 normally.
	// a deferred func that stops a panic
	// makes the deferproc return 1.
	// the code the compiler generates always
	// checks the return value and jumps to the
	// end of the function if deferproc returns != 0.
	return 0;
}

// Run a deferred function if there is one.
// The compiler inserts a call to this at the end of any
// function which calls defer.
// If there is a deferred function, this will call runtime·jmpdefer,
// which will jump to the deferred function such that it appears
// to have been called by the caller of deferreturn at the point
// just before deferreturn was called.  The effect is that deferreturn
// is called again and again until there are no more deferred functions.
// Cannot split the stack because we reuse the caller's frame to
// call the deferred function.
//
// The ... in the prototype keeps the compiler from declaring
// an argument frame size. deferreturn is a very special function,
// and if the runtime ever asks for its frame size, that means
// the traceback routines are probably broken.
#pragma textflag 7
void
runtime·deferreturn(uintptr arg0, ...)
{
	Defer *d;
	byte *argp;
	FuncVal *fn;

	d = g->defer;
	if(d == nil)
		return;
	argp = (byte*)&arg0;
	if(d->argp != argp)
		return;
	runtime·memmove(argp, d->args, d->siz);
	fn = d->fn;
	popdefer();
	freedefer(d);
	runtime·jmpdefer(fn, argp);
}

// Run all deferred functions for the current goroutine.
static void
rundefer(void)
{
	Defer *d;

	while((d = g->defer) != nil) {<commit_msg>runtime: disable preemption during deferreturn<commit_after>// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

#include "runtime.h"
#include "arch_GOARCH.h"
#include "stack.h"
#include "malloc.h"

// Code related to defer, panic and recover.

uint32 runtime·panicking;
static Lock paniclk;

enum
{
	DeferChunkSize = 2048
};

// Allocate a Defer, usually as part of the larger frame of deferred functions.
// Each defer must be released with both popdefer and freedefer.
static Defer*
newdefer(int32 siz)
{
	int32 total;
	DeferChunk *c;
	Defer *d;
	
	c = g->dchunk;
	total = sizeof(*d) + ROUND(siz, sizeof(uintptr)) - sizeof(d->args);
	if(c == nil || total > DeferChunkSize - c->off) {
		if(total > DeferChunkSize / 2) {
			// Not worth putting in any chunk.
			// Allocate a separate block.
			d = runtime·malloc(total);
			d->siz = siz;
			d->special = 1;
			d->free = 1;
			d->link = g->defer;
			g->defer = d;
			return d;
		}

		// Cannot fit in current chunk.
		// Switch to next chunk, allocating if necessary.
		c = g->dchunknext;
		if(c == nil)
			c = runtime·malloc(DeferChunkSize);
		c->prev = g->dchunk;
		c->off = sizeof(*c);
		g->dchunk = c;
		g->dchunknext = nil;
	}

	d = (Defer*)((byte*)c + c->off);
	c->off += total;
	d->siz = siz;
	d->special = 0;
	d->free = 0;
	d->link = g->defer;
	g->defer = d;
	return d;	
}

// Pop the current defer from the defer stack.
// Its contents are still valid until the goroutine begins executing again.
// In particular it is safe to call reflect.call(d->fn, d->argp, d->siz) after
// popdefer returns.
static void
popdefer(void)
{
	Defer *d;
	DeferChunk *c;
	int32 total;
	
	d = g->defer;
	if(d == nil)
		runtime·throw("runtime: popdefer nil");
	g->defer = d->link;
	if(d->special) {
		// Nothing else to do.
		return;
	}
	total = sizeof(*d) + ROUND(d->siz, sizeof(uintptr)) - sizeof(d->args);
	c = g->dchunk;
	if(c == nil || (byte*)d+total != (byte*)c+c->off)
		runtime·throw("runtime: popdefer phase error");
	c->off -= total;
	if(c->off == sizeof(*c)) {
		// Chunk now empty, so pop from stack.
		// Save in dchunknext both to help with pingponging between frames
		// and to make sure d is still valid on return.
		if(g->dchunknext != nil)
			runtime·free(g->dchunknext);
		g->dchunknext = c;
		g->dchunk = c->prev;
	}
}

// Free the given defer.
// For defers in the per-goroutine chunk this just clears the saved arguments.
// For large defers allocated on the heap, this frees them.
// The defer cannot be used after this call.
static void
freedefer(Defer *d)
{
	int32 total;

	if(d->special) {
		if(d->free)
			runtime·free(d);
	} else {
		// Wipe out any possible pointers in argp/pc/fn/args.
		total = sizeof(*d) + ROUND(d->siz, sizeof(uintptr)) - sizeof(d->args);
		runtime·memclr((byte*)d, total);
	}
}

// Create a new deferred function fn with siz bytes of arguments.
// The compiler turns a defer statement into a call to this.
// Cannot split the stack because it assumes that the arguments
// are available sequentially after &fn; they would not be
// copied if a stack split occurred.  It's OK for this to call
// functions that split the stack.
#pragma textflag 7
uintptr
runtime·deferproc(int32 siz, FuncVal *fn, ...)
{
	Defer *d;

	d = newdefer(siz);
	d->fn = fn;
	d->pc = runtime·getcallerpc(&siz);
	if(thechar == '5')
		d->argp = (byte*)(&fn+2);  // skip caller's saved link register
	else
		d->argp = (byte*)(&fn+1);
	runtime·memmove(d->args, d->argp, d->siz);

	// deferproc returns 0 normally.
	// a deferred func that stops a panic
	// makes the deferproc return 1.
	// the code the compiler generates always
	// checks the return value and jumps to the
	// end of the function if deferproc returns != 0.
	return 0;
}

// Run a deferred function if there is one.
// The compiler inserts a call to this at the end of any
// function which calls defer.
// If there is a deferred function, this will call runtime·jmpdefer,
// which will jump to the deferred function such that it appears
// to have been called by the caller of deferreturn at the point
// just before deferreturn was called.  The effect is that deferreturn
// is called again and again until there are no more deferred functions.
// Cannot split the stack because we reuse the caller's frame to
// call the deferred function.
//
// The ... in the prototype keeps the compiler from declaring
// an argument frame size. deferreturn is a very special function,
// and if the runtime ever asks for its frame size, that means
// the traceback routines are probably broken.
#pragma textflag 7
void
runtime·deferreturn(uintptr arg0, ...)
{
	Defer *d;
	byte *argp;
	FuncVal *fn;

	d = g->defer;
	if(d == nil)
		return;
	argp = (byte*)&arg0;
	if(d->argp != argp)
		return;

	// Moving arguments around.
	// Do not allow preemption here, because the garbage collector
	// won't know the form of the arguments until the jmpdefer can
	// flip the PC over to fn.
	m->locks++;
	runtime·memmove(argp, d->args, d->siz);
	fn = d->fn;
	popdefer();
	freedefer(d);
	m->locks--;
	if(m->locks == 0 && g->preempt)
		g->stackguard0 = StackPreempt;
	runtime·jmpdefer(fn, argp);
}

// Run all deferred functions for the current goroutine.
static void
rundefer(void)
{
	Defer *d;

	while((d = g->defer) != nil) {
{'fraction_non_alphanumeric': 0.13326256875422174, 'fraction_numerical': 0.007140789346714272, 'mean_word_length': 3.238854805725971, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 128, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5181900', 'n_tokens_mistral': 3791, 'n_tokens_neox': 3522, 'n_words': 1328}