Tcl Source Code

Check-in [897093b790]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Proof of concept to reduce interp start times by lazy loading oo
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | apn-oo-lazy-init
Files: files | file ages | folders
SHA3-256: 897093b79058d884c5b75fdfc982e7c9d1d34f4f187c5f9e5d09211134d66a54
User & Date: apnadkarni 2025-08-16 04:02:16.526
Context
2025-08-16
04:22
Delete oo::singleton,configurable commands before defining them as classes Leaf check-in: edd3cd05f0 user: apnadkarni tags: apn-oo-lazy-init
04:02
Proof of concept to reduce interp start times by lazy loading oo check-in: 897093b790 user: apnadkarni tags: apn-oo-lazy-init
2025-08-14
13:32
Fix [87b69745be] - move zipfs encoding initialization outside of interp creation. Avoid unnecessary ... check-in: 0433b67adc user: apnadkarni tags: core-9-0-branch
Changes
Unified Diff Ignore Whitespace Patch
Changes to generic/tclBasic.c.
1103
1104
1105
1106
1107
1108
1109

1110
1111
1112
1113
1114
1115
1116
    iPtr->allocCache = (AllocCache *)TclpGetAllocCache();
#else
    iPtr->allocCache = NULL;
#endif
    iPtr->pendingObjDataPtr = NULL;
    iPtr->asyncReadyPtr = TclGetAsyncReadyPtr();
    iPtr->deferredCallbacks = NULL;


    /*
     * Create the core commands. Do it here, rather than calling Tcl_CreateObjCommand,
     * because it's faster (there's no need to check for a preexisting command
     * by the same name). Set the Tcl_CmdProc to NULL.
     */








>







1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
    iPtr->allocCache = (AllocCache *)TclpGetAllocCache();
#else
    iPtr->allocCache = NULL;
#endif
    iPtr->pendingObjDataPtr = NULL;
    iPtr->asyncReadyPtr = TclGetAsyncReadyPtr();
    iPtr->deferredCallbacks = NULL;
    iPtr->objectFoundation = NULL;

    /*
     * Create the core commands. Do it here, rather than calling Tcl_CreateObjCommand,
     * because it's faster (there's no need to check for a preexisting command
     * by the same name). Set the Tcl_CmdProc to NULL.
     */

Changes to generic/tclOO.c.
11
12
13
14
15
16
17

18
19
20
21
22
23
24
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "tclInt.h"
#include "tclOOInt.h"


/*
 * Commands in oo::define and oo::objdefine.
 */

