1 /* -*- Mode: C; indent-tabs-mode: t; tab-width: 4 -*-
2 // ---------------------------------------------------------------------------
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 // -------------------------------------------------------------------------*/
12 #include "sjme/except.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
;
28 * Elevator function to do type.
34 sjme_elevatorDoFunc func
;
35 sjme_elevatorDoType type
;
36 } sjme_elevatorFuncToType
[SJME_NUM_ELEVATOR_DO_TYPES
] =
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
},
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
)
57 sjme_elevatorRunData data
;
58 sjme_elevatorDoType doType
;
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
;
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
);
112 return SJME_JNI_TRUE
;
115 void* sjme_elevatorAlloc(
116 sjme_attrInNotNull sjme_elevatorState
* inState
,
117 sjme_attrInPositiveNonZero
size_t inLen
)
123 return sjme_dieP("No input state.");
126 if (!sjme_alloc(inState
->allocPool
, inLen
, &rv
))
127 return sjme_dieP("Could not allocate pointer in test pool.");
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
;
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
;
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. */
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
;
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
;
255 /* Store the type onto the stack. */
256 stack
->order
[stack
->count
] = typeId
;
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
);
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;
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
;
324 return SJME_JNI_TRUE
;