Renaming core -> jerry-core.
This commit is contained in:
@@ -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 */
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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 */
|
||||
@@ -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 */
|
||||
@@ -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 */
|
||||
@@ -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
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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
@@ -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
|
||||
@@ -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 ();
|
||||
}
|
||||
}
|
||||
@@ -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
@@ -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
@@ -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
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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 */
|
||||
@@ -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)
|
||||
{
|
||||
}
|
||||
@@ -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
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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 */
|
||||
Reference in New Issue
Block a user