static const struct {
    const char *name;







>







11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "tclInt.h"
#include "tclOOInt.h"
#include <assert.h>

/*
 * Commands in oo::define and oo::objdefine.
 */

static const struct {
    const char *name;
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157

static const Tcl_MethodType classConstructor = {
    TCL_OO_METHOD_VERSION_CURRENT,
    "oo::class constructor",
    TclOO_Class_Constructor, NULL, NULL
};

/*
 * Scripted parts of TclOO. First, the main script (cannot be outside this
 * file).
 */

static const char initScript[] =
#ifndef TCL_NO_DEPRECATED
"package ifneeded TclOO " TCLOO_PATCHLEVEL " {# Already present, OK?};"
#endif
"package ifneeded tcl::oo " TCLOO_PATCHLEVEL " {# Already present, OK?};"
"namespace eval ::oo { variable version " TCLOO_VERSION " };"
"namespace eval ::oo { variable patchlevel " TCLOO_PATCHLEVEL " };";
/* "tcl_findLibrary tcloo $oo::version $oo::version" */
/* " tcloo.tcl OO_LIBRARY oo::library;"; */

/*
 * The scripted part of the definitions of TclOO.
 */

#include "tclOOScript.h"

/*







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







130
131
132
133
134
135
136















137
138
139
140
141
142
143

static const Tcl_MethodType classConstructor = {
    TCL_OO_METHOD_VERSION_CURRENT,
    "oo::class constructor",
    TclOO_Class_Constructor, NULL, NULL
};
















/*
 * The scripted part of the definitions of TclOO.
 */

#include "tclOOScript.h"

/*
222
223
224
225
226
227
228
229
230


231



232
233
234
235
236
237
238
239
240
241
242
243
244

245


246


247
248
249
250
251
252
























































253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270





271



272
273
274
275
276
277
278
    }
    list[idx] = NULL;
}

/*
 * ----------------------------------------------------------------------
 *
 * TclOOInit --
 *


 *	Called to initialise the OO system within an interpreter.



 *
 * Result:
 *	TCL_OK if the setup succeeded. Currently assumed to always work.
 *
 * Side effects:
 *	Creates namespaces, commands, several classes and a number of
 *	callbacks. Upon return, the OO system is ready for use.
 *
 * ----------------------------------------------------------------------
 */

int
TclOOInit(

    Tcl_Interp *interp)		/* The interpreter to install into. */


{


    /*
     * Build the core of the OO system.
     */

    if (InitFoundation(interp) != TCL_OK) {
	return TCL_ERROR;
























































    }

    /*
     * Run our initialization script and, if that works, declare the package
     * to be fully provided.
     */

    if (Tcl_EvalEx(interp, initScript, TCL_INDEX_NONE, 0) != TCL_OK) {
	return TCL_ERROR;
    }

#ifndef TCL_NO_DEPRECATED
    Tcl_PkgProvideEx(interp, "TclOO", TCLOO_PATCHLEVEL,
	    &tclOOStubs);
#endif
    return Tcl_PkgProvideEx(interp, "tcl::oo", TCLOO_PATCHLEVEL,
	    &tclOOStubs);
}









/*
 * ----------------------------------------------------------------------
 *
 * TclOOGetFoundation --
 *
 *	Get a reference to the OO core class system.
 *







|

>
>
|
>
>
>


|







<
|
|
>
|
>
>

>
>
|
|
|

|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>



|
|

|
|
<
<





|

|
>
>
>
>
>
|
>
>
>







208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232

233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311


312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
    }
    list[idx] = NULL;
}

/*
 * ----------------------------------------------------------------------
 *
 * TclOOInitModuleObjCmd --
 *
 *	This is stub command that is mapped to the public commands of
 *	oo::class, oo::define, oo::objdefine and oo::object. When called
 *	it will initialize the OO system which will define the real tcl::oo
 *	commands and then call the command that was invoked. Will be called
 *	only once per interpreter since any call will define all of the
 *	real tcl::oo commands, overwriting the stubs.
 *
 * Result:
 *	TCL_OK if the setup succeeded.
 *
 * Side effects:
 *	Creates namespaces, commands, several classes and a number of
 *	callbacks. Upon return, the OO system is ready for use.
 *
 * ----------------------------------------------------------------------
 */

static int
TclOOInitModuleObjCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    Interp *iPtr = (Interp *)interp;
    if (iPtr->objectFoundation == NULL) {
	/*
	 * Build the core of the OO system.
	 */

	if (InitFoundation(interp) != TCL_OK) {
	    return TCL_ERROR;
	}

    }
    return Tcl_EvalObjv(interp, objc, objv, 0);
}

/*
 * ----------------------------------------------------------------------
 *
 * TclOOInit --
 *
 *	Called to initialise the OO system within an interpreter. Does
 *	not do the actual initialization but rather sets up stub commands
 *	that will do the initialization when called.
 *
 * Result:
 *	TCL_OK if the setup succeeded.
 *
 * Side effects:
 *	Creates stub commands for the public oo commands like oo::class etc.,
 *	subcommands for the info command and version variables. Also registers
 *	the tcl::oo package.
 *
 * ----------------------------------------------------------------------
 */
int
TclOOInit(
    Tcl_Interp *interp)		/* The interpreter to install into. */
{
    Tcl_CreateObjCommand(interp, "::oo::class",
	    TclOOInitModuleObjCmd, INT2PTR(0), NULL);
    Tcl_CreateObjCommand(interp, "::oo::define",
	    TclOOInitModuleObjCmd, INT2PTR(0), NULL);
    Tcl_CreateObjCommand(interp, "::oo::objdefine",
	    TclOOInitModuleObjCmd, INT2PTR(0), NULL);
    Tcl_CreateObjCommand(interp, "::oo::object",
	    TclOOInitModuleObjCmd, INT2PTR(0), NULL);


    Tcl_Command infoCmd;
    Tcl_Obj *mapDict;

    /*
     * Install into the [info] ensemble.
     */

    infoCmd = Tcl_FindCommand(interp, "info", NULL, TCL_GLOBAL_ONLY);
    if (infoCmd) {
	Tcl_CreateObjCommand(interp, "::oo::InfoObject",
	    TclOOInitModuleObjCmd, INT2PTR(0), NULL);
	Tcl_CreateObjCommand(interp, "::oo::InfoClass",
	    TclOOInitModuleObjCmd, INT2PTR(0), NULL);
	Tcl_GetEnsembleMappingDict(NULL, infoCmd, &mapDict);
	TclDictPutString(NULL, mapDict, "object", "::oo::InfoObject");
	TclDictPutString(NULL, mapDict, "class", "::oo::InfoClass");
	Tcl_SetEnsembleMappingDict(interp, infoCmd, mapDict);
    }

    /*
     * Set up the version and patchlevel variables. This used to be done by
     * the init script which is no longer used.
     */
    Tcl_SetVar2(interp, "::oo::patchlevel", NULL, TCLOO_PATCHLEVEL, 0);
    Tcl_SetVar2(interp, "::oo::version", NULL, TCLOO_VERSION, 0);



#ifndef TCL_NO_DEPRECATED
    Tcl_PkgProvideEx(interp, "TclOO", TCLOO_PATCHLEVEL,
	    &tclOOStubs);
#endif
    Tcl_PkgProvideEx(interp, "tcl::oo", TCLOO_PATCHLEVEL,
	    &tclOOStubs);

    if (Tcl_EvalEx(interp,
	"package ifneeded tcl::oo " TCLOO_PATCHLEVEL " {};"
	"package ifneeded TclOO " TCLOO_PATCHLEVEL " {};",
	TCL_INDEX_NONE, 0) != TCL_OK) {
	return TCL_ERROR;
    }
    return TCL_OK;
}

/*
 * ----------------------------------------------------------------------
 *
 * TclOOGetFoundation --
 *
 *	Get a reference to the OO core class system.
 *
329
330
331
332
333
334
335




336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353

354
355
356
357
358
359
360
 * ----------------------------------------------------------------------
 */

static int
InitFoundation(
    Tcl_Interp *interp)
{




    static Tcl_ThreadDataKey tsdKey;
    ThreadLocalData *tsdPtr = (ThreadLocalData *)
	    Tcl_GetThreadData(&tsdKey, sizeof(ThreadLocalData));
    Foundation *fPtr = (Foundation *) Tcl_Alloc(sizeof(Foundation));
    Tcl_Namespace *define, *objdef;
    Tcl_Obj *namePtr;
    size_t i;

    /*
     * Initialize the structure that holds the OO system core. This is
     * attached to the interpreter via an assocData entry; not very efficient,
     * but the best we can do without hacking the core more.
     */

    memset(fPtr, 0, sizeof(Foundation));
    ((Interp *) interp)->objectFoundation = fPtr;
    fPtr->interp = interp;
    fPtr->ooNs = Tcl_CreateNamespace(interp, "::oo", fPtr, NULL);

    Tcl_Export(interp, fPtr->ooNs, "[a-z]*", 1);
    define = Tcl_CreateNamespace(interp, "::oo::define", fPtr, NULL);
    objdef = Tcl_CreateNamespace(interp, "::oo::objdefine", fPtr, NULL);
    fPtr->helpersNs = Tcl_CreateNamespace(interp, "::oo::Helpers", fPtr,
	    DeletedHelpersNamespace);
    Tcl_CreateNamespace(interp, "::oo::configuresupport", NULL, NULL);
    fPtr->epoch = 1;







>
>
>
>

















|
>







386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
 * ----------------------------------------------------------------------
 */

static int
InitFoundation(
    Tcl_Interp *interp)
{
    if (((Interp *) interp)->objectFoundation) {
	return TCL_OK;
    }

    static Tcl_ThreadDataKey tsdKey;
    ThreadLocalData *tsdPtr = (ThreadLocalData *)
	    Tcl_GetThreadData(&tsdKey, sizeof(ThreadLocalData));
    Foundation *fPtr = (Foundation *) Tcl_Alloc(sizeof(Foundation));
    Tcl_Namespace *define, *objdef;
    Tcl_Obj *namePtr;
    size_t i;

    /*
     * Initialize the structure that holds the OO system core. This is
     * attached to the interpreter via an assocData entry; not very efficient,
     * but the best we can do without hacking the core more.
     */

    memset(fPtr, 0, sizeof(Foundation));
    ((Interp *) interp)->objectFoundation = fPtr;
    fPtr->interp = interp;
    fPtr->ooNs = Tcl_FindNamespace(interp, "::oo", NULL, 0);
    assert(fPtr->ooNs != NULL);
    Tcl_Export(interp, fPtr->ooNs, "[a-z]*", 1);
    define = Tcl_CreateNamespace(interp, "::oo::define", fPtr, NULL);
    objdef = Tcl_CreateNamespace(interp, "::oo::objdefine", fPtr, NULL);
    fPtr->helpersNs = Tcl_CreateNamespace(interp, "::oo::Helpers", fPtr,
	    DeletedHelpersNamespace);
    Tcl_CreateNamespace(interp, "::oo::configuresupport", NULL, NULL);
    fPtr->epoch = 1;
Changes to library/tclIndex.