Skip to content

Commit 8918a89

Browse files
Support labelled statements.
Related issue: #52 JerryScript-DCO-1.0-Signed-off-by: Ruben Ayrapetyan [email protected]
1 parent ac87616 commit 8918a89

11 files changed

+917
-293
lines changed

jerry-core/parser/js/jsp-label.cpp

Lines changed: 295 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,295 @@
1+
/* Copyright 2015 Samsung Electronics Co., Ltd.
2+
*
3+
* Licensed under the Apache License, Version 2.0 (the "License");
4+
* you may not use this file except in compliance with the License.
5+
* You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software
10+
* distributed under the License is distributed on an "AS IS" BASIS
11+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
* See the License for the specific language governing permissions and
13+
* limitations under the License.
14+
*/
15+
16+
#include "jsp-label.h"
17+
#include "lexer.h"
18+
#include "opcodes-dumper.h"
19+
20+
/** \addtogroup jsparser ECMAScript parser
21+
* @{
22+
*
23+
* \addtogroup labels Jump labels
24+
* @{
25+
*/
26+
27+
/**
28+
* Stack, containing current label set
29+
*/
30+
jsp_label_t *label_set_p = NULL;
31+
32+
/**
33+
* Initialize jumps labels mechanism
34+
*/
35+
void
36+
jsp_label_init (void)
37+
{
38+
JERRY_ASSERT (label_set_p == NULL);
39+
} /* jsp_label_init */
40+
41+
/**
42+
* Finalize jumps labels mechanism
43+
*/
44+
void
45+
jsp_label_finalize (void)
46+
{
47+
JERRY_ASSERT (label_set_p == NULL);
48+
} /* jsp_label_finalize */
49+
50+
/**
51+
* Add label to the current label set
52+
*/
53+
void
54+
jsp_label_push (jsp_label_t *out_label_p, /**< out: place where label structure
55+
* should be initialized and
56+
* linked into label set stack */
57+
jsp_label_type_flag_t type_mask, /**< label's type mask */
58+
token id) /**< identifier of the label (TOK_NAME)
59+
* if mask includes JSP_LABEL_TYPE_NAMED,
60+
* or empty token - otherwise */
61+
{
62+
JERRY_ASSERT (out_label_p != NULL);
63+
64+
if (type_mask & JSP_LABEL_TYPE_NAMED)
65+
{
66+
JERRY_ASSERT (id.type == TOK_NAME);
67+
68+
JERRY_ASSERT (jsp_label_find (JSP_LABEL_TYPE_NAMED, id, NULL) == NULL);
69+
}
70+
else
71+
{
72+
JERRY_ASSERT (id.type == TOK_EMPTY);
73+
}
74+
75+
out_label_p->type_mask = type_mask;
76+
out_label_p->id = id;
77+
out_label_p->continue_tgt_oc = MAX_OPCODES;
78+
out_label_p->breaks_list_oc = MAX_OPCODES;
79+
out_label_p->breaks_number = 0;
80+
out_label_p->continues_list_oc = MAX_OPCODES;
81+
out_label_p->continues_number = 0;
82+
out_label_p->next_label_p = label_set_p;
83+
out_label_p->is_nested_jumpable_border = false;
84+
85+
label_set_p = out_label_p;
86+
} /* jsp_label_push */
87+
88+
/**
89+
* Rewrite jumps to the label, if there any,
90+
* and remove it from the current label set
91+
*
92+
* @return the label should be on top of label set stack
93+
*/
94+
void
95+
jsp_label_rewrite_jumps_and_pop (jsp_label_t *label_p, /**< label to remove (should be on top of stack) */
96+
opcode_counter_t break_tgt_oc) /**< target opcode counter
97+
* for breaks on the label */
98+
{
99+
JERRY_ASSERT (label_p != NULL);
100+
JERRY_ASSERT (break_tgt_oc != MAX_OPCODES);
101+
JERRY_ASSERT (label_set_p == label_p);
102+
103+
/* Iterating jumps list, rewriting them */
104+
while (label_p->breaks_number--)
105+
{
106+
JERRY_ASSERT (label_p->breaks_list_oc != MAX_OPCODES);
107+
108+
label_p->breaks_list_oc = rewrite_simple_or_nested_jump_and_get_next (label_p->breaks_list_oc,
109+
break_tgt_oc);
110+
}
111+
while (label_p->continues_number--)
112+
{
113+
JERRY_ASSERT (label_p->continue_tgt_oc != MAX_OPCODES);
114+
JERRY_ASSERT (label_p->continues_list_oc != MAX_OPCODES);
115+
116+
label_p->continues_list_oc = rewrite_simple_or_nested_jump_and_get_next (label_p->continues_list_oc,
117+
label_p->continue_tgt_oc);
118+
}
119+
120+
label_set_p = label_set_p->next_label_p;
121+
} /* jsp_label_rewrite_jumps_and_pop */
122+
123+
/**
124+
* Find label with specified identifier
125+
*
126+
* @return if found, pointer to label descriptor,
127+
* otherwise - NULL.
128+
*/
129+
jsp_label_t*
130+
jsp_label_find (jsp_label_type_flag_t type_mask, /**< types to search for */
131+
token id, /**< identifier of the label (TOK_NAME)
132+
* if mask equals to JSP_LABEL_TYPE_NAMED,
133+
* or empty token - otherwise
134+
* (if so, mask should not include JSP_LABEL_TYPE_NAMED) */
135+
bool *out_is_simply_jumpable_p) /**< out: is the label currently
136+
* accessible with a simple jump */
137+
{
138+
bool is_search_named = (type_mask == JSP_LABEL_TYPE_NAMED);
139+
140+
if (is_search_named)
141+
{
142+
JERRY_ASSERT (id.type == TOK_NAME);
143+
}
144+
else
145+
{
146+
JERRY_ASSERT (!(type_mask & JSP_LABEL_TYPE_NAMED));
147+
JERRY_ASSERT (id.type == TOK_EMPTY);
148+
}
149+
150+
bool is_simply_jumpable = true;
151+
jsp_label_t *ret_label_p = NULL;
152+
153+
for (jsp_label_t* label_iter_p = label_set_p;
154+
label_iter_p != NULL;
155+
label_iter_p = label_iter_p->next_label_p)
156+
{
157+
if (label_iter_p->is_nested_jumpable_border)
158+
{
159+
is_simply_jumpable = false;
160+
}
161+
162+
bool is_named_label = (label_iter_p->type_mask & JSP_LABEL_TYPE_NAMED);
163+
if ((is_search_named
164+
&& is_named_label
165+
&& lexer_are_tokens_with_same_identifier (label_iter_p->id, id))
166+
|| (!is_search_named
167+
&& (type_mask & label_iter_p->type_mask)))
168+
{
169+
ret_label_p = label_iter_p;
170+
171+
break;
172+
}
173+
}
174+
175+
if (out_is_simply_jumpable_p != NULL)
176+
{
177+
*out_is_simply_jumpable_p = is_simply_jumpable;
178+
}
179+
180+
return ret_label_p;
181+
} /* jsp_label_find */
182+
183+
/**
184+
* Dump jump and register it in the specified label to be rewritten later (see also: jsp_label_rewrite_jumps_and_pop)
185+
*
186+
* Warning:
187+
* The dumped instruction should not be modified before it is rewritten, as its idx fields are used
188+
* to link jump instructions related to the label into singly linked list.
189+
*/
190+
void
191+
jsp_label_add_jump (jsp_label_t *label_p, /**< label to register jump for */
192+
bool is_simply_jumpable, /**< is the label currently
193+
* accessible with a simple jump */
194+
bool is_break) /**< type of jump - 'break' (true) or 'continue' (false) */
195+
{
196+
JERRY_ASSERT (label_p != NULL);
197+
198+
if (is_break)
199+
{
200+
label_p->breaks_list_oc = dump_simple_or_nested_jump_for_rewrite (is_simply_jumpable,
201+
label_p->breaks_list_oc);
202+
label_p->breaks_number++;
203+
}
204+
else
205+
{
206+
label_p->continues_list_oc = dump_simple_or_nested_jump_for_rewrite (is_simply_jumpable,
207+
label_p->continues_list_oc);
208+
label_p->continues_number++;
209+
}
210+
} /* jsp_label_add_jump */
211+
212+
/**
213+
* Setup target for 'continue' jumps,
214+
* associated with the labels, from innermost
215+
* to the specified label.
216+
*/
217+
void
218+
jsp_label_setup_continue_target (jsp_label_t *outermost_label_p, /**< the outermost label to setup target for */
219+
opcode_counter_t tgt_oc) /**< target */
220+
{
221+
/* There are no labels that could not be targeted with 'break' jumps */
222+
JERRY_ASSERT (tgt_oc != MAX_OPCODES);
223+
JERRY_ASSERT (outermost_label_p != NULL);
224+
225+
for (jsp_label_t *label_iter_p = label_set_p;
226+
label_iter_p != outermost_label_p->next_label_p;
227+
label_iter_p = label_iter_p->next_label_p)
228+
{
229+
JERRY_ASSERT (label_iter_p != NULL);
230+
JERRY_ASSERT (label_iter_p->continue_tgt_oc == MAX_OPCODES);
231+
232+
label_iter_p->continue_tgt_oc = tgt_oc;
233+
}
234+
} /* jsp_label_setup_continue_target */
235+
236+
/**
237+
* Mark current label, if any, as nested jumpable border
238+
*/
239+
void
240+
jsp_label_raise_nested_jumpable_border (void)
241+
{
242+
if (label_set_p != NULL)
243+
{
244+
JERRY_ASSERT (!label_set_p->is_nested_jumpable_border);
245+
label_set_p->is_nested_jumpable_border = true;
246+
}
247+
} /* jsp_label_raise_nested_jumpable_border */
248+
249+
/**
250+
* Unmark current label, if any, as nested jumpable border
251+
*/
252+
void
253+
jsp_label_remove_nested_jumpable_border (void)
254+
{
255+
if (label_set_p != NULL)
256+
{
257+
JERRY_ASSERT (label_set_p->is_nested_jumpable_border);
258+
label_set_p->is_nested_jumpable_border = false;
259+
}
260+
} /* jsp_label_remove_nested_jumpable_border */
261+
262+
/**
263+
* Mask current label set to restore it later, and start new label set
264+
*
265+
* @return pointer to masked label set's list of labels
266+
*/
267+
jsp_label_t*
268+
jsp_label_mask_set (void)
269+
{
270+
jsp_label_t *ret_p = label_set_p;
271+
272+
label_set_p = NULL;
273+
274+
return ret_p;
275+
} /* jsp_label_mask_set */
276+
277+
/**
278+
* Restore previously masked label set
279+
*
280+
* Note:
281+
* current label set should be empty
282+
*/
283+
void
284+
jsp_label_restore_set (jsp_label_t *masked_label_set_list_p) /**< list of labels of
285+
* a masked label set */
286+
{
287+
JERRY_ASSERT (label_set_p == NULL);
288+
289+
label_set_p = masked_label_set_list_p;
290+
} /* jsp_label_restore_set */
291+
292+
/**
293+
* @}
294+
* @}
295+
*/

