Prefix the JNI types from SquirrelJME with sjme_ so that they can easily be mixed...
[SquirrelJME.git] / nanocoat / tests / src / elevator.c
blob8da8b24a4834b9a2e927b4e5c580f7934494b440
1 /* -*- Mode: C; indent-tabs-mode: t; tab-width: 4 -*-
2 // ---------------------------------------------------------------------------
3 // SquirrelJME
4 // Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
5 // ---------------------------------------------------------------------------
6 // SquirrelJME is under the Mozilla Public License Version 2.0.
7 // See license.mkd for licensing and copyright information.
8 // -------------------------------------------------------------------------*/
10 #include <string.h>
12 #include "sjme/except.h"
13 #include "elevator.h"
15 struct sjme_elevatorRunData
17 /** The index type counts. */
18 sjme_jint indexTypeCount[SJME_NUM_ELEVATOR_DO_TYPES];
20 /** The current run. */
21 sjme_elevatorRunCurrent current;
23 /** The next thread ID. */
24 sjme_jint nextThreadId;
27 /**
28 * Elevator function to do type.
30 * @since 2023/11/11
32 struct
34 sjme_elevatorDoFunc func;
35 sjme_elevatorDoType type;
36 } sjme_elevatorFuncToType[SJME_NUM_ELEVATOR_DO_TYPES] =
38 {sjme_elevatorDoInit,
39 SJME_ELEVATOR_DO_TYPE_INIT},
40 {sjme_elevatorDoMakeThread,
41 SJME_ELEVATOR_DO_TYPE_MAKE_THREAD},
42 {sjme_elevatorDoMakeObject,
43 SJME_ELEVATOR_DO_TYPE_MAKE_OBJECT},
44 {sjme_elevatorDoMakeFrame,
45 SJME_ELEVATOR_DO_TYPE_MAKE_FRAME},
47 /* End. */
48 {NULL, SJME_ELEVATOR_DO_TYPE_UNKNOWN}
51 sjme_jboolean sjme_elevatorAct(
52 sjme_attrInNotNull sjme_elevatorState* inState,
53 sjme_attrInNotNull const sjme_elevatorSet* inSet,
54 sjme_attrInValue sjme_jint special)
56 sjme_jint dx, i;
57 sjme_elevatorRunData data;
58 sjme_elevatorDoType doType;
60 /* Check. */
61 if (inState == NULL || inSet == NULL)
62 return sjme_die("Null arguments.");
64 /* Confirm that the set is valid. */
65 if (inSet->config == NULL)
66 return sjme_die("Invalid configuration.");
68 /* Allocate main memory pool. */
69 if (!sjme_alloc_poolMalloc(&inState->allocPool, 1024 * 1024))
70 return sjme_die("Could not allocate main memory pool.");
72 /* Initialize base data. */
73 memset(&data, 0, sizeof(data));
75 /* Go through each entry, stop at NULl. */
76 for (dx = 0; inSet->order[dx] != NULL; dx++)
78 /* Always wipe the current data so it is fresh. */
79 memset(&data.current, 0, sizeof(data.current));
81 /* This index is just a straight through. */
82 data.current.indexAll = dx;
84 /* Find the type for this function. */
85 doType = SJME_ELEVATOR_DO_TYPE_UNKNOWN;
86 for (i = 0; i < SJME_NUM_ELEVATOR_DO_TYPES; i++)
87 if (inSet->order[dx] == sjme_elevatorFuncToType[i].func)
89 doType = sjme_elevatorFuncToType[i].type;
90 break;
93 /* Not found? */
94 if (doType == SJME_ELEVATOR_DO_TYPE_UNKNOWN)
95 return sjme_die("Could not find the type for do function.");
97 /* Increment up the index for this. */
98 data.current.type = doType;
99 data.current.indexType = data.indexTypeCount[doType]++;
100 data.current.special = special;
102 /* Run configuration function to initialize the data set. */
103 if (!inSet->config(inState, &data.current))
104 return sjme_die("Configuration step failed at %d.", dx);
106 /* Call do function to perform whatever test initialization. */
107 if (!inSet->order[dx](inState, &data))
108 return sjme_die("Do failed at %d.", dx);
111 /* Successful. */
112 return SJME_JNI_TRUE;
115 void* sjme_elevatorAlloc(
116 sjme_attrInNotNull sjme_elevatorState* inState,
117 sjme_attrInPositiveNonZero size_t inLen)
119 void* rv;
121 /* Check. */
122 if (inState == NULL)
123 return sjme_dieP("No input state.");
125 rv = NULL;
126 if (!sjme_alloc(inState->allocPool, inLen, &rv))
127 return sjme_dieP("Could not allocate pointer in test pool.");
129 return rv;
132 sjme_jboolean sjme_elevatorDoInit(
133 sjme_attrInNotNull sjme_elevatorState* inState,
134 sjme_attrInNotNull sjme_elevatorRunData* inData)
136 sjme_nvm_state* newState;
138 if (inState == NULL || inData == NULL)
139 return sjme_die("Null arguments.");
141 /* Allocate virtual machine state. */
142 newState = sjme_elevatorAlloc(inState,
143 sizeof(*inState->nvmState));
144 inState->nvmState = newState;
146 /* Store test state, as required for some tests. */
147 newState->special = inState;
149 /* Register any hooks? */
150 if (inData->current.data.state.hooks != NULL)
151 newState->hooks = inData->current.data.state.hooks;
153 /* Done. */
154 return SJME_JNI_TRUE;
157 sjme_jboolean sjme_elevatorDoMakeFrame(
158 sjme_attrInNotNull sjme_elevatorState* inState,
159 sjme_attrInNotNull sjme_elevatorRunData* inData)
161 sjme_jint threadIndex, treadMax, tallyLocals, stackBase, desireMaxLocals;
162 sjme_jint tallyStack, desireMaxStack, localIndex;
163 sjme_nvm_thread* thread;
164 sjme_nvm_frame* newFrame;
165 sjme_basicTypeId typeId;
166 sjme_nvm_frameTread* tread;
167 sjme_nvm_frameStack* stack;
168 sjme_nvm_frameLocalMap* localMap;
169 sjme_jbyte baseLocalAt[SJME_NUM_JAVA_TYPE_IDS];
171 if (inState == NULL || inData == NULL)
172 return sjme_die("Null arguments.");
174 /* Make sure the requested thread index is valid. */
175 threadIndex = inData->current.data.frame.threadIndex;
176 if (threadIndex < 0 || threadIndex >= SJME_ELEVATOR_MAX_THREADS ||
177 inState->threads[threadIndex].nvmThread == NULL)
178 return sjme_die("Invalid thread index %d.", threadIndex);
180 /* Get the actual thread. */
181 thread = inState->threads[threadIndex].nvmThread;
183 /* Allocate new frame. */
184 newFrame = sjme_elevatorAlloc(inState, sizeof(*newFrame));
185 if (newFrame == NULL)
186 return sjme_die("Could not allocate frame.");
188 /* Correlate the frame index to the thread. */
189 newFrame->frameIndex = thread->numFrames;
190 thread->numFrames++;
192 /* Link in frame to the thread. */
193 newFrame->inThread = thread;
194 newFrame->parent = thread->top;
195 thread->top = newFrame;
197 /* Track tally of locals and stack for consistency. */
198 tallyLocals = 0;
199 tallyStack = 0;
201 /* Setup locals mapping. */
202 desireMaxLocals = inData->current.data.frame.maxLocals;
203 localMap = sjme_elevatorAlloc(inState,
204 SJME_SIZEOF_FRAME_LOCAL_MAP(desireMaxLocals));
205 localMap->max = desireMaxLocals;
207 /* Setup stack information. */
208 desireMaxStack = inData->current.data.frame.maxStack;
209 stack = sjme_elevatorAlloc(inState,
210 SJME_SIZEOF_FRAME_STACK(desireMaxStack));
211 newFrame->stack = stack;
212 stack->limit = desireMaxStack;
214 /* Remember to set the local mapping in the frame. */
215 newFrame->localMap = localMap;
217 /* Clear base local map set trackers. */
218 memset(baseLocalAt, 0, sizeof(baseLocalAt));
220 /* Need to initialize frame locals and stack? */
221 for (typeId = 0; typeId < SJME_NUM_JAVA_TYPE_IDS; typeId++)
223 /* Ignore if empty. */
224 treadMax = inData->current.data.frame.treads[typeId].max;
225 if (treadMax <= 0)
226 continue;
228 /* Allocate target tread. */
229 tread = sjme_elevatorAlloc(inState,
230 SJME_SIZEOF_FRAME_TREAD_VAR(typeId, treadMax));
231 newFrame->treads[typeId] = tread;
233 /* Setup stack base. */
234 stackBase = inData->current.data.frame.treads[typeId].stackBaseIndex;
235 if (stackBase < 0 || stackBase > treadMax)
236 return sjme_die("Invalid test stack base %d, outside range %d.",
237 stackBase, treadMax);
239 /* Local tally goes up by the stack base. */
240 tallyLocals += stackBase;
242 /* Tally number of stack items. */
243 tallyStack += treadMax - stackBase;
245 /* Setup other tread details. */
246 tread->stackBaseIndex = stackBase;
247 tread->count = stackBase;
248 tread->max = treadMax;
250 /* Fill in local mappings for a given tread. */
251 for (localIndex = 0; localIndex < stackBase; localIndex++)
252 localMap->maps[localIndex].to[typeId] = (sjme_jbyte)localIndex;
254 #if 0
255 /* Store the type onto the stack. */
256 stack->order[stack->count] = typeId;
257 stack->count++;
258 #endif
261 /* Consistency check. */
262 if (tallyLocals != desireMaxLocals)
263 return sjme_die("Calculated and desired locals invalid: %d != %d.",
264 tallyLocals, desireMaxLocals);
266 if (tallyStack != desireMaxStack)
267 return sjme_die("Calculated and desired stack invalid: %d != %d.",
268 tallyStack, desireMaxStack);
270 /* Done. */
271 return SJME_JNI_TRUE;
274 sjme_jboolean sjme_elevatorDoMakeObject(
275 sjme_attrInNotNull sjme_elevatorState* inState,
276 sjme_attrInNotNull sjme_elevatorRunData* inData)
278 sjme_jobject newObject;
280 if (inState == NULL || inData == NULL)
281 return sjme_die("Null arguments.");
283 /* Too many objects? */
284 if (inState->numObjects >= SJME_ELEVATOR_MAX_OBJECTS)
285 sjme_die("Too many elevator objects.");
287 /* Allocate new object. */
288 newObject = sjme_elevatorAlloc(inState, sizeof(*newObject));
289 inState->objects[inState->numObjects++] = newObject;
291 /* Initialize object details. */
292 newObject->refCount = 1;
294 /* Success. */
295 return SJME_JNI_TRUE;
298 sjme_jboolean sjme_elevatorDoMakeThread(
299 sjme_attrInNotNull sjme_elevatorState* inState,
300 sjme_attrInNotNull sjme_elevatorRunData* inData)
302 sjme_jint threadIndex;
303 sjme_nvm_thread* newThread;
305 if (inState == NULL || inData == NULL)
306 return sjme_die("Null arguments.");
308 /* Elevator has a limited set of threads for testing purposes. */
309 threadIndex = inState->numThreads;
310 if (threadIndex >= SJME_ELEVATOR_MAX_THREADS)
311 return sjme_die("Too make elevator threads.");
313 /* Allocate thread. */
314 newThread = sjme_elevatorAlloc(inState, sizeof(*newThread));
315 if (newThread == NULL)
316 return sjme_die("Could not allocate thread.");
318 /* Store in thread and bump up. */
319 newThread->threadId = ++inData->nextThreadId;
320 newThread->inState = inState->nvmState;
321 inState->threads[threadIndex].nvmThread = newThread;
323 /* Done. */
324 return SJME_JNI_TRUE;