RexxLocalVariables.cpp
Go to the documentation of this file.
1 /*----------------------------------------------------------------------------*/
2 /* */
3 /* Copyright (c) 1995, 2004 IBM Corporation. All rights reserved. */
4 /* Copyright (c) 2005-2009 Rexx Language Association. All rights reserved. */
5 /* */
6 /* This program and the accompanying materials are made available under */
7 /* the terms of the Common Public License v1.0 which accompanies this */
8 /* distribution. A copy is also available at the following address: */
9 /* http://www.oorexx.org/license.html */
10 /* */
11 /* Redistribution and use in source and binary forms, with or */
12 /* without modification, are permitted provided that the following */
13 /* conditions are met: */
14 /* */
15 /* Redistributions of source code must retain the above copyright */
16 /* notice, this list of conditions and the following disclaimer. */
17 /* Redistributions in binary form must reproduce the above copyright */
18 /* notice, this list of conditions and the following disclaimer in */
19 /* the documentation and/or other materials provided with the distribution. */
20 /* */
21 /* Neither the name of Rexx Language Association nor the names */
22 /* of its contributors may be used to endorse or promote products */
23 /* derived from this software without specific prior written permission. */
24 /* */
25 /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */
26 /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */
27 /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS */
28 /* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */
29 /* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */
30 /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */
31 /* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, */
32 /* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY */
33 /* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */
34 /* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */
35 /* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
36 /* */
37 /*----------------------------------------------------------------------------*/
38 /******************************************************************************/
39 /* REXX Kernel RexxLocalVariables.cpp */
40 /* */
41 /* Primitive Local Variable Cache */
42 /* */
43 /******************************************************************************/
44 #include <stdlib.h>
45 #include "RexxCore.h"
46 #include "StringClass.hpp"
47 #include "RexxLocalVariables.hpp"
48 #include "RexxActivation.hpp"
49 
50 void RexxLocalVariables::live(size_t liveMark)
51 /******************************************************************************/
52 /* Function: Normal garbage collection live marking */
53 /******************************************************************************/
54 {
55  // We can only mark if full initialized
56  if (locals != NULL)
57  {
58  RexxVariable **entry; /* marked stack entry */
59  RexxVariable **top;
60 
61  /* loop through the stack entries */
62  for (entry = locals, top = entry + size; entry < top; entry++)
63  {
64  memory_mark(*entry); /* marking each one */
65  }
66  }
67  memory_mark(dictionary); /* also mark any created vdict */
68 }
69 
71 /******************************************************************************/
72 /* Function: Generalized object marking */
73 /******************************************************************************/
74 {
75  // We can only mark if full initialized
76  if (locals != NULL)
77  {
78  RexxVariable **entry; /* marked stack entry */
79  RexxVariable **top;
80 
81  /* loop through the stack entries */
82  for (entry = locals, top = entry + size; entry < top; entry++)
83  {
84  memory_mark_general(*entry); /* marking each one */
85  }
86  }
87  memory_mark_general(dictionary); /* also mark any created vdict */
88 }
89 
90 
92 /******************************************************************************/
93 /* Function: Migrate the expression stack to a new activity */
94 /******************************************************************************/
95 {
96  RexxVariable **oldFrame = locals;
97  /* allocate a new frame */
98  activity->allocateLocalVariableFrame(this);
99  /* copy the enties over to the new stack. */
100  memcpy(locals, oldFrame, sizeof(RexxVariable *) * size);
101 }
102 
103 
105 /******************************************************************************/
106 /* Function: Do a more extensive search for a variable, without creating */
107 /* one if it doesn't exist. */
108 /******************************************************************************/
109 {
110  RexxVariable *variable = OREF_NULL;
111 
112  /* if we have a dictionary already, we can do a fast lookup. */
113  if (dictionary != OREF_NULL)
114  {
115  variable = dictionary->resolveVariable(name);
116  /* if we have an index, fill in the cache entry. */
117  if (index != 0)
118  {
119  /* add this to the variable cache */
120  locals[index] = variable;
121  }
122  }
123  else
124  {
125  /* if this is a non-targetted lookup, we don't know the slot */
126  /* this variable needs to be stored in, or this is a */
127  /* dynamically accessed variable that may not have a slot. We */
128  /* might need to create a variable dictionary for this. */
129  if (index == 0)
130  {
131  /* if we haven't created a variable dictionary yet, scan */
132  /* the set of variables looking for one we may have created */
133  /* earlier. */
134  size_t i;
135  for (i = 0; i < size; i++)
136  {
137  /* grab the item */
138  variable = locals[i];
139  /* if the variable at this position exists, check the name. */
140  if (variable != OREF_NULL)
141  {
142  /* if the names match, this is our target */
143  if (name->memCompare(variable->getName()))
144  {
145  return variable;
146  }
147  }
148  }
149  }
150  variable = NULL; // force this to null, otherwise it returns last variable examined
151  }
152  return variable;
153 }
154 
156 /******************************************************************************/
157 /* Function: Create a local variable object of the given name and store */
158 /* it at the given location. */
159 /******************************************************************************/
160 {
161  RexxVariable *variable = OREF_NULL;
162 
163  /* if this is a non-targetted lookup, we don't know the slot */
164  /* this variable needs to be stored in, or this is a */
165  /* dynamically accessed variable that may not have a slot. We */
166  /* might need to create a variable dictionary for this. */
167  if (index == 0)
168  {
169  /* if we haven't created a variable dictionary yet, scan */
170  /* the set of variables looking for one we may have created */
171  /* earlier. */
172  if (dictionary == OREF_NULL)
173  {
174  size_t i;
175  for (i = 0; i < size; i++)
176  {
177  /* grab the item */
178  variable = locals[i];
179  /* if the variable at this position exists, check the name. */
180  if (variable != OREF_NULL)
181  {
182  /* if the names match, this is our target */
183  if (name->memCompare(variable->getName()))
184  {
185  return variable;
186  }
187  }
188  }
189  /* go create the dictionary and populate it with our variable set. */
191  }
192 
193 
194  /* get the variable item for this name */
195  return dictionary->getVariable(name);
196  }
197  else
198  {
199  /* if we've had to create a dictionary for this because of */
200  /* prior dynamic access, then we need to retrieve the */
201  /* variable from the dictionary. */
202  if (dictionary != OREF_NULL)
203  {
204  variable = dictionary->getVariable(name);
205  }
206  else
207  {
208  /* create a new variable item for this */
209  variable = owner->newLocalVariable(name);
210  }
211  /* add this to the variable cache */
212  locals[index] = variable;
213  /* and return the new variable */
214  return variable;
215  }
216 }
217 
218 
220 /******************************************************************************/
221 /* Function: Create a local variable object of the given name and store */
222 /* it at the given location. */
223 /******************************************************************************/
224 {
225  RexxVariable *variable;
226 
227  /* if this is a non-targetted lookup, we don't know the slot */
228  /* this variable needs to be stored in, or this is a */
229  /* dynamically accessed variable that may not have a slot. We */
230  /* might need to create a variable dictionary for this. */
231  if (index == 0)
232  {
233  /* if we haven't created a variable dictionary yet, scan */
234  /* the set of variables looking for one we may have created */
235  /* earlier. */
236  if (dictionary == OREF_NULL)
237  {
238  size_t i;
239  for (i = 0; i < size; i++)
240  {
241  /* grab the item */
242  variable = locals[i];
243  /* if the variable at this position exists, check the name. */
244  if (variable != OREF_NULL)
245  {
246  /* if the names match, this is our target */
247  if (name->memCompare(variable->getName()))
248  {
249  return variable;
250  }
251  }
252  }
253 
254  /* go create the dictionary and populate it with our variable set. */
256  }
257 
258  /* get the variable item for this name */
259  return dictionary->getStemVariable(name);
260  }
261  else
262  {
263  /* if we've had to create a dictionary for this because of */
264  /* prior dynamic access, then we need to retrieve the */
265  /* variable from the dictionary. */
266  if (dictionary != OREF_NULL)
267  {
268  variable = dictionary->getStemVariable(name);
269  /* add this to the variable cache */
270  locals[index] = variable;
271  }
272  else
273  {
274  /* create a new variable item for this */
275  variable = owner->newLocalVariable(name);
276  /* add this to the variable cache */
277  locals[index] = variable;
278  /* create a stem object as value */
279  RexxStem *stemtable = new RexxStem(name);
280  /* the stem object is the value of */
281  /* stem variable */
282  variable->set((RexxObject *)stemtable);
283  }
284  /* and return the new variable */
285  return variable;
286  }
287 }
288 
290 /******************************************************************************/
291 /* Function: Do a more extensive search for a variable, without creating */
292 /* one if it doesn't exist. */
293 /******************************************************************************/
294 {
295  RexxVariable *oldVariable = OREF_NULL;
296  RexxString *name = variable->getName();
297 
298  /* if we haven't created a variable dictionary yet, scan */
299  /* the set of variables looking for one we may have created */
300  /* earlier. */
301  size_t i;
302  for (i = 0; i < size; i++)
303  {
304  /* grab the item */
305  oldVariable = locals[i];
306  /* if the variable at this position exists, check the name. */
307  if (oldVariable != OREF_NULL)
308  {
309  /* if the names match, this is our target */
310  if (name->memCompare(oldVariable->getName()))
311  {
312  /* overwrite this */
313  locals[i] = variable;
314 
315  /* if we have a dictionary, we update that entry too */
316  if (dictionary != OREF_NULL)
317  {
318  dictionary->put(variable, name);
319  return;
320  }
321  break;
322  }
323  }
324  }
325 
326  /* we didn't find a static one, so this is a completely dynamic */
327  /* update. Make sure we have a dynamic dictionary and insert */
328  /* this entry. */
329  if (dictionary == OREF_NULL)
330  {
332  }
333  /* add the variable to the dictionary */
334  dictionary->put(variable, name);
335 }
336 
338 /******************************************************************************/
339 /* Function: Create a variable dictionary for this method activation to */
340 /* support dynamic access to variables. This is created only */
341 /* when dynamic lookup cannot be avoided. */
342 /******************************************************************************/
343 {
344  /* create a dictionary with the recommended size */
346  for (size_t i = 0; i < size; i++)
347  {
348  /* grab the item */
349  RexxVariable *variable = locals[i];
350  /* if the variable at this position exists, check the name. */
351  if (variable != OREF_NULL)
352  {
353  /* add the variable to the dictionary */
354  dictionary->put(variable, variable->getName());
355  }
356  }
357 }
#define OREF_NULL
Definition: RexxCore.h:61
#define memory_mark(oref)
Definition: RexxMemory.hpp:450
#define memory_mark_general(oref)
Definition: RexxMemory.hpp:451
RexxVariableDictionary * new_variableDictionary(size_t s)
RexxVariable * newLocalVariable(RexxString *name)
void allocateLocalVariableFrame(RexxLocalVariables *locals)
RexxActivation * owner
void migrate(RexxActivity *)
void updateVariable(RexxVariable *)
RexxVariable * findVariable(RexxString *name, size_t index)
RexxVariable * lookupVariable(RexxString *name, size_t index)
void liveGeneral(int reason)
RexxVariableDictionary * dictionary
RexxVariable * lookupStemVariable(RexxString *name, size_t index)
bool memCompare(const char *s, size_t l)
RexxVariable * resolveVariable(RexxString *name)
RexxVariable * getVariable(RexxString *name)
RexxVariable * getStemVariable(RexxString *stemName)
void put(RexxVariable *, RexxString *)
void set(RexxObject *value)
RexxString * getName()