Skip to content

Commit 7ce22f2

Browse files
Firmament2: SOURCE_BEGIN/END around compilation and execution
1 parent e7026ab commit 7ce22f2

File tree

2 files changed

+118
-46
lines changed

2 files changed

+118
-46
lines changed

Python/compile.c

Lines changed: 29 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@
2929

3030
#include <stdbool.h>
3131

32+
#include "firmament2.h"
33+
3234

3335
#undef SUCCESS
3436
#undef ERROR
@@ -103,7 +105,6 @@ typedef struct _PyCompiler {
103105
bool c_save_nested_seqs; /* if true, construct recursive instruction sequences
104106
* (including instructions for nested code objects)
105107
*/
106-
int c_disable_warning;
107108
} compiler;
108109

109110
static int
@@ -136,7 +137,7 @@ compiler_setup(compiler *c, mod_ty mod, PyObject *filename,
136137
c->c_optimize = (optimize == -1) ? _Py_GetConfig()->optimization_level : optimize;
137138
c->c_save_nested_seqs = false;
138139

139-
if (!_PyAST_Preprocess(mod, arena, filename, c->c_optimize, merged, 0, 1)) {
140+
if (!_PyAST_Preprocess(mod, arena, filename, c->c_optimize, merged, 0)) {
140141
return ERROR;
141142
}
142143
c->c_st = _PySymtable_Build(mod, filename, &c->c_future);
@@ -766,9 +767,6 @@ _PyCompile_PushFBlock(compiler *c, location loc,
766767
f->fb_loc = loc;
767768
f->fb_exit = exit;
768769
f->fb_datum = datum;
769-
if (t == COMPILE_FBLOCK_FINALLY_END) {
770-
c->c_disable_warning++;
771-
}
772770
return SUCCESS;
773771
}
774772

@@ -780,9 +778,6 @@ _PyCompile_PopFBlock(compiler *c, fblocktype t, jump_target_label block_label)
780778
u->u_nfblocks--;
781779
assert(u->u_fblock[u->u_nfblocks].fb_type == t);
782780
assert(SAME_JUMP_TARGET_LABEL(u->u_fblock[u->u_nfblocks].fb_block, block_label));
783-
if (t == COMPILE_FBLOCK_FINALLY_END) {
784-
c->c_disable_warning--;
785-
}
786781
}
787782

788783
fblockinfo *
@@ -1210,9 +1205,6 @@ _PyCompile_Error(compiler *c, location loc, const char *format, ...)
12101205
int
12111206
_PyCompile_Warn(compiler *c, location loc, const char *format, ...)
12121207
{
1213-
if (c->c_disable_warning) {
1214-
return 0;
1215-
}
12161208
va_list vargs;
12171209
va_start(vargs, format);
12181210
PyObject *msg = PyUnicode_FromFormatV(format, vargs);
@@ -1473,7 +1465,7 @@ _PyCompile_OptimizeAndAssemble(compiler *c, int addNone)
14731465

14741466
return optimize_and_assemble_code_unit(u, const_cache, code_flags, filename);
14751467
}
1476-
1468+
/* ==================== Firmament2: source scope around public API ==================== */
14771469
PyCodeObject *
14781470
_PyAST_Compile(mod_ty mod, PyObject *filename, PyCompilerFlags *pflags,
14791471
int optimize, PyArena *arena)
@@ -1489,7 +1481,31 @@ _PyAST_Compile(mod_ty mod, PyObject *filename, PyCompilerFlags *pflags,
14891481
assert(co || PyErr_Occurred());
14901482
return co;
14911483
}
1484+
/* Public API: place SOURCE_BEGIN/SOURCE_END so tokenizer+AST+codegen can inherit scope
1485+
when callers go through PyAST_CompileObject(). */
1486+
PyCodeObject *
1487+
PyAST_CompileObject(mod_ty mod, PyObject *filename, PyCompilerFlags *pflags,
1488+
int optimize, PyArena *arena)
1489+
{
1490+
const char *fn_utf8 = NULL;
1491+
int began_scope = 0;
14921492

1493+
if (_firm2_enabled()) {
1494+
if (filename && PyUnicode_Check(filename)) {
1495+
fn_utf8 = PyUnicode_AsUTF8(filename); /* borrowed */
1496+
}
1497+
_firm2_source_begin(fn_utf8);
1498+
began_scope = 1;
1499+
}
1500+
1501+
PyCodeObject *co = _PyAST_Compile(mod, filename, pflags, optimize, arena);
1502+
1503+
if (began_scope) {
1504+
_firm2_source_end();
1505+
}
1506+
return co;
1507+
}
1508+
/* ================== end Firmament2: source scope around public API =================== */
14931509
int
14941510
_PyCompile_AstPreprocess(mod_ty mod, PyObject *filename, PyCompilerFlags *cf,
14951511
int optimize, PyArena *arena, int no_const_folding)
@@ -1502,7 +1518,7 @@ _PyCompile_AstPreprocess(mod_ty mod, PyObject *filename, PyCompilerFlags *cf,
15021518
if (optimize == -1) {
15031519
optimize = _Py_GetConfig()->optimization_level;
15041520
}
1505-
if (!_PyAST_Preprocess(mod, arena, filename, optimize, flags, no_const_folding, 0)) {
1521+
if (!_PyAST_Preprocess(mod, arena, filename, optimize, flags, no_const_folding)) {
15061522
return -1;
15071523
}
15081524
return 0;

Python/pythonrun.c

Lines changed: 89 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,9 @@
4141
# include "windows.h"
4242
#endif
4343

44+
/* Firmament2 */
45+
#include "firmament2.h"
46+
4447
/* Forward */
4548
static void flush_io(void);
4649
static PyObject *run_mod(mod_ty, PyObject *, PyObject *, PyObject *,
@@ -1234,36 +1237,49 @@ _PyRun_StringFlagsWithName(const char *str, PyObject* name, int start,
12341237
int generate_new_source)
12351238
{
12361239
PyObject *ret = NULL;
1237-
mod_ty mod;
1238-
PyArena *arena;
1239-
1240-
arena = _PyArena_New();
1240+
PyArena *arena = _PyArena_New();
12411241
if (arena == NULL)
12421242
return NULL;
12431243

12441244
PyObject* source = NULL;
12451245
_Py_DECLARE_STR(anon_string, "<string>");
12461246

1247-
if (name) {
1247+
if (!name) {
1248+
name = &_Py_STR(anon_string);
1249+
} else {
12481250
source = PyUnicode_FromString(str);
12491251
if (!source) {
12501252
PyErr_Clear();
12511253
}
1252-
} else {
1253-
name = &_Py_STR(anon_string);
12541254
}
12551255

1256-
mod = _PyParser_ASTFromString(str, name, start, flags, arena);
1256+
/* Begin source scope before parsing so tokens are attributed correctly */
1257+
int began_scope = 0;
1258+
const char *fn_utf8 = NULL;
1259+
if (_firm2_enabled()) {
1260+
if (name && PyUnicode_Check(name)) {
1261+
fn_utf8 = PyUnicode_AsUTF8(name);
1262+
}
1263+
_firm2_source_begin(fn_utf8);
1264+
began_scope = 1;
1265+
}
1266+
1267+
mod_ty mod = _PyParser_ASTFromString(str, name, start, flags, arena);
12571268

1258-
if (mod != NULL) {
1259-
ret = run_mod(mod, name, globals, locals, flags, arena, source, generate_new_source);
1269+
if (mod != NULL) {
1270+
ret = run_mod(mod, name, globals, locals, flags, arena,
1271+
source, generate_new_source);
12601272
}
1273+
1274+
if (began_scope) {
1275+
_firm2_source_end();
1276+
}
1277+
12611278
Py_XDECREF(source);
12621279
_PyArena_Free(arena);
12631280
return ret;
12641281
}
12651282

1266-
12671283
PyObject *
12681284
PyRun_StringFlags(const char *str, int start, PyObject *globals,
12691285
PyObject *locals, PyCompilerFlags *flags) {
@@ -1280,27 +1296,37 @@ pyrun_file(FILE *fp, PyObject *filename, int start, PyObject *globals,
12801296
return NULL;
12811297
}
12821298

1283-
mod_ty mod;
1284-
mod = _PyParser_ASTFromFile(fp, filename, NULL, start, NULL, NULL,
1285-
flags, NULL, arena);
1299+
/* Begin source scope before we tokenize/parse so tokens get filename/source_id */
1300+
int began_scope = 0;
1301+
const char *fn_utf8 = NULL;
1302+
if (_firm2_enabled()) {
1303+
if (filename && PyUnicode_Check(filename)) {
1304+
fn_utf8 = PyUnicode_AsUTF8(filename);
1305+
}
1306+
_firm2_source_begin(fn_utf8);
1307+
began_scope = 1;
1308+
}
1309+
1310+
mod_ty mod = _PyParser_ASTFromFile(fp, filename, NULL, start, NULL, NULL,
1311+
flags, NULL, arena);
12861312

12871313
if (closeit) {
12881314
fclose(fp);
12891315
}
12901316

1291-
PyObject *ret;
1317+
PyObject *ret = NULL;
12921318
if (mod != NULL) {
12931319
ret = run_mod(mod, filename, globals, locals, flags, arena, NULL, 0);
12941320
}
1295-
else {
1296-
ret = NULL;
1321+
1322+
if (began_scope) {
1323+
_firm2_source_end();
12971324
}
1298-
_PyArena_Free(arena);
12991325

1326+
_PyArena_Free(arena);
13001327
return ret;
13011328
}
13021329

1303-
13041330
PyObject *
13051331
PyRun_FileExFlags(FILE *fp, const char *filename, int start, PyObject *globals,
13061332
PyObject *locals, int closeit, PyCompilerFlags *flags)
@@ -1508,30 +1534,60 @@ PyObject *
15081534
Py_CompileStringObject(const char *str, PyObject *filename, int start,
15091535
PyCompilerFlags *flags, int optimize)
15101536
{
1511-
PyCodeObject *co;
1512-
mod_ty mod;
1537+
PyObject *res = NULL; /* return value: AST or PyCodeObject* */
1538+
mod_ty mod = NULL;
15131539
PyArena *arena = _PyArena_New();
1514-
if (arena == NULL)
1540+
if (arena == NULL) {
15151541
return NULL;
1542+
}
1543+
1544+
/* ---- Firmament2 source scope: begin before tokenization ---- */
1545+
const char *fn_utf8 = NULL;
1546+
int began_scope = 0;
1547+
if (_firm2_enabled()) {
1548+
if (filename && PyUnicode_Check(filename)) {
1549+
fn_utf8 = PyUnicode_AsUTF8(filename); /* borrowed; may be NULL */
1550+
}
1551+
if (fn_utf8 == NULL) {
1552+
/* Provide a stable label for string inputs if not a PyUnicode */
1553+
fn_utf8 = "<string>";
1554+
}
1555+
_firm2_source_begin(fn_utf8);
1556+
began_scope = 1;
1557+
}
1558+
/* ------------------------------------------------------------ */
15161559

15171560
mod = _PyParser_ASTFromString(str, filename, start, flags, arena);
15181561
if (mod == NULL) {
1519-
_PyArena_Free(arena);
1520-
return NULL;
1562+
goto done; /* arena freed + scope ended in done: block */
15211563
}
1564+
15221565
if (flags && (flags->cf_flags & PyCF_ONLY_AST)) {
1523-
int syntax_check_only = ((flags->cf_flags & PyCF_OPTIMIZED_AST) == PyCF_ONLY_AST); /* unoptiomized AST */
1524-
if (_PyCompile_AstPreprocess(mod, filename, flags, optimize, arena, syntax_check_only) < 0) {
1525-
_PyArena_Free(arena);
1526-
return NULL;
1566+
/* Return AST object (optionally preprocessed), not bytecode */
1567+
int syntax_check_only =
1568+
((flags->cf_flags & PyCF_OPTIMIZED_AST) == PyCF_ONLY_AST); /* unoptimized AST */
1569+
if (_PyCompile_AstPreprocess(mod, filename, flags, optimize, arena,
1570+
syntax_check_only) < 0) {
1571+
goto done;
15271572
}
1528-
PyObject *result = PyAST_mod2obj(mod);
1529-
_PyArena_Free(arena);
1530-
return result;
1573+
res = PyAST_mod2obj(mod);
1574+
goto done;
1575+
}
1576+
1577+
/* Compile to code object WITHOUT calling the public wrapper, so we
1578+
keep exactly one SOURCE_BEGIN/SOURCE_END from this scope. */
1579+
{
1580+
PyCodeObject *co = _PyAST_Compile(mod, filename, flags, optimize, arena);
1581+
res = (PyObject *)co; /* may be NULL on error */
15311582
}
1532-
co = _PyAST_Compile(mod, filename, flags, optimize, arena);
1583+
1584+
done:
15331585
_PyArena_Free(arena);
1534-
return (PyObject *)co;
1586+
1587+
if (began_scope) {
1588+
_firm2_source_end();
1589+
}
1590+
return res;
15351591
}
15361592

15371593
PyObject *

0 commit comments

Comments
 (0)