Renaming core -> jerry-core.

This commit is contained in:
Ruben Ayrapetyan
2015-02-17 19:00:34 +03:00
parent b6d018d019
commit 88353e93cf
183 changed files with 14 additions and 14 deletions
@@ -0,0 +1,141 @@
/* Copyright 2014-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 "array-list.h"
#include "mem-heap.h"
#include "jrt-libc-includes.h"
#define ARRAY_LIST_MAGIC 0x39
typedef struct
{
uint8_t magic;
uint8_t element_size;
size_t len;
size_t size;
}
array_list_header;
static array_list_header *
extract_header (array_list al)
{
JERRY_ASSERT (al != null_list);
array_list_header *header = (array_list_header *) al;
JERRY_ASSERT (header->magic == ARRAY_LIST_MAGIC);
return header;
}
static uint8_t *
data (array_list al)
{
return (uint8_t *) al + sizeof (array_list_header);
}
array_list
array_list_append (array_list al, void *element)
{
array_list_header *h = extract_header (al);
if ((h->len + 1) * h->element_size + sizeof (array_list_header) > h->size)
{
size_t size = mem_heap_recommend_allocation_size (h->size + h->element_size);
JERRY_ASSERT (size > h->size);
uint8_t* new_block_p = (uint8_t*) mem_heap_alloc_block (size, MEM_HEAP_ALLOC_SHORT_TERM);
memcpy (new_block_p, h, h->size);
memset (new_block_p + h->size, 0, size - h->size);
mem_heap_free_block ((uint8_t *) h);
h = (array_list_header *) new_block_p;
h->size = size;
al = (array_list) h;
}
memcpy (data (al) + (h->len * h->element_size), element, h->element_size);
h->len++;
return al;
}
void
array_list_drop_last (array_list al)
{
array_list_header *h = extract_header (al);
JERRY_ASSERT (h->len > 0);
h->len--;
}
void *
array_list_element (array_list al, size_t index)
{
array_list_header *h = extract_header (al);
if (h->len <= index)
{
return NULL;
}
return data (al) + (index * h->element_size);
}
void
array_list_set_element (array_list al, size_t index, void *elem)
{
array_list_header *h = extract_header (al);
JERRY_ASSERT (index < h->len);
memcpy (data (al) + (index * h->element_size), elem, h->element_size);
}
void *
array_list_last_element (array_list al, size_t index)
{
array_list_header *h = extract_header (al);
if (index == 0 || index > h->len)
{
return NULL;
}
return array_list_element (al, (size_t) (h->len - index));
}
void
array_list_set_last_element (array_list al, size_t index, void *elem)
{
array_list_header *h = extract_header (al);
JERRY_ASSERT (index != 0 && index <= h->len);
array_list_set_element (al, (size_t) (h->len - index), elem);
}
array_list
array_list_init (uint8_t element_size)
{
size_t size = mem_heap_recommend_allocation_size (sizeof (array_list_header));
array_list_header *header = (array_list_header *) mem_heap_alloc_block (size, MEM_HEAP_ALLOC_SHORT_TERM);
memset (header, 0, size);
header->magic = ARRAY_LIST_MAGIC;
header->element_size = element_size;
header->len = 0;
header->size = size;
return (array_list) header;
}
size_t
array_list_len (array_list al)
{
array_list_header *h = extract_header (al);
return h->len;
}
void
array_list_free (array_list al)
{
array_list_header *h = extract_header (al);
mem_heap_free_block ((uint8_t *) h);
}
@@ -0,0 +1,34 @@
/* Copyright 2014-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.
*/
#ifndef ARRAY_LIST_H
#define ARRAY_LIST_H
#include "jrt.h"
typedef uint8_t* array_list;
#define null_list NULL
array_list array_list_init (uint8_t);
void array_list_free (array_list);
array_list array_list_append (array_list, void *);
void array_list_drop_last (array_list);
void *array_list_element (array_list, size_t);
void array_list_set_element (array_list, size_t, void *);
void *array_list_last_element (array_list, size_t);
void array_list_set_last_element (array_list, size_t, void *);
size_t array_list_len (array_list);
#endif /* ARRAY_LIST_H */
@@ -0,0 +1,136 @@
/* Copyright 2014-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 "hash-table.h"
#include "array-list.h"
#include "mem-heap.h"
#include "jrt-libc-includes.h"
#define HASH_MAP_MAGIC 0x67
typedef struct
{
uint16_t (*hash) (void *);
array_list *data;
uint16_t size;
uint8_t magic;
uint8_t key_size;
uint8_t value_size;
mem_heap_alloc_term_t alloc_term;
}
hash_table_int;
static hash_table_int *
extract_header (hash_table ht)
{
JERRY_ASSERT (ht != null_hash);
hash_table_int *hti = (hash_table_int *) ht;
JERRY_ASSERT (hti->magic == HASH_MAP_MAGIC);
return hti;
}
static uint8_t
bucket_size (hash_table_int *hti)
{
return (uint8_t) (hti->key_size + hti->value_size);
}
static array_list
get_list (hash_table_int *h, uint16_t i)
{
return h->data[i];
}
static void
set_list (hash_table_int *h, uint16_t i, array_list al)
{
h->data[i] = al;
}
void
hash_table_insert (hash_table ht, void *key, void *value)
{
hash_table_int *hti = extract_header (ht);
uint16_t index = hti->hash (key);
JERRY_ASSERT (index < hti->size);
array_list list = get_list (hti, index);
if (list == null_list)
{
list = array_list_init (bucket_size (hti));
}
uint8_t *bucket = (uint8_t*) mem_heap_alloc_block (bucket_size (hti), hti->alloc_term);
memcpy (bucket, key, hti->key_size);
memcpy (bucket + hti->key_size, value, hti->value_size);
list = array_list_append (list, bucket);
hti->data[index] = list;
mem_heap_free_block (bucket);
}
void *
hash_table_lookup (hash_table ht, void *key)
{
JERRY_ASSERT (key != NULL);
hash_table_int *h = extract_header (ht);
uint16_t index = h->hash (key);
array_list al = get_list (h, index);
if (al == null_list)
{
return NULL;
}
for (uint16_t i = 0; i < array_list_len (al); i++)
{
uint8_t *bucket = (uint8_t*) array_list_element (al, i);
JERRY_ASSERT (bucket != NULL);
if (!memcmp (bucket, key, h->key_size))
{
return bucket + h->key_size;
}
}
return NULL;
}
hash_table
hash_table_init (uint8_t key_size, uint8_t value_size, uint16_t size,
uint16_t (*hash) (void *), mem_heap_alloc_term_t alloc_term)
{
hash_table_int *res = (hash_table_int *) mem_heap_alloc_block (sizeof (hash_table_int), alloc_term);
memset (res, 0, sizeof (hash_table_int));
res->magic = HASH_MAP_MAGIC;
res->key_size = key_size;
res->value_size = value_size;
res->size = size;
res->alloc_term = alloc_term;
res->data = (array_list *) mem_heap_alloc_block (size * sizeof (array_list), alloc_term);
memset (res->data, 0, size * sizeof (array_list));
res->hash = hash;
return res;
}
void
hash_table_free (hash_table ht)
{
hash_table_int *h = extract_header (ht);
for (uint16_t i = 0; i < h->size; i++)
{
array_list al = get_list (h, i);
if (al != null_list)
{
array_list_free (al);
set_list (h, i, null_list);
}
}
mem_heap_free_block ((uint8_t *) h->data);
mem_heap_free_block ((uint8_t *) h);
}
@@ -0,0 +1,38 @@
/* Copyright 2014 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.
*/
/**
This file contains functions to create and manipulate hash-tables.
Before using the hash initialize it by calling hash_table_init function.
The function takes pointer to hash function as the last parameter.
URGENT: the result of the hash function must not be greater than size of the hash table.
To insert a key-value pair, use hash_table_insert function.
To lookup a value by the key, use hash_table_lookup function.
After using the hash, delete it by calling hash_table_free function.
*/
#ifndef HASH_TABLE_H
#define HASH_TABLE_H
#include "mem-heap.h"
typedef void* hash_table;
#define null_hash NULL
hash_table hash_table_init (uint8_t, uint8_t, uint16_t, uint16_t (*hash) (void *), mem_heap_alloc_term_t);
void hash_table_free (hash_table);
void hash_table_insert (hash_table, void *, void *);
void *hash_table_lookup (hash_table, void *);
#endif /* HASH_TABLE_H */
@@ -0,0 +1,117 @@
/* Copyright 2014-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 "linked-list.h"
#include "jrt-libc-includes.h"
#include "jrt.h"
#include "mem-heap.h"
#include "lp-string.h"
#define LINKED_LIST_MAGIC 0x42
typedef struct linked_list_header
{
struct linked_list_header *next;
struct linked_list_header *prev;
uint16_t block_size;
uint16_t element_size;
uint8_t magic;
}
linked_list_header;
#define ASSERT_LIST(list) \
do { \
linked_list_header *header = (linked_list_header *) list; \
JERRY_ASSERT (header); \
JERRY_ASSERT (header->magic == LINKED_LIST_MAGIC); \
} while (0);
linked_list
linked_list_init (uint16_t element_size)
{
size_t size = mem_heap_recommend_allocation_size (element_size);
linked_list list = (linked_list) mem_heap_alloc_block (size, MEM_HEAP_ALLOC_SHORT_TERM);
if (list == null_list)
{
printf ("Out of memory");
JERRY_UNREACHABLE ();
}
memset (list, 0, size);
linked_list_header* header = (linked_list_header *) list;
header->magic = LINKED_LIST_MAGIC;
header->prev = header->next = null_list;
header->element_size = element_size;
header->block_size = (uint8_t) (size - sizeof (linked_list_header));
return list;
}
void
linked_list_free (linked_list list)
{
ASSERT_LIST (list);
linked_list_header *header = (linked_list_header *) list;
if (header->next)
{
linked_list_free ((linked_list) header->next);
}
mem_heap_free_block (list);
}
void *
linked_list_element (linked_list list, uint16_t element_num)
{
ASSERT_LIST (list);
linked_list_header *header = (linked_list_header *) list;
linked_list raw = list + sizeof (linked_list_header);
if (header->block_size < header->element_size * (element_num + 1))
{
if (header->next)
{
return linked_list_element ((linked_list) header->next,
(uint16_t) (element_num - (header->block_size / header->element_size)));
}
else
{
return NULL;
}
}
raw += header->element_size * element_num;
return raw;
}
void
linked_list_set_element (linked_list list, uint16_t element_num, void *element)
{
ASSERT_LIST (list);
linked_list_header *header = (linked_list_header *) list;
uint8_t *raw = (uint8_t *) (header + 1);
if (header->block_size < header->element_size * (element_num + 1))
{
if (header->next == null_list)
{
header->next = (linked_list_header *) linked_list_init (header->element_size);
header->next->prev = header;
}
linked_list_set_element ((linked_list) header->next,
(uint16_t) (element_num - (header->block_size / header->element_size)),
element);
return;
}
if (element == NULL)
{
return;
}
memcpy (raw + element_num * header->element_size, element, header->element_size);
}
@@ -0,0 +1,29 @@
/* Copyright 2014-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.
*/
#ifndef LINKED_LIST_H
#define LINKED_LIST_H
#include "jrt.h"
typedef uint8_t* linked_list;
#define null_list NULL
linked_list linked_list_init (uint16_t);
void linked_list_free (linked_list);
void *linked_list_element (linked_list, uint16_t);
void linked_list_set_element (linked_list, uint16_t, void *);
#endif /* LINKED_LIST_H */
@@ -0,0 +1,66 @@
/* Copyright 2014-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 "lit-id-hash-table.h"
#include "mem-heap.h"
#include "jrt-libc-includes.h"
#include "bytecode-data.h"
lit_id_hash_table *
lit_id_hash_table_init (size_t buckets_count, size_t blocks_count)
{
size_t size = mem_heap_recommend_allocation_size (sizeof (lit_id_hash_table));
lit_id_hash_table *table = (lit_id_hash_table *) mem_heap_alloc_block (size, MEM_HEAP_ALLOC_LONG_TERM);
memset (table, 0, size);
size = mem_heap_recommend_allocation_size (sizeof (literal_index_t) * buckets_count);
table->raw_buckets = (literal_index_t *) mem_heap_alloc_block (size, MEM_HEAP_ALLOC_LONG_TERM);
memset (table->raw_buckets, 0, size);
size = mem_heap_recommend_allocation_size (sizeof (literal_index_t *) * blocks_count);
table->buckets = (literal_index_t **) mem_heap_alloc_block (size, MEM_HEAP_ALLOC_LONG_TERM);
memset (table->buckets, 0, size);
table->current_bucket_pos = 0;
return table;
}
void
lit_id_hash_table_free (lit_id_hash_table *table)
{
JERRY_ASSERT (table);
mem_heap_free_block ((uint8_t *) table->raw_buckets);
mem_heap_free_block ((uint8_t *) table->buckets);
mem_heap_free_block ((uint8_t *) table);
}
void
lit_id_hash_table_insert (lit_id_hash_table *table, idx_t uid, opcode_counter_t oc, literal_index_t lit_id)
{
JERRY_ASSERT (table);
size_t block_id = oc / BLOCK_SIZE;
if (table->buckets[block_id] == NULL)
{
table->buckets[block_id] = table->raw_buckets + table->current_bucket_pos;
}
table->buckets[block_id][uid] = lit_id;
table->current_bucket_pos++;
}
literal_index_t
lit_id_hash_table_lookup (lit_id_hash_table *table, idx_t uid, opcode_counter_t oc)
{
JERRY_ASSERT (table);
size_t block_id = oc / BLOCK_SIZE;
JERRY_ASSERT (table->buckets[block_id]);
return table->buckets[block_id][uid];
}
@@ -0,0 +1,36 @@
/* Copyright 2014-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.
*/
#ifndef LIT_ID_HASH_TABLE
#define LIT_ID_HASH_TABLE
#include "jrt.h"
#include "ecma-globals.h"
#include "opcodes.h"
typedef struct
{
size_t current_bucket_pos;
literal_index_t *raw_buckets;
literal_index_t **buckets;
}
lit_id_hash_table;
lit_id_hash_table *lit_id_hash_table_init (size_t, size_t);
void lit_id_hash_table_free (lit_id_hash_table *);
void lit_id_hash_table_insert (lit_id_hash_table *, idx_t, opcode_counter_t, literal_index_t);
literal_index_t lit_id_hash_table_lookup (lit_id_hash_table *, idx_t, opcode_counter_t);
#endif /* LIT_ID_HASH_TABLE */
+62
View File
@@ -0,0 +1,62 @@
/* 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.
*/
#ifndef LITERAL_H
#define LITERAL_H
#include "ecma-globals.h"
#include "lp-string.h"
typedef enum
{
LIT_UNKNOWN,
LIT_STR,
LIT_MAGIC_STR,
LIT_NUMBER
}
literal_type;
typedef struct
{
union
{
ecma_magic_string_id_t magic_str_id;
ecma_number_t num;
lp_string lp;
void *none;
}
data;
literal_type type;
}
literal;
#define LITERAL_TO_REWRITE (INVALID_VALUE - 1)
literal create_empty_literal (void);
literal create_literal_from_num (ecma_number_t);
literal create_literal_from_str (const char *, ecma_length_t);
literal create_literal_from_str_compute_len (const char *);
literal create_literal_from_zt (const ecma_char_t *, ecma_length_t);
bool literal_equal (literal, literal);
bool literal_equal_s (literal, const char *);
bool literal_equal_zt (literal, const ecma_char_t *);
bool literal_equal_num (literal, ecma_number_t);
bool literal_equal_type (literal, literal);
bool literal_equal_type_s (literal, const char *);
bool literal_equal_type_zt (literal, const ecma_char_t *);
bool literal_equal_type_num (literal, ecma_number_t);
const ecma_char_t *literal_to_zt (literal);
#endif /* LITERAL_H */
@@ -0,0 +1,63 @@
/* Copyright 2014-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 "lp-string.h"
#include "jrt-libc-includes.h"
bool
lp_string_equal (lp_string s1, lp_string s2)
{
if (s1.length != s2.length)
{
return false;
}
for (ecma_length_t i = 0; i < s1.length; i++)
{
JERRY_ASSERT (s1.str[i] != '\0' && s1.str[i] != '\0');
if (s1.str[i] != s2.str[i])
{
return false;
}
}
return true;
}
bool
lp_string_equal_s (lp_string lp, const char *s)
{
return lp_string_equal_zt (lp, (const ecma_char_t *) s);
}
bool
lp_string_equal_zt (lp_string lp, const ecma_char_t *s)
{
for (ecma_length_t i = 0; i < lp.length; i++)
{
JERRY_ASSERT (lp.str[i] != '\0');
if (lp.str[i] != s[i])
{
return false;
}
}
if (s[lp.length] != '\0')
{
return false;
}
return true;
}
+34
View File
@@ -0,0 +1,34 @@
/* Copyright 2014 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.
*/
#ifndef LP_STRING
#define LP_STRING
#include "ecma-globals.h"
/* Length-prefixed or "pascal" string. */
typedef struct
{
const ecma_char_t *str;
ecma_length_t length;
ecma_string_hash_t hash;
}
lp_string;
bool lp_string_equal (lp_string, lp_string);
bool lp_string_equal_s (lp_string, const char *);
bool lp_string_equal_zt (lp_string, const ecma_char_t *);
#endif /* LP_STRING */
+237
View File
@@ -0,0 +1,237 @@
/* Copyright 2014-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.
*/
/**
This file contains macros to define and use stacks.
Use macro STACK or STATIC_STACK to create stack variable and define all necessaty routines.
Also, define variable with name NAME##_global_size. If the variable more than 0,
first NAME##_global_size element will remain untouched during STACK_PUSH and STACK_POP operations.
Before using the stack, init it by calling STACK_INIT macro.
Use macros STACK_PUSH, STACK_POP, STACK_DROP, STACK_CLEAN and STACK_HEAD to manipulate the stack.
DO NOT FORGET to free stack memory by calling STACK_FREE macro.
For check usage of stack during a function, use STACK_DECLARE_USAGE and STACK_CHECK_USAGE macros.
For the purpose of memory fragmentation reduction, the memory is allocated by chunks and them are
used to store data. The chunks are connected to each other in manner of double-linked list.
Macro STACK_CONVERT_TO_RAW_DATA allocates memory, so use it after finishing working with the stack.
Example (parser.c):
enum
{
temp_name,
min_temp_name,
max_temp_name,
temp_names_global_size
};
STACK(temp_names, uint8_t, uint8_t)
#define GLOBAL(NAME, VAR) \
STACK_ELEMENT (NAME, VAR)
#define MAX_TEMP_NAME() \
GLOBAL(temp_names, max_temp_name)
#define MIN_TEMP_NAME() \
GLOBAL(temp_names, min_temp_name)
#define TEMP_NAME() \
GLOBAL(temp_names, temp_name)
void
parser_init (void)
{
STACK_INIT(temp_names)
}
void
parser_free (void)
{
STACK_FREE(temp_names)
}
*/
#ifndef STACK_H
#define STACK_H
#include "array-list.h"
#define DEFINE_STACK_TYPE(NAME, TYPE) \
typedef TYPE NAME##_stack_value_type; \
typedef struct \
{ \
array_list data; \
} \
NAME##_stack;
#define STACK_INIT(NAME) \
do { \
NAME.data = array_list_init (sizeof (NAME##_stack_value_type)); \
} while (0)
#define STACK_FREE(NAME) \
do { \
array_list_free (NAME.data); \
NAME.data = null_list; \
} while (0)
#define DEFINE_STACK_ELEMENT(NAME, TYPE) \
static TYPE NAME##_stack_element (size_t) __attr_unused___; \
static TYPE NAME##_stack_element (size_t elem) { \
return *((TYPE *) array_list_element (NAME.data, elem)); \
}
#define DEFINE_SET_STACK_ELEMENT(NAME, TYPE) \
static void set_##NAME##_stack_element (size_t, TYPE) __attr_unused___; \
static void set_##NAME##_stack_element (size_t elem, TYPE value) { \
array_list_set_element (NAME.data, elem, &value); \
}
#define DEFINE_STACK_HEAD(NAME, TYPE) \
static TYPE NAME##_stack_head (size_t) __attr_unused___; \
static TYPE NAME##_stack_head (size_t elem) { \
return *((TYPE *) array_list_last_element (NAME.data, elem)); \
}
#define DEFINE_SET_STACK_HEAD(NAME, TYPE) \
static void set_##NAME##_stack_head (size_t, TYPE) __attr_unused___; \
static void set_##NAME##_stack_head (size_t elem, TYPE value) { \
array_list_set_last_element (NAME.data, elem, &value); \
}
#define DEFINE_STACK_PUSH(NAME, TYPE) \
static void NAME##_stack_push (TYPE) __attr_unused___; \
static void NAME##_stack_push (TYPE value) { \
NAME.data = array_list_append (NAME.data, &value); \
}
#define DEFINE_CONVERT_TO_RAW_DATA(NAME, TYPE) \
static TYPE *convert_##NAME##_to_raw_data (void) __attr_unused___; \
static TYPE *convert_##NAME##_to_raw_data (void) { \
if (array_list_len (NAME.data) == 0) \
{ \
return NULL; \
} \
size_t size = mem_heap_recommend_allocation_size ( \
array_list_len (NAME.data) * sizeof (NAME##_stack_value_type)); \
TYPE *DATA = (TYPE *) mem_heap_alloc_block (size, MEM_HEAP_ALLOC_LONG_TERM); \
if (DATA == NULL) \
{ \
printf ("Out of memory\n"); \
JERRY_UNREACHABLE (); \
} \
memcpy (DATA, array_list_element (NAME.data, 0), array_list_len (NAME.data) * sizeof (NAME##_stack_value_type)); \
return DATA; \
}
#define STACK_PUSH(NAME, VALUE) \
do { NAME##_stack_push (VALUE); } while (0)
#define STACK_DROP(NAME, I) \
do { \
for (size_t i = 0, till = (size_t) (I); i < till; i++) { \
array_list_drop_last (NAME.data); } } while (0)
#define STACK_CLEAN(NAME) \
STACK_DROP (NAME, NAME.current - NAME##_global_size);
#define STACK_HEAD(NAME, I) \
NAME##_stack_head ((size_t) (I))
#define STACK_SET_HEAD(NAME, I, VALUE) \
do { set_##NAME##_stack_head ((size_t) (I), VALUE); } while (0)
#define STACK_INCR_HEAD(NAME, I) \
do { STACK_SET_HEAD (NAME, I, (NAME##_stack_value_type) (STACK_HEAD (NAME, I) + 1)); } while (0)
#define STACK_DECR_HEAD(NAME, I) \
do { STACK_SET_HEAD (NAME, I, (NAME##_stack_value_type) (STACK_HEAD (NAME, I) - 1)); } while (0)
#define STACK_TOP(NAME) \
STACK_HEAD (NAME, 1)
#define STACK_SWAP(NAME) \
do { \
NAME##_stack_value_type temp = STACK_TOP(NAME); \
STACK_SET_HEAD(NAME, 1, STACK_HEAD(NAME, 2)); \
STACK_SET_HEAD(NAME, 2, temp); \
} while (0)
#define STACK_SIZE(NAME) \
array_list_len (NAME.data)
#define STACK_ELEMENT(NAME, I) \
NAME##_stack_element ((size_t) (I))
#define STACK_SET_ELEMENT(NAME, I, VALUE) \
do { set_##NAME##_stack_element ((size_t) I, VALUE); } while (0)
#define STACK_CONVERT_TO_RAW_DATA(NAME, DATA) \
do { DATA = convert_##NAME##_to_raw_data (); } while (0)
#define STACK_INCR_ELEMENT(NAME, I) \
do { STACK_SET_ELEMENT (NAME, I, (NAME##_stack_value_type) (STACK_ELEMENT(NAME, I) + 1)); } while (0)
#define STACK_DECR_ELEMENT(NAME, I) \
do { STACK_SET_ELEMENT (NAME, I, (NAME##_stack_value_type) (STACK_ELEMENT(NAME, I) - 1)); } while (0)
#define STACK_ITERATE(NAME, VAL, FROM) \
for (size_t NAME##_i = FROM; \
NAME##_i < array_list_len (NAME.data); \
NAME##_i++) \
{ \
NAME##_stack_value_type VAL = STACK_ELEMENT (NAME, NAME##_i);
#define STACK_ITERATE_END() \
}
#define STACK_ITERATE_VARG_SET(NAME, FUNC, FROM, ...) \
do { for (size_t i = FROM; i < array_list_len (NAME.data); i++) { \
STACK_SET_ELEMENT (NAME, i, FUNC (STACK_ELEMENT (NAME, i), __VA_ARGS__)); \
} } while (0)
#define STACK(NAME, TYPE) \
DEFINE_STACK_TYPE(NAME, TYPE) \
NAME##_stack NAME; \
DEFINE_STACK_ELEMENT(NAME, TYPE) \
DEFINE_SET_STACK_ELEMENT(NAME, TYPE) \
DEFINE_STACK_HEAD(NAME, TYPE) \
DEFINE_CONVERT_TO_RAW_DATA(NAME, TYPE) \
DEFINE_SET_STACK_HEAD(NAME, TYPE) \
DEFINE_STACK_PUSH(NAME, TYPE)
#define STATIC_STACK(NAME, TYPE) \
DEFINE_STACK_TYPE(NAME, TYPE) \
static NAME##_stack NAME; \
DEFINE_STACK_ELEMENT(NAME, TYPE) \
DEFINE_SET_STACK_ELEMENT(NAME, TYPE) \
DEFINE_STACK_HEAD(NAME, TYPE) \
DEFINE_CONVERT_TO_RAW_DATA(NAME, TYPE) \
DEFINE_SET_STACK_HEAD(NAME, TYPE) \
DEFINE_STACK_PUSH(NAME, TYPE)
#ifndef JERRY_NDEBUG
#define STACK_DECLARE_USAGE(NAME) \
size_t NAME##_current = array_list_len (NAME.data);
#define STACK_CHECK_USAGE(NAME) \
do { \
JERRY_ASSERT (array_list_len (NAME.data) == NAME##_current); \
} while (0)
#else
#define STACK_DECLARE_USAGE(NAME) ;
#define STACK_CHECK_USAGE(NAME) ;
#endif /* JERRY_NDEBUG */
#endif /* STACK_H */
+32
View File
@@ -0,0 +1,32 @@
/* Copyright 2014 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.
*/
#ifndef TREE_H
#define TREE_H
#include "linked-list.h"
#define TREE_MAGIC 0x43
typedef struct tree_header
{
struct tree_header *parent;
linked_list children;
uint8_t magic;
uint8_t children_num;
}
tree_header;
#endif /* TREE_H */
View File
+48
View File
@@ -0,0 +1,48 @@
/* Copyright 2014-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.
*/
#ifndef BYTECODE_DATA_H
#define BYTECODE_DATA_H
#include "opcodes.h"
#include "stack.h"
#include "jrt-libc-includes.h"
#include "literal.h"
#include "scopes-tree.h"
#include "lit-id-hash-table.h"
#define BLOCK_SIZE 64
typedef struct
{
opcode_counter_t oc;
idx_t uid;
uint8_t reserved;
}
lit_id_table_key;
typedef struct
{
const literal *literals;
const opcode_t *opcodes;
lit_id_hash_table *lit_id_hash;
literal_index_t literals_count;
opcode_counter_t opcodes_count;
} bytecode_data_t;
extern bytecode_data_t bytecode_data;
extern scopes_tree current_scope;
#endif // BYTECODE_DATA_H
+101
View File
@@ -0,0 +1,101 @@
/* Copyright 2014 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 "deserializer.h"
#include "bytecode-data.h"
#include "ecma-helpers.h"
const ecma_char_t *strings_buffer;
void
deserializer_set_strings_buffer (const ecma_char_t *s)
{
strings_buffer = s;
}
literal
deserialize_literal_by_id (literal_index_t id)
{
JERRY_ASSERT (id != INVALID_LITERAL);
JERRY_ASSERT (id < bytecode_data.literals_count);
return bytecode_data.literals[id];
}
literal_index_t
deserialize_lit_id_by_uid (uint8_t id, opcode_counter_t oc)
{
if (bytecode_data.lit_id_hash == null_hash)
{
return INVALID_LITERAL;
}
return lit_id_hash_table_lookup (bytecode_data.lit_id_hash, id, oc);
}
const void *
deserialize_bytecode (void)
{
JERRY_ASSERT (bytecode_data.opcodes != NULL);
return bytecode_data.opcodes;
}
opcode_t
deserialize_opcode (opcode_counter_t oc)
{
if (bytecode_data.opcodes == NULL)
{
return deserialize_op_meta (oc).op;
}
JERRY_ASSERT (oc < bytecode_data.opcodes_count);
return bytecode_data.opcodes[oc];
}
op_meta
deserialize_op_meta (opcode_counter_t oc)
{
JERRY_ASSERT (current_scope);
return scopes_tree_op_meta (current_scope, oc);
}
uint8_t
deserialize_min_temp (void)
{
return 128;
}
void
deserializer_init (void)
{
bytecode_data.literals = NULL;
strings_buffer = NULL;
bytecode_data.opcodes = NULL;
}
void
deserializer_free (void)
{
if (strings_buffer)
{
mem_heap_free_block ((uint8_t *) strings_buffer);
}
if (bytecode_data.lit_id_hash != NULL)
{
lit_id_hash_table_free (bytecode_data.lit_id_hash);
}
if (bytecode_data.literals != NULL)
{
mem_heap_free_block ((uint8_t *) bytecode_data.literals);
}
mem_heap_free_block ((uint8_t *) bytecode_data.opcodes);
}
+35
View File
@@ -0,0 +1,35 @@
/* Copyright 2014-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.
*/
#ifndef DESERIALIZER_H
#define DESERIALIZER_H
#include "jrt.h"
#include "ecma-globals.h"
#include "opcodes.h"
#include "scopes-tree.h"
#include "literal.h"
void deserializer_init (void);
void deserializer_set_strings_buffer (const ecma_char_t *);
literal deserialize_literal_by_id (literal_index_t);
literal_index_t deserialize_lit_id_by_uid (uint8_t, opcode_counter_t);
const void *deserialize_bytecode (void);
opcode_t deserialize_opcode (opcode_counter_t);
op_meta deserialize_op_meta (opcode_counter_t);
uint8_t deserialize_min_temp (void);
void deserializer_free (void);
#endif //DESERIALIZER_H
File diff suppressed because it is too large Load Diff
+191
View File
@@ -0,0 +1,191 @@
/* Copyright 2014 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.
*/
#ifndef LEXER_H
#define LEXER_H
#include "literal.h"
#define INVALID_VALUE 255
#define INVALID_LITERAL UINT32_MAX
/* Keywords. */
typedef enum
{
/* Not a keyword. */
KW_NONE = 0,
KW_BREAK,
KW_CASE,
KW_CATCH,
KW_CLASS,
KW_CONST,
KW_CONTINUE,
KW_DEBUGGER,
KW_DEFAULT,
KW_DELETE,
KW_DO,
KW_ELSE,
KW_ENUM,
KW_EXPORT,
KW_EXTENDS,
KW_FINALLY,
KW_FOR,
KW_FUNCTION,
KW_IF,
KW_IN,
KW_INSTANCEOF,
KW_INTERFACE,
KW_IMPORT,
KW_IMPLEMENTS,
KW_LET,
KW_NEW,
KW_PACKAGE,
KW_PRIVATE,
KW_PROTECTED,
KW_PUBLIC,
KW_RETURN,
KW_STATIC,
KW_SUPER,
KW_SWITCH,
KW_THIS,
KW_THROW,
KW_TRY,
KW_TYPEOF,
KW_VAR,
KW_VOID,
KW_WHILE,
KW_WITH,
KW_YIELD
}
keyword;
/* Type of tokens. */
typedef enum
{
TOK_EOF = 0, // End of file
TOK_NAME, // Identifier
TOK_KEYWORD, // Keyword
TOK_SMALL_INT,
TOK_NUMBER,
TOK_NULL,
TOK_BOOL,
TOK_NEWLINE,
TOK_STRING,
TOK_OPEN_BRACE, // {
TOK_CLOSE_BRACE, // }
TOK_OPEN_PAREN, // (
TOK_CLOSE_PAREN, //)
TOK_OPEN_SQUARE, // [
TOK_CLOSE_SQUARE, // [
TOK_DOT, // .
TOK_SEMICOLON, // ;
TOK_COMMA, // ,
TOK_LESS, // <
TOK_GREATER, // >
TOK_LESS_EQ, // <=
TOK_GREATER_EQ, // <=
TOK_DOUBLE_EQ, // ==
TOK_NOT_EQ, // !=
TOK_TRIPLE_EQ, // ===
TOK_NOT_DOUBLE_EQ, // !==
TOK_PLUS, // +
TOK_MINUS, // -
TOK_MULT, // *
TOK_MOD, // %
TOK_DOUBLE_PLUS, // ++
TOK_DOUBLE_MINUS, // --
TOK_LSHIFT, // <<
TOK_RSHIFT, // >>
TOK_RSHIFT_EX, // >>>
TOK_AND, // &
TOK_OR, // |
TOK_XOR, // ^
TOK_NOT, // !
TOK_COMPL, // ~
TOK_DOUBLE_AND, // &&
TOK_DOUBLE_OR, // ||
TOK_QUERY, // ?
TOK_COLON, // :
TOK_EQ, // =
TOK_PLUS_EQ, // +=
TOK_MINUS_EQ, // -=
TOK_MULT_EQ, // *=
TOK_MOD_EQ, // %=
TOK_LSHIFT_EQ, // <<=
TOK_RSHIFT_EQ, // >>=
TOK_RSHIFT_EX_EQ, // >>>=
TOK_AND_EQ, // &=
TOK_OR_EQ, // |=
TOK_XOR_EQ, // ^=
TOK_DIV, // /
TOK_DIV_EQ, // /=
TOK_EMPTY,
}
token_type;
typedef size_t locus;
/* Represents the contents of a token. */
typedef struct
{
locus loc;
token_type type;
literal_index_t uid;
}
token;
void lexer_init (const char *, size_t, bool);
void lexer_free (void);
token lexer_next_token (void);
void lexer_save_token (token);
token lexer_prev_token (void);
const literal *lexer_get_literals (void);
const ecma_char_t *lexer_get_strings_cache (void);
void lexer_add_literal_if_not_present (literal);
literal_index_t lexer_get_literals_count (void);
literal lexer_get_literal_by_id (literal_index_t);
literal_index_t lexer_lookup_literal_uid (literal lit);
void lexer_seek (locus);
void lexer_locus_to_line_and_column (locus, size_t *, size_t *);
void lexer_dump_line (size_t);
const char *lexer_keyword_to_string (keyword);
const char *lexer_token_type_to_string (token_type);
void lexer_set_strict_mode (bool);
#endif
+235
View File
@@ -0,0 +1,235 @@
/* Copyright 2014-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 "literal.h"
#include "ecma-helpers.h"
#include "jrt-libc-includes.h"
literal
create_empty_literal (void)
{
literal ret;
ret.type = LIT_UNKNOWN;
ret.data.none = NULL;
return ret;
}
literal
create_literal_from_num (ecma_number_t num)
{
literal ret;
ret.type = LIT_NUMBER;
ret.data.num = num;
return ret;
}
literal
create_literal_from_str (const char *s, ecma_length_t len)
{
return create_literal_from_zt ((const ecma_char_t *) s, len);
}
literal
create_literal_from_str_compute_len (const char *s)
{
return create_literal_from_zt ((const ecma_char_t *) s, (ecma_length_t) strlen (s));
}
literal
create_literal_from_zt (const ecma_char_t *s, ecma_length_t len)
{
for (ecma_magic_string_id_t msi = (ecma_magic_string_id_t) 0;
msi < ECMA_MAGIC_STRING__COUNT;
msi = (ecma_magic_string_id_t) (msi + 1))
{
if (ecma_zt_string_length (ecma_get_magic_string_zt (msi)) != len)
{
continue;
}
if (!strncmp ((const char *) s, (const char *) ecma_get_magic_string_zt (msi), len))
{
literal ret;
ret.type = LIT_MAGIC_STR;
ret.data.magic_str_id = msi;
return ret;
}
}
literal ret;
ret.type = LIT_STR;
ret.data.lp.length = len;
ret.data.lp.str = s;
ret.data.lp.hash = ecma_chars_buffer_calc_hash_last_chars (s, len);
return ret;
}
bool
literal_equal_type (literal lit1, literal lit2)
{
if (lit1.type != lit2.type)
{
return false;
}
return literal_equal (lit1, lit2);
}
bool
literal_equal_type_s (literal lit, const char *s)
{
return literal_equal_type_zt (lit, (const ecma_char_t *) s);
}
bool
literal_equal_type_zt (literal lit, const ecma_char_t *s)
{
if (lit.type != LIT_STR && lit.type != LIT_MAGIC_STR)
{
return false;
}
return literal_equal_zt (lit, s);
}
bool
literal_equal_type_num (literal lit, ecma_number_t num)
{
if (lit.type != LIT_NUMBER)
{
return false;
}
return literal_equal_num (lit, num);
}
static bool
literal_equal_lp (literal lit, lp_string lp)
{
switch (lit.type)
{
case LIT_UNKNOWN:
{
return false;
}
case LIT_STR:
{
return lp_string_equal (lit.data.lp, lp);
}
case LIT_MAGIC_STR:
{
return lp_string_equal_zt (lp, ecma_get_magic_string_zt (lit.data.magic_str_id));
}
case LIT_NUMBER:
{
ecma_char_t buff[ECMA_MAX_CHARS_IN_STRINGIFIED_NUMBER];
ecma_number_to_zt_string (lit.data.num, buff, ECMA_MAX_CHARS_IN_STRINGIFIED_NUMBER);
return lp_string_equal_zt (lp, buff);
}
default:
{
JERRY_UNREACHABLE ();
}
}
}
bool
literal_equal (literal lit1, literal lit2)
{
switch (lit2.type)
{
case LIT_UNKNOWN:
{
return lit2.type == LIT_UNKNOWN;
}
case LIT_STR:
{
return literal_equal_lp (lit1, lit2.data.lp);
}
case LIT_MAGIC_STR:
{
return literal_equal_zt (lit1, ecma_get_magic_string_zt (lit2.data.magic_str_id));
}
case LIT_NUMBER:
{
return literal_equal_num (lit1, lit2.data.num);
}
default:
{
JERRY_UNREACHABLE ();
}
}
}
bool
literal_equal_s (literal lit, const char *s)
{
return literal_equal_zt (lit, (const ecma_char_t *) s);
}
bool
literal_equal_zt (literal lit, const ecma_char_t *s)
{
switch (lit.type)
{
case LIT_UNKNOWN:
{
return false;
}
case LIT_STR:
{
return lp_string_equal_zt (lit.data.lp, s);
}
case LIT_MAGIC_STR:
{
return ecma_compare_zt_strings (s, ecma_get_magic_string_zt (lit.data.magic_str_id));
}
case LIT_NUMBER:
{
ecma_char_t buff[ECMA_MAX_CHARS_IN_STRINGIFIED_NUMBER];
ecma_number_to_zt_string (lit.data.num, buff, ECMA_MAX_CHARS_IN_STRINGIFIED_NUMBER);
return ecma_compare_zt_strings (s, buff);
}
default:
{
JERRY_UNREACHABLE ();
}
}
}
bool
literal_equal_num (literal lit, ecma_number_t num)
{
ecma_char_t buff[ECMA_MAX_CHARS_IN_STRINGIFIED_NUMBER];
ecma_number_to_zt_string (num, buff, ECMA_MAX_CHARS_IN_STRINGIFIED_NUMBER);
return literal_equal_zt (lit, buff);
}
const ecma_char_t *
literal_to_zt (literal lit)
{
JERRY_ASSERT (lit.type == LIT_STR || lit.type == LIT_MAGIC_STR);
switch (lit.type)
{
case LIT_STR: return lit.data.lp.str;
case LIT_MAGIC_STR: return ecma_get_magic_string_zt (lit.data.magic_str_id);
default: JERRY_UNREACHABLE ();
}
}
+62
View File
@@ -0,0 +1,62 @@
/* 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.
*/
#ifndef LITERAL_H
#define LITERAL_H
#include "ecma-globals.h"
#include "lp-string.h"
typedef enum
{
LIT_UNKNOWN,
LIT_STR,
LIT_MAGIC_STR,
LIT_NUMBER
}
literal_type;
typedef struct
{
union
{
ecma_magic_string_id_t magic_str_id;
ecma_number_t num;
lp_string lp;
void *none;
}
data;
literal_type type;
}
literal;
#define LITERAL_TO_REWRITE (INVALID_VALUE - 1)
literal create_empty_literal (void);
literal create_literal_from_num (ecma_number_t);
literal create_literal_from_str (const char *, ecma_length_t);
literal create_literal_from_str_compute_len (const char *);
literal create_literal_from_zt (const ecma_char_t *, ecma_length_t);
bool literal_equal (literal, literal);
bool literal_equal_s (literal, const char *);
bool literal_equal_zt (literal, const ecma_char_t *);
bool literal_equal_num (literal, ecma_number_t);
bool literal_equal_type (literal, literal);
bool literal_equal_type_s (literal, const char *);
bool literal_equal_type_zt (literal, const ecma_char_t *);
bool literal_equal_type_num (literal, ecma_number_t);
const ecma_char_t *literal_to_zt (literal);
#endif /* LITERAL_H */
File diff suppressed because it is too large Load Diff
+233
View File
@@ -0,0 +1,233 @@
/* Copyright 2014 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.
*/
#ifndef OPCODES_DUMPER_H
#define OPCODES_DUMPER_H
#include "opcodes.h"
#include "ecma-globals.h"
#include "lexer.h"
typedef enum
{
OPERAND_LITERAL,
OPERAND_TMP
}
operand_type;
typedef struct
{
operand_type type;
union
{
idx_t uid;
literal_index_t lit_id;
}
data;
}
operand;
typedef enum
{
VARG_FUNC_DECL,
VARG_FUNC_EXPR,
VARG_ARRAY_DECL,
VARG_OBJ_DECL,
VARG_CONSTRUCT_EXPR,
VARG_CALL_EXPR
}
varg_list_type;
operand empty_operand (void);
operand literal_operand (literal_index_t);
bool operand_is_empty (operand);
void dumper_init (void);
void dumper_free (void);
void dumper_new_statement (void);
void dumper_new_scope (void);
void dumper_finish_scope (void);
bool dumper_is_intrinsic (operand);
operand dump_intrinsic (operand, operand);
void dump_boolean_assignment (operand, bool);
operand dump_boolean_assignment_res (bool);
void dump_string_assignment (operand, literal_index_t);
operand dump_string_assignment_res (literal_index_t);
void dump_number_assignment (operand, literal_index_t);
operand dump_number_assignment_res (literal_index_t);
void dump_smallint_assignment (operand, idx_t);
operand dump_smallint_assignment_res (idx_t);
void dump_undefined_assignment (operand);
operand dump_undefined_assignment_res (void);
void dump_null_assignment (operand);
operand dump_null_assignment_res (void);
void dump_variable_assignment (operand, operand);
operand dump_variable_assignment_res (operand);
void dump_varg_header_for_rewrite (varg_list_type, operand);
operand rewrite_varg_header_set_args_count (uint8_t);
void dump_this_arg (operand);
void dump_varg (operand);
void dump_prop_name_and_value (operand, operand);
void dump_prop_getter_decl (operand, operand);
void dump_prop_setter_decl (operand, operand);
void dump_prop_getter (operand, operand, operand);
operand dump_prop_getter_res (operand, operand);
void dump_prop_setter (operand, operand, operand);
void dump_function_end_for_rewrite (void);
void rewrite_function_end (varg_list_type);
void dump_this (operand);
operand dump_this_res (void);
void dump_post_increment (operand, operand);
operand dump_post_increment_res (operand);
void dump_post_decrement (operand, operand);
operand dump_post_decrement_res (operand);
void dump_pre_increment (operand, operand);
operand dump_pre_increment_res (operand);
void dump_pre_decrement (operand, operand);
operand dump_pre_decrement_res (operand);
void dump_unary_plus (operand, operand);
operand dump_unary_plus_res (operand);
void dump_unary_minus (operand, operand);
operand dump_unary_minus_res (operand);
void dump_bitwise_not (operand, operand);
operand dump_bitwise_not_res (operand);
void dump_logical_not (operand, operand);
operand dump_logical_not_res (operand);
void dump_multiplication (operand, operand, operand);
operand dump_multiplication_res (operand, operand);
void dump_division (operand, operand, operand);
operand dump_division_res (operand, operand);
void dump_remainder (operand, operand, operand);
operand dump_remainder_res (operand, operand);
void dump_addition (operand, operand, operand);
operand dump_addition_res (operand, operand);
void dump_substraction (operand, operand, operand);
operand dump_substraction_res (operand, operand);
void dump_left_shift (operand, operand, operand);
operand dump_left_shift_res (operand, operand);
void dump_right_shift (operand, operand, operand);
operand dump_right_shift_res (operand, operand);
void dump_right_shift_ex (operand, operand, operand);
operand dump_right_shift_ex_res (operand, operand);
void dump_less_than (operand, operand, operand);
operand dump_less_than_res (operand, operand);
void dump_greater_than (operand, operand, operand);
operand dump_greater_than_res (operand, operand);
void dump_less_or_equal_than (operand, operand, operand);
operand dump_less_or_equal_than_res (operand, operand);
void dump_greater_or_equal_than (operand, operand, operand);
operand dump_greater_or_equal_than_res (operand, operand);
void dump_instanceof (operand, operand, operand);
operand dump_instanceof_res (operand, operand);
void dump_in (operand, operand, operand);
operand dump_in_res (operand, operand);
void dump_equal_value (operand, operand, operand);
operand dump_equal_value_res (operand, operand);
void dump_not_equal_value (operand, operand, operand);
operand dump_not_equal_value_res (operand, operand);
void dump_equal_value_type (operand, operand, operand);
operand dump_equal_value_type_res (operand, operand);
void dump_not_equal_value_type (operand, operand, operand);
operand dump_not_equal_value_type_res (operand, operand);
void dump_bitwise_and (operand, operand, operand);
operand dump_bitwise_and_res (operand, operand);
void dump_bitwise_xor (operand, operand, operand);
operand dump_bitwise_xor_res (operand, operand);
void dump_bitwise_or (operand, operand, operand);
operand dump_bitwise_or_res (operand, operand);
void start_dumping_logical_and_checks (void);
void dump_logical_and_check_for_rewrite (operand);
void rewrite_logical_and_checks (void);
void start_dumping_logical_or_checks (void);
void dump_logical_or_check_for_rewrite (operand);
void rewrite_logical_or_checks (void);
void dump_conditional_check_for_rewrite (operand);
void rewrite_conditional_check (void);
void dump_jump_to_end_for_rewrite (void);
void rewrite_jump_to_end (void);
void start_dumping_assignment_expression (void);
operand dump_prop_setter_or_variable_assignment_res (operand, operand);
operand dump_prop_setter_or_addition_res (operand, operand);
operand dump_prop_setter_or_multiplication_res (operand, operand);
operand dump_prop_setter_or_division_res (operand, operand);
operand dump_prop_setter_or_remainder_res (operand, operand);
operand dump_prop_setter_or_substraction_res (operand, operand);
operand dump_prop_setter_or_left_shift_res (operand, operand);
operand dump_prop_setter_or_right_shift_res (operand, operand);
operand dump_prop_setter_or_right_shift_ex_res (operand, operand);
operand dump_prop_setter_or_bitwise_and_res (operand, operand);
operand dump_prop_setter_or_bitwise_xor_res (operand, operand);
operand dump_prop_setter_or_bitwise_or_res (operand, operand);
void start_collecting_breaks (void);
void start_collecting_continues (void);
void dumper_set_break_target (void);
void dumper_set_continue_target (void);
void dumper_set_next_interation_target (void);
void dump_continue_for_rewrite (void);
void dump_break_for_rewrite (void);
void rewrite_continues (void);
void rewrite_breaks (void);
void dump_continue_iterations_check (operand);
void start_dumping_case_clauses (void);
void dump_case_clause_check_for_rewrite (operand, operand);
void dump_default_clause_check_for_rewrite (void);
void rewrite_case_clause (void);
void rewrite_default_clause (void);
void finish_dumping_case_clauses (void);
void dump_delete (operand, operand, bool, locus);
operand dump_delete_res (operand, bool, locus);
void dump_typeof (operand, operand);
operand dump_typeof_res (operand);
void dump_with (operand);
void dump_with_end (void);
void dump_try_for_rewrite (void);
void rewrite_try (void);
void dump_catch_for_rewrite (operand);
void rewrite_catch (void);
void dump_finally_for_rewrite (void);
void rewrite_finally (void);
void dump_end_try_catch_finally (void);
void dump_throw (operand);
bool dumper_variable_declaration_exists (literal_index_t);
void dump_variable_declaration (literal_index_t);
void dump_strict_mode_header (void);
void dump_reg_var_decl_for_rewrite (void);
void rewrite_reg_var_decl (void);
void dump_ret (void);
void dump_retval (operand op);
void dump_exit (void);
#endif /* OPCODES_DUMPER_H */
File diff suppressed because it is too large Load Diff
+25
View File
@@ -0,0 +1,25 @@
/* Copyright 2014-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.
*/
#ifndef PARSER_H
#define PARSER_H
#include "jrt.h"
void parser_init (const char *, size_t, bool);
void parser_parse_program (void);
void parser_free (void);
#endif
+686
View File
@@ -0,0 +1,686 @@
/* Copyright 2014-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 "scopes-tree.h"
#include "mem-heap.h"
#include "jrt-libc-includes.h"
#include "lexer.h"
#include "bytecode-data.h"
#define OPCODE(op) (__op__idx_##op)
#define HASH_SIZE 128
static hash_table lit_id_to_uid = null_hash;
static opcode_counter_t global_oc;
static idx_t next_uid;
static void
assert_tree (scopes_tree t)
{
JERRY_ASSERT (t != NULL);
JERRY_ASSERT (t->t.magic == TREE_MAGIC);
}
static idx_t
get_uid (op_meta *op, uint8_t i)
{
JERRY_ASSERT (i < 4);
raw_opcode *raw = (raw_opcode *) &op->op;
return raw->uids[i + 1];
}
static void
set_uid (op_meta *op, uint8_t i, idx_t uid)
{
JERRY_ASSERT (i < 4);
raw_opcode *raw = (raw_opcode *) &op->op;
raw->uids[i + 1] = uid;
}
opcode_counter_t
scopes_tree_opcodes_num (scopes_tree t)
{
assert_tree (t);
return t->opcodes_num;
}
void
scopes_tree_add_op_meta (scopes_tree tree, op_meta op)
{
assert_tree (tree);
linked_list_set_element (tree->opcodes, tree->opcodes_num++, &op);
}
void
scopes_tree_set_op_meta (scopes_tree tree, opcode_counter_t oc, op_meta op)
{
assert_tree (tree);
JERRY_ASSERT (oc < tree->opcodes_num);
linked_list_set_element (tree->opcodes, oc, &op);
}
void
scopes_tree_set_opcodes_num (scopes_tree tree, opcode_counter_t oc)
{
assert_tree (tree);
JERRY_ASSERT (oc < tree->opcodes_num);
tree->opcodes_num = oc;
}
op_meta
scopes_tree_op_meta (scopes_tree tree, opcode_counter_t oc)
{
assert_tree (tree);
JERRY_ASSERT (oc < tree->opcodes_num);
return *(op_meta *) linked_list_element (tree->opcodes, oc);
}
opcode_counter_t
scopes_tree_count_opcodes (scopes_tree t)
{
assert_tree (t);
opcode_counter_t res = t->opcodes_num;
for (uint8_t i = 0; i < t->t.children_num; i++)
{
res = (opcode_counter_t) (
res + scopes_tree_count_opcodes (
*(scopes_tree *) linked_list_element (t->t.children, i)));
}
return res;
}
static uint16_t
lit_id_hash (void * lit_id)
{
return *(literal_index_t *) lit_id % HASH_SIZE;
}
static void
start_new_block_if_necessary (void)
{
if (global_oc % BLOCK_SIZE == 0)
{
next_uid = 0;
if (lit_id_to_uid != null_hash)
{
hash_table_free (lit_id_to_uid);
lit_id_to_uid = null_hash;
}
lit_id_to_uid = hash_table_init (sizeof (literal_index_t), sizeof (idx_t), HASH_SIZE, lit_id_hash,
MEM_HEAP_ALLOC_SHORT_TERM);
}
}
static bool
is_possible_literal (uint16_t mask, uint8_t index)
{
int res;
switch (index)
{
case 0:
{
res = mask >> 8;
break;
}
case 1:
{
res = (mask & 0xF0) >> 4;
break;
}
default:
{
JERRY_ASSERT (index = 2);
res = mask & 0x0F;
}
}
JERRY_ASSERT (res == 0 || res == 1);
return res == 1;
}
static void
change_uid (op_meta *om, lit_id_hash_table *lit_ids, uint16_t mask)
{
for (uint8_t i = 0; i < 3; i++)
{
if (is_possible_literal (mask, i))
{
if (get_uid (om, i) == LITERAL_TO_REWRITE)
{
JERRY_ASSERT (om->lit_id[i] != NOT_A_LITERAL);
literal_index_t lit_id = om->lit_id[i];
idx_t *uid = (idx_t *) hash_table_lookup (lit_id_to_uid, &lit_id);
if (uid == NULL)
{
hash_table_insert (lit_id_to_uid, &lit_id, &next_uid);
lit_id_hash_table_insert (lit_ids, next_uid, global_oc, lit_id);
uid = (idx_t *) hash_table_lookup (lit_id_to_uid, &lit_id);
JERRY_ASSERT (uid != NULL);
JERRY_ASSERT (*uid == next_uid);
next_uid++;
}
set_uid (om, i, *uid);
}
else
{
JERRY_ASSERT (om->lit_id[i] == NOT_A_LITERAL);
}
}
else
{
JERRY_ASSERT (om->lit_id[i] == NOT_A_LITERAL);
}
}
}
static void
insert_uids_to_lit_id_map (op_meta *om, uint16_t mask)
{
for (uint8_t i = 0; i < 3; i++)
{
if (is_possible_literal (mask, i))
{
if (get_uid (om, i) == LITERAL_TO_REWRITE)
{
JERRY_ASSERT (om->lit_id[i] != NOT_A_LITERAL);
literal_index_t lit_id = om->lit_id[i];
idx_t *uid = (idx_t *) hash_table_lookup (lit_id_to_uid, &lit_id);
if (uid == NULL)
{
hash_table_insert (lit_id_to_uid, &lit_id, &next_uid);
uid = (idx_t *) hash_table_lookup (lit_id_to_uid, &lit_id);
JERRY_ASSERT (uid != NULL);
JERRY_ASSERT (*uid == next_uid);
next_uid++;
}
}
else
{
JERRY_ASSERT (om->lit_id[i] == NOT_A_LITERAL);
}
}
else
{
JERRY_ASSERT (om->lit_id[i] == NOT_A_LITERAL);
}
}
}
static op_meta *
extract_op_meta (scopes_tree tree, opcode_counter_t opc_index)
{
return (op_meta *) linked_list_element (tree->opcodes, opc_index);
}
static opcode_t
generate_opcode (scopes_tree tree, opcode_counter_t opc_index, lit_id_hash_table *lit_ids)
{
start_new_block_if_necessary ();
op_meta *om = extract_op_meta (tree, opc_index);
/* Now we should change uids of opcodes.
Since different opcodes has different literals/tmps in different places,
we should change only them.
For each case possible literal positions are shown as 0xYYY literal,
where Y is set to '1' when there is a possible literal in this position,
and '0' otherwise. */
switch (om->op.op_idx)
{
case OPCODE (prop_getter):
case OPCODE (prop_setter):
case OPCODE (delete_prop):
case OPCODE (b_shift_left):
case OPCODE (b_shift_right):
case OPCODE (b_shift_uright):
case OPCODE (b_and):
case OPCODE (b_or):
case OPCODE (b_xor):
case OPCODE (equal_value):
case OPCODE (not_equal_value):
case OPCODE (equal_value_type):
case OPCODE (not_equal_value_type):
case OPCODE (less_than):
case OPCODE (greater_than):
case OPCODE (less_or_equal_than):
case OPCODE (greater_or_equal_than):
case OPCODE (instanceof):
case OPCODE (in):
case OPCODE (addition):
case OPCODE (substraction):
case OPCODE (division):
case OPCODE (multiplication):
case OPCODE (remainder):
{
change_uid (om, lit_ids, 0x111);
break;
}
case OPCODE (call_n):
case OPCODE (native_call):
case OPCODE (construct_n):
case OPCODE (func_expr_n):
case OPCODE (delete_var):
case OPCODE (typeof):
case OPCODE (b_not):
case OPCODE (logical_not):
case OPCODE (post_incr):
case OPCODE (post_decr):
case OPCODE (pre_incr):
case OPCODE (pre_decr):
case OPCODE (unary_plus):
case OPCODE (unary_minus):
{
change_uid (om, lit_ids, 0x110);
break;
}
case OPCODE (assignment):
{
switch (om->op.data.assignment.type_value_right)
{
case OPCODE_ARG_TYPE_SIMPLE:
case OPCODE_ARG_TYPE_SMALLINT:
case OPCODE_ARG_TYPE_SMALLINT_NEGATE:
{
change_uid (om, lit_ids, 0x100);
break;
}
case OPCODE_ARG_TYPE_NUMBER:
case OPCODE_ARG_TYPE_NUMBER_NEGATE:
case OPCODE_ARG_TYPE_STRING:
case OPCODE_ARG_TYPE_VARIABLE:
{
change_uid (om, lit_ids, 0x101);
break;
}
}
break;
}
case OPCODE (func_decl_n):
case OPCODE (array_decl):
case OPCODE (obj_decl):
case OPCODE (this_binding):
case OPCODE (with):
case OPCODE (throw_value):
case OPCODE (is_true_jmp_up):
case OPCODE (is_true_jmp_down):
case OPCODE (is_false_jmp_up):
case OPCODE (is_false_jmp_down):
case OPCODE (var_decl):
case OPCODE (retval):
{
change_uid (om, lit_ids, 0x100);
break;
}
case OPCODE (exitval):
case OPCODE (ret):
case OPCODE (try_block):
case OPCODE (jmp_up):
case OPCODE (jmp_down):
case OPCODE (nop):
case OPCODE (reg_var_decl):
{
change_uid (om, lit_ids, 0x000);
break;
}
case OPCODE (meta):
{
switch (om->op.data.meta.type)
{
case OPCODE_META_TYPE_VARG_PROP_DATA:
case OPCODE_META_TYPE_VARG_PROP_GETTER:
case OPCODE_META_TYPE_VARG_PROP_SETTER:
{
change_uid (om, lit_ids, 0x011);
break;
}
case OPCODE_META_TYPE_THIS_ARG:
case OPCODE_META_TYPE_VARG:
case OPCODE_META_TYPE_CATCH_EXCEPTION_IDENTIFIER:
{
change_uid (om, lit_ids, 0x010);
break;
}
case OPCODE_META_TYPE_UNDEFINED:
case OPCODE_META_TYPE_END_WITH:
case OPCODE_META_TYPE_FUNCTION_END:
case OPCODE_META_TYPE_CATCH:
case OPCODE_META_TYPE_FINALLY:
case OPCODE_META_TYPE_END_TRY_CATCH_FINALLY:
case OPCODE_META_TYPE_STRICT_CODE:
{
change_uid (om, lit_ids, 0x000);
break;
}
}
break;
}
}
return om->op;
}
static idx_t
count_new_literals_in_opcode (scopes_tree tree, opcode_counter_t opc_index)
{
start_new_block_if_necessary ();
idx_t current_uid = next_uid;
op_meta *om = extract_op_meta (tree, opc_index);
switch (om->op.op_idx)
{
case OPCODE (prop_getter):
case OPCODE (prop_setter):
case OPCODE (delete_prop):
case OPCODE (b_shift_left):
case OPCODE (b_shift_right):
case OPCODE (b_shift_uright):
case OPCODE (b_and):
case OPCODE (b_or):
case OPCODE (b_xor):
case OPCODE (equal_value):
case OPCODE (not_equal_value):
case OPCODE (equal_value_type):
case OPCODE (not_equal_value_type):
case OPCODE (less_than):
case OPCODE (greater_than):
case OPCODE (less_or_equal_than):
case OPCODE (greater_or_equal_than):
case OPCODE (instanceof):
case OPCODE (in):
case OPCODE (addition):
case OPCODE (substraction):
case OPCODE (division):
case OPCODE (multiplication):
case OPCODE (remainder):
{
insert_uids_to_lit_id_map (om, 0x111);
break;
}
case OPCODE (call_n):
case OPCODE (native_call):
case OPCODE (construct_n):
case OPCODE (func_expr_n):
case OPCODE (delete_var):
case OPCODE (typeof):
case OPCODE (b_not):
case OPCODE (logical_not):
case OPCODE (post_incr):
case OPCODE (post_decr):
case OPCODE (pre_incr):
case OPCODE (pre_decr):
case OPCODE (unary_plus):
case OPCODE (unary_minus):
{
insert_uids_to_lit_id_map (om, 0x110);
break;
}
case OPCODE (assignment):
{
switch (om->op.data.assignment.type_value_right)
{
case OPCODE_ARG_TYPE_SIMPLE:
case OPCODE_ARG_TYPE_SMALLINT:
case OPCODE_ARG_TYPE_SMALLINT_NEGATE:
{
insert_uids_to_lit_id_map (om, 0x100);
break;
}
case OPCODE_ARG_TYPE_NUMBER:
case OPCODE_ARG_TYPE_NUMBER_NEGATE:
case OPCODE_ARG_TYPE_STRING:
case OPCODE_ARG_TYPE_VARIABLE:
{
insert_uids_to_lit_id_map (om, 0x101);
break;
}
}
break;
}
case OPCODE (func_decl_n):
case OPCODE (array_decl):
case OPCODE (obj_decl):
case OPCODE (this_binding):
case OPCODE (with):
case OPCODE (throw_value):
case OPCODE (is_true_jmp_up):
case OPCODE (is_true_jmp_down):
case OPCODE (is_false_jmp_up):
case OPCODE (is_false_jmp_down):
case OPCODE (var_decl):
case OPCODE (retval):
{
insert_uids_to_lit_id_map (om, 0x100);
break;
}
case OPCODE (exitval):
case OPCODE (ret):
case OPCODE (try_block):
case OPCODE (jmp_up):
case OPCODE (jmp_down):
case OPCODE (nop):
case OPCODE (reg_var_decl):
{
insert_uids_to_lit_id_map (om, 0x000);
break;
}
case OPCODE (meta):
{
switch (om->op.data.meta.type)
{
case OPCODE_META_TYPE_VARG_PROP_DATA:
case OPCODE_META_TYPE_VARG_PROP_GETTER:
case OPCODE_META_TYPE_VARG_PROP_SETTER:
{
insert_uids_to_lit_id_map (om, 0x011);
break;
}
case OPCODE_META_TYPE_THIS_ARG:
case OPCODE_META_TYPE_VARG:
case OPCODE_META_TYPE_CATCH_EXCEPTION_IDENTIFIER:
{
insert_uids_to_lit_id_map (om, 0x010);
break;
}
case OPCODE_META_TYPE_UNDEFINED:
case OPCODE_META_TYPE_END_WITH:
case OPCODE_META_TYPE_FUNCTION_END:
case OPCODE_META_TYPE_CATCH:
case OPCODE_META_TYPE_FINALLY:
case OPCODE_META_TYPE_END_TRY_CATCH_FINALLY:
case OPCODE_META_TYPE_STRICT_CODE:
{
insert_uids_to_lit_id_map (om, 0x000);
break;
}
}
break;
}
}
return (idx_t) (next_uid - current_uid);
}
/* Before filling literal indexes 'hash' table we shall initiate it with number of neccesary literal indexes.
Since bytecode is divided into blocks and id of the block is a part of hash key, we shall divide bytecode
into blocks and count unique literal indexes used in each block. */
size_t
scopes_tree_count_literals_in_blocks (scopes_tree tree)
{
assert_tree (tree);
size_t result = 0;
if (lit_id_to_uid != null_hash)
{
hash_table_free (lit_id_to_uid);
lit_id_to_uid = null_hash;
}
next_uid = 0;
global_oc = 0;
assert_tree (tree);
opcode_counter_t opc_index;
bool header = true;
for (opc_index = 0; opc_index < tree->opcodes_num; opc_index++)
{
op_meta *om = extract_op_meta (tree, opc_index);
if (om->op.op_idx != OPCODE (var_decl)
&& om->op.op_idx != OPCODE (meta) && !header)
{
break;
}
if (om->op.op_idx == OPCODE (reg_var_decl))
{
header = false;
}
result += count_new_literals_in_opcode (tree, opc_index);
}
for (uint8_t child_id = 0; child_id < tree->t.children_num; child_id++)
{
result += scopes_tree_count_literals_in_blocks (*(scopes_tree *) linked_list_element (tree->t.children, child_id));
}
for (; opc_index < tree->opcodes_num; opc_index++)
{
result += count_new_literals_in_opcode (tree, opc_index);
}
return result;
}
/* This function performs functions hoisting.
Each scope consists of four parts:
1) Header with 'use strict' marker and reg_var_decl opcode
2) Variable declarations, dumped by the preparser
3) Function declarations
4) Computational code
Header and var_decls are dumped first,
then we shall recursively dump function declaration,
and finally, other opcodes.
For each opcodes block (size of block is defined in bytecode-data.h)
literal indexes 'hash' table is filled. */
static void
merge_subscopes (scopes_tree tree, opcode_t *data, lit_id_hash_table *lit_ids)
{
assert_tree (tree);
JERRY_ASSERT (data);
opcode_counter_t opc_index;
bool header = true;
for (opc_index = 0; opc_index < tree->opcodes_num; opc_index++)
{
op_meta *om = extract_op_meta (tree, opc_index);
if (om->op.op_idx != OPCODE (var_decl)
&& om->op.op_idx != OPCODE (meta) && !header)
{
break;
}
if (om->op.op_idx == OPCODE (reg_var_decl))
{
header = false;
}
data[global_oc] = generate_opcode (tree, opc_index, lit_ids);
global_oc++;
}
for (uint8_t child_id = 0; child_id < tree->t.children_num; child_id++)
{
merge_subscopes (*(scopes_tree *) linked_list_element (tree->t.children, child_id),
data, lit_ids);
}
for (; opc_index < tree->opcodes_num; opc_index++)
{
data[global_oc] = generate_opcode (tree, opc_index, lit_ids);
global_oc++;
}
}
/* Postparser.
Init literal indexes 'hash' table.
Reorder function declarations.
Rewrite opcodes' temporary uids with their keys in literal indexes 'hash' table. */
opcode_t *
scopes_tree_raw_data (scopes_tree tree, lit_id_hash_table *lit_ids)
{
JERRY_ASSERT (lit_ids);
assert_tree (tree);
if (lit_id_to_uid != null_hash)
{
hash_table_free (lit_id_to_uid);
lit_id_to_uid = null_hash;
}
next_uid = 0;
global_oc = 0;
/* Dump bytecode and fill literal indexes 'hash' table. */
size_t size = ((size_t) (scopes_tree_count_opcodes (tree) + 1) * sizeof (opcode_t)); // +1 for valgrind
opcode_t *opcodes = (opcode_t *) mem_heap_alloc_block (size, MEM_HEAP_ALLOC_LONG_TERM);
memset (opcodes, 0, size);
merge_subscopes (tree, opcodes, lit_ids);
if (lit_id_to_uid != null_hash)
{
hash_table_free (lit_id_to_uid);
lit_id_to_uid = null_hash;
}
return opcodes;
}
void
scopes_tree_set_strict_mode (scopes_tree tree, bool strict_mode)
{
assert_tree (tree);
tree->strict_mode = strict_mode ? 1 : 0;
}
bool
scopes_tree_strict_mode (scopes_tree tree)
{
assert_tree (tree);
return (bool) tree->strict_mode;
}
scopes_tree
scopes_tree_init (scopes_tree parent)
{
scopes_tree tree = (scopes_tree) mem_heap_alloc_block (sizeof (scopes_tree_int), MEM_HEAP_ALLOC_SHORT_TERM);
memset (tree, 0, sizeof (scopes_tree_int));
tree->t.magic = TREE_MAGIC;
tree->t.parent = (tree_header *) parent;
tree->t.children = null_list;
tree->t.children_num = 0;
if (parent != NULL)
{
if (parent->t.children_num == 0)
{
parent->t.children = linked_list_init (sizeof (scopes_tree));
}
linked_list_set_element (parent->t.children, parent->t.children_num, &tree);
void *added = linked_list_element (parent->t.children, parent->t.children_num);
JERRY_ASSERT (*(scopes_tree *) added == tree);
parent->t.children_num++;
}
tree->opcodes_num = 0;
tree->strict_mode = 0;
tree->opcodes = linked_list_init (sizeof (op_meta));
return tree;
}
void
scopes_tree_free (scopes_tree tree)
{
assert_tree (tree);
if (tree->t.children_num != 0)
{
for (uint8_t i = 0; i < tree->t.children_num; ++i)
{
scopes_tree_free (*(scopes_tree *) linked_list_element (tree->t.children, i));
}
linked_list_free (tree->t.children);
}
linked_list_free (tree->opcodes);
mem_heap_free_block ((uint8_t *) tree);
}
+60
View File
@@ -0,0 +1,60 @@
/* Copyright 2014 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.
*/
#ifndef SCOPES_TREE_H
#define SCOPES_TREE_H
#include "tree.h"
#include "linked-list.h"
#include "lexer.h"
#include "ecma-globals.h"
#include "hash-table.h"
#include "opcodes.h"
#include "lit-id-hash-table.h"
#define NOT_A_LITERAL (INVALID_LITERAL - 1)
typedef struct
{
literal_index_t lit_id[3];
opcode_t op;
}
op_meta;
typedef struct
{
tree_header t;
linked_list opcodes;
opcode_counter_t opcodes_num;
unsigned strict_mode:1;
}
scopes_tree_int;
typedef scopes_tree_int * scopes_tree;
scopes_tree scopes_tree_init (scopes_tree);
void scopes_tree_free (scopes_tree);
opcode_counter_t scopes_tree_opcodes_num (scopes_tree);
void scopes_tree_add_op_meta (scopes_tree, op_meta);
void scopes_tree_set_op_meta (scopes_tree, opcode_counter_t, op_meta);
void scopes_tree_set_opcodes_num (scopes_tree, opcode_counter_t);
op_meta scopes_tree_op_meta (scopes_tree, opcode_counter_t);
size_t scopes_tree_count_literals_in_blocks (scopes_tree);
opcode_counter_t scopes_tree_count_opcodes (scopes_tree);
opcode_t *scopes_tree_raw_data (scopes_tree, lit_id_hash_table *);
void scopes_tree_set_strict_mode (scopes_tree, bool);
bool scopes_tree_strict_mode (scopes_tree);
#endif /* SCOPES_TREE_H */
+143
View File
@@ -0,0 +1,143 @@
/* Copyright 2014-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 "jrt.h"
#include "serializer.h"
#include "parser.h"
#include "jrt-libc-includes.h"
#include "bytecode-data.h"
#include "deserializer.h"
#include "pretty-printer.h"
bytecode_data_t bytecode_data;
scopes_tree current_scope;
static bool print_opcodes;
void
serializer_set_scope (scopes_tree new_scope)
{
current_scope = new_scope;
}
void
serializer_merge_scopes_into_bytecode (void)
{
JERRY_ASSERT (bytecode_data.lit_id_hash == null_hash);
bytecode_data.opcodes_count = scopes_tree_count_opcodes (current_scope);
bytecode_data.lit_id_hash = lit_id_hash_table_init (scopes_tree_count_literals_in_blocks (current_scope),
bytecode_data.opcodes_count);
bytecode_data.opcodes = scopes_tree_raw_data (current_scope, bytecode_data.lit_id_hash);
}
void
serializer_dump_literals (const literal literals[], literal_index_t literals_count)
{
#ifdef JERRY_ENABLE_PRETTY_PRINTER
if (print_opcodes)
{
pp_literals (literals, literals_count);
}
#endif
bytecode_data.literals_count = literals_count;
bytecode_data.literals = literals;
}
void
serializer_dump_op_meta (op_meta op)
{
JERRY_ASSERT (scopes_tree_opcodes_num (current_scope) < MAX_OPCODES);
scopes_tree_add_op_meta (current_scope, op);
#ifdef JERRY_ENABLE_PRETTY_PRINTER
if (print_opcodes)
{
pp_op_meta ((opcode_counter_t) (scopes_tree_opcodes_num (current_scope) - 1), op, false);
}
#endif
}
opcode_counter_t
serializer_get_current_opcode_counter (void)
{
return scopes_tree_opcodes_num (current_scope);
}
opcode_counter_t
serializer_count_opcodes_in_subscopes (void)
{
return (opcode_counter_t) (scopes_tree_count_opcodes (current_scope) - scopes_tree_opcodes_num (current_scope));
}
void
serializer_set_writing_position (opcode_counter_t oc)
{
scopes_tree_set_opcodes_num (current_scope, oc);
}
void
serializer_rewrite_op_meta (const opcode_counter_t loc, op_meta op)
{
scopes_tree_set_op_meta (current_scope, loc, op);
#ifdef JERRY_ENABLE_PRETTY_PRINTER
if (print_opcodes)
{
pp_op_meta (loc, op, true);
}
#endif
}
void
serializer_print_opcodes (void)
{
#ifdef JERRY_ENABLE_PRETTY_PRINTER
opcode_counter_t loc;
if (!print_opcodes)
{
return;
}
printf ("AFTER OPTIMIZER:\n");
for (loc = 0; loc < bytecode_data.opcodes_count; loc++)
{
op_meta opm;
opm.op = bytecode_data.opcodes[loc];
for (int i = 0; i < 3; i++)
{
opm.lit_id [i] = NOT_A_LITERAL;
}
pp_op_meta (loc, opm, false);
}
#endif
}
void
serializer_init (bool show_opcodes)
{
current_scope = NULL;
print_opcodes = show_opcodes;
}
void
serializer_free (void)
{
}
+38
View File
@@ -0,0 +1,38 @@
/* Copyright 2014-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.
*/
#ifndef SERIALIZER_H
#define SERIALIZER_H
#include "jrt.h"
#include "ecma-globals.h"
#include "opcodes.h"
#include "vm.h"
#include "literal.h"
#include "scopes-tree.h"
void serializer_init (bool show_opcodes);
void serializer_dump_literals (const literal *, literal_index_t);
void serializer_set_scope (scopes_tree);
void serializer_merge_scopes_into_bytecode (void);
void serializer_dump_op_meta (op_meta);
opcode_counter_t serializer_get_current_opcode_counter (void);
opcode_counter_t serializer_count_opcodes_in_subscopes (void);
void serializer_set_writing_position (opcode_counter_t);
void serializer_rewrite_op_meta (opcode_counter_t, op_meta);
void serializer_print_opcodes (void);
void serializer_free (void);
#endif // SERIALIZER_H
+224
View File
@@ -0,0 +1,224 @@
/* Copyright 2014-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 "syntax-errors.h"
#include "stack.h"
#include "jrt.h"
#include "parser.h"
#include "jrt-libc-includes.h"
#include "ecma-helpers.h"
typedef struct
{
prop_type type;
literal lit;
}
prop_literal;
enum
{
props_global_size
};
STATIC_STACK (props, prop_literal)
enum
{
U8_global_size
};
STATIC_STACK (U8, uint8_t)
static prop_literal
create_prop_literal (literal lit, prop_type type)
{
prop_literal ret;
ret.type = type;
ret.lit = lit;
return ret;
}
void
syntax_start_checking_of_prop_names (void)
{
STACK_PUSH (U8, (uint8_t) STACK_SIZE (props));
}
void
syntax_add_prop_name (operand op, prop_type pt)
{
JERRY_ASSERT (op.type == OPERAND_LITERAL);
STACK_PUSH (props, create_prop_literal (lexer_get_literal_by_id (op.data.lit_id), pt));
}
void
syntax_check_for_duplication_of_prop_names (bool is_strict, locus loc __attr_unused___)
{
if (STACK_SIZE (props) - STACK_TOP (U8) < 2)
{
STACK_DROP (U8, 1);
return;
}
for (uint8_t i = (uint8_t) (STACK_TOP (U8) + 1);
i < STACK_SIZE (props);
i++)
{
const prop_literal previous = STACK_ELEMENT (props, i);
if (previous.type == VARG)
{
continue;
}
JERRY_ASSERT (previous.type == PROP_DATA
|| previous.type == PROP_GET
|| previous.type == PROP_SET);
for (uint8_t j = STACK_TOP (U8); j < i; j = (uint8_t) (j + 1))
{
/*4*/
const prop_literal current = STACK_ELEMENT (props, j);
if (current.type == VARG)
{
continue;
}
JERRY_ASSERT (current.type == PROP_DATA
|| current.type == PROP_GET
|| current.type == PROP_SET);
if (literal_equal (previous.lit, current.lit))
{
/*a*/
if (is_strict && previous.type == PROP_DATA && current.type == PROP_DATA)
{
PARSE_ERROR_VARG ("Duplication of parameter name '%s' in ObjectDeclaration is not allowed in strict mode",
loc, (const char *) literal_to_zt (current.lit));
}
/*b*/
if (previous.type == PROP_DATA
&& (current.type == PROP_SET || current.type == PROP_GET))
{
PARSE_ERROR_VARG ("Parameter name '%s' in ObjectDeclaration may not be both data and accessor",
loc, (const char *) literal_to_zt (current.lit));
}
/*c*/
if (current.type == PROP_DATA
&& (previous.type == PROP_SET || previous.type == PROP_GET))
{
PARSE_ERROR_VARG ("Parameter name '%s' in ObjectDeclaration may not be both data and accessor",
loc, (const char *) literal_to_zt (current.lit));
}
/*d*/
if ((previous.type == PROP_SET && current.type == PROP_SET)
|| (previous.type == PROP_GET && current.type == PROP_GET))
{
PARSE_ERROR_VARG ("Parameter name '%s' in ObjectDeclaration may not be accessor of same type",
loc, (const char *) literal_to_zt (current.lit));
}
}
}
}
STACK_DROP (props, (uint8_t) (STACK_SIZE (props) - STACK_TOP (U8)));
STACK_DROP (U8, 1);
}
void
syntax_start_checking_of_vargs (void)
{
STACK_PUSH (U8, (uint8_t) STACK_SIZE (props));
}
void syntax_add_varg (operand op)
{
JERRY_ASSERT (op.type == OPERAND_LITERAL);
STACK_PUSH (props, create_prop_literal (lexer_get_literal_by_id (op.data.lit_id), VARG));
}
static void
emit_error_on_eval_and_arguments (operand op, locus loc __attr_unused___)
{
if (op.type == OPERAND_LITERAL)
{
if (literal_equal_type_zt (lexer_get_literal_by_id (op.data.lit_id),
ecma_get_magic_string_zt (ECMA_MAGIC_STRING_ARGUMENTS))
|| literal_equal_type_zt (lexer_get_literal_by_id (op.data.lit_id),
ecma_get_magic_string_zt (ECMA_MAGIC_STRING_EVAL)))
{
PARSE_ERROR ("'eval' and 'arguments' are not allowed here in strict mode", loc);
}
}
}
void
syntax_check_for_eval_and_arguments_in_strict_mode (operand op, bool is_strict, locus loc)
{
if (is_strict)
{
emit_error_on_eval_and_arguments (op, loc);
}
}
/* 13.1, 15.3.2 */
void
syntax_check_for_syntax_errors_in_formal_param_list (bool is_strict, locus loc __attr_unused___)
{
if (STACK_SIZE (props) - STACK_TOP (U8) < 2 || !is_strict)
{
STACK_DROP (U8, 1);
return;
}
for (uint8_t i = (uint8_t) (STACK_TOP (U8) + 1); i < STACK_SIZE (props); i = (uint8_t) (i + 1))
{
JERRY_ASSERT (STACK_ELEMENT (props, i).type == VARG);
const literal previous = STACK_ELEMENT (props, i).lit;
JERRY_ASSERT (previous.type == LIT_STR || previous.type == LIT_MAGIC_STR);
for (uint8_t j = STACK_TOP (U8); j < i; j = (uint8_t) (j + 1))
{
JERRY_ASSERT (STACK_ELEMENT (props, j).type == VARG);
const literal current = STACK_ELEMENT (props, j).lit;
JERRY_ASSERT (current.type == LIT_STR || current.type == LIT_MAGIC_STR);
if (literal_equal_type (previous, current))
{
PARSE_ERROR_VARG ("Duplication of literal '%s' in FormalParameterList is not allowed in strict mode",
loc, (const char *) literal_to_zt (previous));
}
}
}
STACK_DROP (props, (uint8_t) (STACK_SIZE (props) - STACK_TOP (U8)));
STACK_DROP (U8, 1);
}
void
syntax_check_delete (bool is_strict, locus loc __attr_unused___)
{
if (is_strict)
{
PARSE_ERROR ("'delete' operator shall not apply on identifier in strict mode.", loc);
}
}
void
syntax_init (void)
{
STACK_INIT (props);
STACK_INIT (U8);
}
void
syntax_free (void)
{
STACK_FREE (U8);
STACK_FREE (props);
}
+104
View File
@@ -0,0 +1,104 @@
/* Copyright 2014-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.
*/
#ifndef SYNTAX_ERRORS_H
#define SYNTAX_ERRORS_H
#include "literal.h"
#include "opcodes-dumper.h"
#include "lexer.h"
#ifndef JERRY_NDEBUG
#define PARSE_ERROR(MESSAGE, LOCUS) do { \
size_t line, column; \
lexer_locus_to_line_and_column ((locus) (LOCUS), &line, &column); \
lexer_dump_line (line); \
printf ("\n"); \
for (size_t i = 0; i < column; i++) { \
putchar (' '); \
} \
printf ("^\n"); \
printf ("ERROR: Ln %lu, Col %lu: %s\n", (unsigned long) (line + 1), (unsigned long) (column + 1), MESSAGE); \
jerry_fatal (ERR_PARSER); \
} while (0)
#define PARSE_WARN(MESSAGE, LOCUS) do { \
size_t line, column; \
lexer_locus_to_line_and_column ((locus) (LOCUS), &line, &column); \
printf ("WARNING: Ln %lu, Col %lu: %s\n", (unsigned long) (line + 1), (unsigned long) (column + 1), MESSAGE); \
} while (0)
#define PARSE_ERROR_VARG(MESSAGE, LOCUS, ...) do { \
size_t line, column; \
lexer_locus_to_line_and_column ((locus) (LOCUS), &line, &column); \
lexer_dump_line (line); \
printf ("\n"); \
for (size_t i = 0; i < column; i++) { \
putchar (' '); \
} \
printf ("^\n"); \
printf ("ERROR: Ln %lu, Col %lu: ", (unsigned long) (line + 1), (unsigned long) (column + 1)); \
printf (MESSAGE, __VA_ARGS__); \
printf ("\n"); \
jerry_fatal (ERR_PARSER); \
} while (0)
#define PARSE_SORRY(MESSAGE, LOCUS) do { \
size_t line, column; \
lexer_locus_to_line_and_column ((locus) (LOCUS), &line, &column); \
lexer_dump_line (line); \
printf ("\n"); \
for (size_t i = 0; i < column; i++) { \
putchar (' '); \
} \
printf ("^\n"); \
printf ("SORRY, Unimplemented: Ln %lu, Col %lu: %s\n", (unsigned long) (line + 1), (unsigned long) (column + 1), MESSAGE); \
JERRY_UNIMPLEMENTED ("Unimplemented parser feature."); \
} while (0)
#else /* JERRY_NDEBUG */
#define PARSE_ERROR(MESSAGE, LOCUS) do { \
jerry_fatal (ERR_PARSER); \
} while (0)
#define PARSE_WARN(MESSAGE, LOCUS) do { \
} while (0)
#define PARSE_ERROR_VARG(MESSAGE, LOCUS, ...) do { \
jerry_fatal (ERR_PARSER); \
} while (0)
#define PARSE_SORRY(MESSAGE, LOCUS) do { \
JERRY_UNIMPLEMENTED ("Unimplemented parser feature."); \
} while (0)
#endif /* JERRY_NDEBUG */
typedef enum
{
PROP_DATA,
PROP_SET,
PROP_GET,
VARG
}
prop_type;
void syntax_init (void);
void syntax_free (void);
void syntax_start_checking_of_prop_names (void);
void syntax_add_prop_name (operand, prop_type);
void syntax_check_for_duplication_of_prop_names (bool, locus);
void syntax_start_checking_of_vargs (void);
void syntax_add_varg (operand);
void syntax_check_for_eval_and_arguments_in_strict_mode (operand, bool, locus);
void syntax_check_for_syntax_errors_in_formal_param_list (bool, locus);
void syntax_check_delete (bool, locus);
#endif /* SYNTAX_ERRORS_H */