mirror of
https://github.com/jerryscript-project/jerryscript.git
synced 2025-12-15 16:29:21 +00:00
Related issue: #52 JerryScript-DCO-1.0-Signed-off-by: Ruben Ayrapetyan r.ayrapetyan@samsung.com
296 lines
8.6 KiB
C++
296 lines
8.6 KiB
C++
/* Copyright 2015 Samsung Electronics Co., Ltd.
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#include "jsp-label.h"
|
|
#include "lexer.h"
|
|
#include "opcodes-dumper.h"
|
|
|
|
/** \addtogroup jsparser ECMAScript parser
|
|
* @{
|
|
*
|
|
* \addtogroup labels Jump labels
|
|
* @{
|
|
*/
|
|
|
|
/**
|
|
* Stack, containing current label set
|
|
*/
|
|
jsp_label_t *label_set_p = NULL;
|
|
|
|
/**
|
|
* Initialize jumps labels mechanism
|
|
*/
|
|
void
|
|
jsp_label_init (void)
|
|
{
|
|
JERRY_ASSERT (label_set_p == NULL);
|
|
} /* jsp_label_init */
|
|
|
|
/**
|
|
* Finalize jumps labels mechanism
|
|
*/
|
|
void
|
|
jsp_label_finalize (void)
|
|
{
|
|
JERRY_ASSERT (label_set_p == NULL);
|
|
} /* jsp_label_finalize */
|
|
|
|
/**
|
|
* Add label to the current label set
|
|
*/
|
|
void
|
|
jsp_label_push (jsp_label_t *out_label_p, /**< out: place where label structure
|
|
* should be initialized and
|
|
* linked into label set stack */
|
|
jsp_label_type_flag_t type_mask, /**< label's type mask */
|
|
token id) /**< identifier of the label (TOK_NAME)
|
|
* if mask includes JSP_LABEL_TYPE_NAMED,
|
|
* or empty token - otherwise */
|
|
{
|
|
JERRY_ASSERT (out_label_p != NULL);
|
|
|
|
if (type_mask & JSP_LABEL_TYPE_NAMED)
|
|
{
|
|
JERRY_ASSERT (id.type == TOK_NAME);
|
|
|
|
JERRY_ASSERT (jsp_label_find (JSP_LABEL_TYPE_NAMED, id, NULL) == NULL);
|
|
}
|
|
else
|
|
{
|
|
JERRY_ASSERT (id.type == TOK_EMPTY);
|
|
}
|
|
|
|
out_label_p->type_mask = type_mask;
|
|
out_label_p->id = id;
|
|
out_label_p->continue_tgt_oc = MAX_OPCODES;
|
|
out_label_p->breaks_list_oc = MAX_OPCODES;
|
|
out_label_p->breaks_number = 0;
|
|
out_label_p->continues_list_oc = MAX_OPCODES;
|
|
out_label_p->continues_number = 0;
|
|
out_label_p->next_label_p = label_set_p;
|
|
out_label_p->is_nested_jumpable_border = false;
|
|
|
|
label_set_p = out_label_p;
|
|
} /* jsp_label_push */
|
|
|
|
/**
|
|
* Rewrite jumps to the label, if there any,
|
|
* and remove it from the current label set
|
|
*
|
|
* @return the label should be on top of label set stack
|
|
*/
|
|
void
|
|
jsp_label_rewrite_jumps_and_pop (jsp_label_t *label_p, /**< label to remove (should be on top of stack) */
|
|
opcode_counter_t break_tgt_oc) /**< target opcode counter
|
|
* for breaks on the label */
|
|
{
|
|
JERRY_ASSERT (label_p != NULL);
|
|
JERRY_ASSERT (break_tgt_oc != MAX_OPCODES);
|
|
JERRY_ASSERT (label_set_p == label_p);
|
|
|
|
/* Iterating jumps list, rewriting them */
|
|
while (label_p->breaks_number--)
|
|
{
|
|
JERRY_ASSERT (label_p->breaks_list_oc != MAX_OPCODES);
|
|
|
|
label_p->breaks_list_oc = rewrite_simple_or_nested_jump_and_get_next (label_p->breaks_list_oc,
|
|
break_tgt_oc);
|
|
}
|
|
while (label_p->continues_number--)
|
|
{
|
|
JERRY_ASSERT (label_p->continue_tgt_oc != MAX_OPCODES);
|
|
JERRY_ASSERT (label_p->continues_list_oc != MAX_OPCODES);
|
|
|
|
label_p->continues_list_oc = rewrite_simple_or_nested_jump_and_get_next (label_p->continues_list_oc,
|
|
label_p->continue_tgt_oc);
|
|
}
|
|
|
|
label_set_p = label_set_p->next_label_p;
|
|
} /* jsp_label_rewrite_jumps_and_pop */
|
|
|
|
/**
|
|
* Find label with specified identifier
|
|
*
|
|
* @return if found, pointer to label descriptor,
|
|
* otherwise - NULL.
|
|
*/
|
|
jsp_label_t*
|
|
jsp_label_find (jsp_label_type_flag_t type_mask, /**< types to search for */
|
|
token id, /**< identifier of the label (TOK_NAME)
|
|
* if mask equals to JSP_LABEL_TYPE_NAMED,
|
|
* or empty token - otherwise
|
|
* (if so, mask should not include JSP_LABEL_TYPE_NAMED) */
|
|
bool *out_is_simply_jumpable_p) /**< out: is the label currently
|
|
* accessible with a simple jump */
|
|
{
|
|
bool is_search_named = (type_mask == JSP_LABEL_TYPE_NAMED);
|
|
|
|
if (is_search_named)
|
|
{
|
|
JERRY_ASSERT (id.type == TOK_NAME);
|
|
}
|
|
else
|
|
{
|
|
JERRY_ASSERT (!(type_mask & JSP_LABEL_TYPE_NAMED));
|
|
JERRY_ASSERT (id.type == TOK_EMPTY);
|
|
}
|
|
|
|
bool is_simply_jumpable = true;
|
|
jsp_label_t *ret_label_p = NULL;
|
|
|
|
for (jsp_label_t *label_iter_p = label_set_p;
|
|
label_iter_p != NULL;
|
|
label_iter_p = label_iter_p->next_label_p)
|
|
{
|
|
if (label_iter_p->is_nested_jumpable_border)
|
|
{
|
|
is_simply_jumpable = false;
|
|
}
|
|
|
|
bool is_named_label = (label_iter_p->type_mask & JSP_LABEL_TYPE_NAMED);
|
|
if ((is_search_named
|
|
&& is_named_label
|
|
&& lexer_are_tokens_with_same_identifier (label_iter_p->id, id))
|
|
|| (!is_search_named
|
|
&& (type_mask & label_iter_p->type_mask)))
|
|
{
|
|
ret_label_p = label_iter_p;
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (out_is_simply_jumpable_p != NULL)
|
|
{
|
|
*out_is_simply_jumpable_p = is_simply_jumpable;
|
|
}
|
|
|
|
return ret_label_p;
|
|
} /* jsp_label_find */
|
|
|
|
/**
|
|
* Dump jump and register it in the specified label to be rewritten later (see also: jsp_label_rewrite_jumps_and_pop)
|
|
*
|
|
* Warning:
|
|
* The dumped instruction should not be modified before it is rewritten, as its idx fields are used
|
|
* to link jump instructions related to the label into singly linked list.
|
|
*/
|
|
void
|
|
jsp_label_add_jump (jsp_label_t *label_p, /**< label to register jump for */
|
|
bool is_simply_jumpable, /**< is the label currently
|
|
* accessible with a simple jump */
|
|
bool is_break) /**< type of jump - 'break' (true) or 'continue' (false) */
|
|
{
|
|
JERRY_ASSERT (label_p != NULL);
|
|
|
|
if (is_break)
|
|
{
|
|
label_p->breaks_list_oc = dump_simple_or_nested_jump_for_rewrite (is_simply_jumpable,
|
|
label_p->breaks_list_oc);
|
|
label_p->breaks_number++;
|
|
}
|
|
else
|
|
{
|
|
label_p->continues_list_oc = dump_simple_or_nested_jump_for_rewrite (is_simply_jumpable,
|
|
label_p->continues_list_oc);
|
|
label_p->continues_number++;
|
|
}
|
|
} /* jsp_label_add_jump */
|
|
|
|
/**
|
|
* Setup target for 'continue' jumps,
|
|
* associated with the labels, from innermost
|
|
* to the specified label.
|
|
*/
|
|
void
|
|
jsp_label_setup_continue_target (jsp_label_t *outermost_label_p, /**< the outermost label to setup target for */
|
|
opcode_counter_t tgt_oc) /**< target */
|
|
{
|
|
/* There are no labels that could not be targeted with 'break' jumps */
|
|
JERRY_ASSERT (tgt_oc != MAX_OPCODES);
|
|
JERRY_ASSERT (outermost_label_p != NULL);
|
|
|
|
for (jsp_label_t *label_iter_p = label_set_p;
|
|
label_iter_p != outermost_label_p->next_label_p;
|
|
label_iter_p = label_iter_p->next_label_p)
|
|
{
|
|
JERRY_ASSERT (label_iter_p != NULL);
|
|
JERRY_ASSERT (label_iter_p->continue_tgt_oc == MAX_OPCODES);
|
|
|
|
label_iter_p->continue_tgt_oc = tgt_oc;
|
|
}
|
|
} /* jsp_label_setup_continue_target */
|
|
|
|
/**
|
|
* Mark current label, if any, as nested jumpable border
|
|
*/
|
|
void
|
|
jsp_label_raise_nested_jumpable_border (void)
|
|
{
|
|
if (label_set_p != NULL)
|
|
{
|
|
JERRY_ASSERT (!label_set_p->is_nested_jumpable_border);
|
|
label_set_p->is_nested_jumpable_border = true;
|
|
}
|
|
} /* jsp_label_raise_nested_jumpable_border */
|
|
|
|
/**
|
|
* Unmark current label, if any, as nested jumpable border
|
|
*/
|
|
void
|
|
jsp_label_remove_nested_jumpable_border (void)
|
|
{
|
|
if (label_set_p != NULL)
|
|
{
|
|
JERRY_ASSERT (label_set_p->is_nested_jumpable_border);
|
|
label_set_p->is_nested_jumpable_border = false;
|
|
}
|
|
} /* jsp_label_remove_nested_jumpable_border */
|
|
|
|
/**
|
|
* Mask current label set to restore it later, and start new label set
|
|
*
|
|
* @return pointer to masked label set's list of labels
|
|
*/
|
|
jsp_label_t*
|
|
jsp_label_mask_set (void)
|
|
{
|
|
jsp_label_t *ret_p = label_set_p;
|
|
|
|
label_set_p = NULL;
|
|
|
|
return ret_p;
|
|
} /* jsp_label_mask_set */
|
|
|
|
/**
|
|
* Restore previously masked label set
|
|
*
|
|
* Note:
|
|
* current label set should be empty
|
|
*/
|
|
void
|
|
jsp_label_restore_set (jsp_label_t *masked_label_set_list_p) /**< list of labels of
|
|
* a masked label set */
|
|
{
|
|
JERRY_ASSERT (label_set_p == NULL);
|
|
|
|
label_set_p = masked_label_set_list_p;
|
|
} /* jsp_label_restore_set */
|
|
|
|
/**
|
|
* @}
|
|
* @}
|
|
*/
|