jerry-core/parser/js/jsp-label.h

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
/* Copyright 2015 Samsung Electronics Co., Ltd.
2+
*
3+
* Licensed under the Apache License, Version 2.0 (the "License");
4+
* you may not use this file except in compliance with the License.
5+
* You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software
10+
* distributed under the License is distributed on an "AS IS" BASIS
11+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
* See the License for the specific language governing permissions and
13+
* limitations under the License.
14+
*/
15+
16+
#ifndef JSP_LABEL_H
17+
#define JSP_LABEL_H
18+
19+
#include "lexer.h"
20+
#include "opcodes.h"
21+
22+
/** \addtogroup jsparser ECMAScript parser
23+
* @{
24+
*
25+
* \addtogroup labels Jump labels
26+
* @{
27+
*/
28+
29+
/**
30+
* Label types
31+
*/
32+
typedef enum
33+
{
34+
JSP_LABEL_TYPE_NAMED = (1 << 0), /**< label for breaks and continues with identifiers */
35+
JSP_LABEL_TYPE_UNNAMED_BREAKS = (1 << 1), /**< label for breaks without identifiers */
36+
JSP_LABEL_TYPE_UNNAMED_CONTINUES = (1 << 2) /**< label for continues without identifiers */
37+
} jsp_label_type_flag_t;
38+
39+
/**
40+
* Descriptor of a jump label (See also: ECMA-262 v5, 12.12, Labelled statements)
41+
*
42+
* Note:
43+
* Jump instructions with target identified by some specific label,
44+
* are linked into singly-linked list.
45+
*
46+
* Pointer to a next element of the list is represented with opcode counter.
47+
* stored in instructions linked into the list.
48+
*
49+
*/
50+
typedef struct jsp_label_t
51+
{
52+
jsp_label_type_flag_t type_mask; /**< label type mask */
53+
token id; /**< label name (TOK_NAME), if type is LABEL_NAMED */
54+
opcode_counter_t continue_tgt_oc; /**< target opcode counter for continues on the label */
55+
opcode_counter_t breaks_list_oc; /**< opcode counter of first 'break' instruction in the list
56+
* of instructions with the target identified by the label */
57+
opcode_counter_t breaks_number; /**< number of 'break' instructions in the list */
58+
opcode_counter_t continues_list_oc; /**< opcode counter of first 'continue' instruction in the list
59+
* of instructions with the target identified by the label */
60+
opcode_counter_t continues_number; /**< number of 'continue' instructions in the list */
61+
jsp_label_t *next_label_p; /**< next label in current label set stack */
62+
bool is_nested_jumpable_border : 1; /**< flag, indicating that this and outer labels
63+
* are not currently accessible with simple jumps,
64+
* and so should be targetted with nested jumps only */
65+
} jsp_label_t;
66+
67+
extern void jsp_label_init (void);
68+
extern void jsp_label_finalize (void);
69+
70+
extern void jsp_label_push (jsp_label_t *out_label_p, jsp_label_type_flag_t type_mask, token id);
71+
extern void jsp_label_rewrite_jumps_and_pop (jsp_label_t *label_p, opcode_counter_t break_tgt_oc);
72+
73+
extern jsp_label_t* jsp_label_find (jsp_label_type_flag_t type_mask, token id, bool *out_is_simply_jumpable_p);
74+
75+
extern void jsp_label_add_jump (jsp_label_t *label_p, bool is_simply_jumpable, bool is_break);
76+
extern void jsp_label_setup_continue_target (jsp_label_t *outermost_label_p, opcode_counter_t tgt_oc);
77+
78+
extern void jsp_label_raise_nested_jumpable_border (void);
79+
extern void jsp_label_remove_nested_jumpable_border (void);
80+
81+
extern jsp_label_t* jsp_label_mask_set (void);
82+
extern void jsp_label_restore_set (jsp_label_t *masked_label_set_list_p);
83+
84+
/**
85+
* @}
86+
* @}
87+
*/
88+
89+
#endif /* !JSP_LABEL_H */

0 commit comments

Comments
 (0)