Simplify serializer/deserializer. Reduce memory usage in lexer. Create HashTable data structure. Finish preparations for introducing new strings addressation.

This commit is contained in:
Ilmir Usmanov
2014-09-23 16:39:30 +04:00
parent f237a8d5e1
commit 8a5b956e38
27 changed files with 1152 additions and 1159 deletions
+3 -2
View File
@@ -273,8 +273,9 @@ SOURCES_JERRY_C = \
$(wildcard ./src/libecmabuiltins/*.c) \
$(wildcard ./src/liballocator/*.c) \
$(wildcard ./src/libcoreint/*.c) \
$(wildcard ./src/liboptimizer/*.c) ) \
$(wildcard ./src/libruntime/target/$(TARGET_SYSTEM)/*.c)
$(wildcard ./src/libintstructs/*.c) \
$(wildcard ./src/liboptimizer/*.c ) \
$(wildcard ./src/libruntime/target/$(TARGET_SYSTEM)/*.c) )
SOURCES_JERRY_H = \
$(sort \
+1 -1
View File
@@ -55,7 +55,7 @@
/**
* Size of heap
*/
#define CONFIG_MEM_HEAP_AREA_SIZE (4 * 1024 + 512)
#define CONFIG_MEM_HEAP_AREA_SIZE (5 * 1024 + 512)
/**
* Log2 of maximum possible offset in the heap
+56
View File
@@ -0,0 +1,56 @@
/* 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 "lp-string.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)
{
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;
}
+33
View File
@@ -0,0 +1,33 @@
/* 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
{
ecma_length_t length;
const ecma_char_t *str;
}
__packed
lp_string;
bool lp_string_equal (lp_string, lp_string);
bool lp_string_equal_s (lp_string, const char *);
#endif /* LP_STRING */
+64 -50
View File
@@ -15,22 +15,16 @@
/**
This file contains macros to define and use stacks.
Do define stack type use macro DEFINE_STACK_TYPE.
After definition of type use macro STACK to create stack variable and define all necessaty routines.
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 PUSH and POP operations.
Before using the stack, init it by calling INIT_STACK macro.
Use macros PUSH, POP, DROP, CLEAN and HEAD to manipulate the stack.
DO NOT FORGET to free stack memory by calling FREE_STACK macro.
For check usage of stack during a function, use DECLARE_USAGE and CHECK_USAGE macros.
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.
Example (parser.c):
#ifndef UINT8_T_STACK_DEFINED
#define UINT8_T_STACK_DEFINED
DEFINE_STACK_TYPE (uint8_t)
#endif
enum
{
temp_name,
@@ -38,7 +32,7 @@
max_temp_name,
temp_names_global_size
};
STACK(uint8_t, temp_names)
STACK(temp_names, uint8_t, uint8_t)
#define GLOBAL(NAME, VAR) \
NAME.data[VAR]
@@ -55,19 +49,19 @@
void
parser_init (void)
{
INIT_STACK(uint8_t, temp_names)
STACK_INIT(uint8_t, temp_names)
}
void
parser_free (void)
{
FREE_STACK(temp_names)
STACK_FREE(temp_names)
}
*/
#ifndef STACK_H
#define STACK_H
#define DEFINE_STACK_TYPE(DATA_TYPE, TYPE) \
#define DEFINE_STACK_TYPE(NAME, DATA_TYPE, TYPE) \
typedef struct \
{ \
DATA_TYPE length; \
@@ -75,20 +69,20 @@ typedef struct \
TYPE *data; \
} \
__packed \
TYPE##_stack;
NAME##_stack;
#define INIT_STACK(TYPE, NAME) \
#define STACK_INIT(TYPE, NAME) \
do { \
size_t NAME##_size = mem_heap_recommend_allocation_size (sizeof (TYPE) * NAME##_global_size); \
NAME.data = (TYPE *) mem_heap_alloc_block (NAME##_size, MEM_HEAP_ALLOC_SHORT_TERM); \
NAME.current = NAME##_global_size; \
NAME.length = (__typeof__ (NAME.length)) (NAME##_size / sizeof (TYPE)); \
size_t stack_size = mem_heap_recommend_allocation_size (sizeof (TYPE) * NAME##_global_size); \
NAME.data = (TYPE *) mem_heap_alloc_block (stack_size, MEM_HEAP_ALLOC_SHORT_TERM); \
NAME.current = NAME##_global_size; \
NAME.length = (__typeof__ (NAME.length)) (stack_size / sizeof (TYPE)); \
} while (0)
#define FREE_STACK(NAME) \
#define STACK_FREE(NAME) \
do { \
mem_heap_free_block ((uint8_t *) NAME.data); \
NAME.length = NAME.current = 0; \
mem_heap_free_block ((uint8_t *) NAME.data); \
NAME.length = NAME.current = 0; \
} while (0)
/* In most cases (for example, in parser) default size of stack is enough.
@@ -100,7 +94,7 @@ NAME.length = NAME.current = 0; \
4) Allocate new memory. (It must point to the memory before increasing).
5) Copy data back.
6) Free temp buffer. */
#define DEFINE_INCREASE_STACK_SIZE(TYPE, NAME) \
#define DEFINE_INCREASE_STACK_SIZE(NAME, TYPE) \
static void increase_##NAME##_stack_size (__typeof__ (NAME.length)) __unused; \
static void \
increase_##NAME##_stack_size (__typeof__ (NAME.length) elements_count) { \
@@ -122,6 +116,12 @@ increase_##NAME##_stack_size (__typeof__ (NAME.length) elements_count) { \
mem_heap_free_block ((uint8_t *) NAME.data); \
mem_heap_free_block ((uint8_t *) temp1); \
NAME.data = (TYPE *) mem_heap_alloc_block (new_size, MEM_HEAP_ALLOC_SHORT_TERM); \
if (NAME.data == NULL) \
{ \
__printf ("old_size: %d\ntemp1_size: %d\nnew_size: %d\n", old_size, temp1_size, new_size); \
mem_heap_print (true, false, true); \
JERRY_UNREACHABLE (); \
} \
__memcpy (NAME.data, temp2, old_size); \
mem_heap_free_block ((uint8_t *) temp2); \
NAME.length = (__typeof__ (NAME.length)) (new_size / sizeof (TYPE)); \
@@ -137,44 +137,58 @@ decrease_##NAME##_stack_size (uint8_t elements_count) { \
NAME.current = (__typeof__ (NAME.current)) (NAME.current - elements_count); \
}
#define PUSH(NAME, VALUE) \
increase_##NAME##_stack_size (1); \
NAME.data[NAME.current - 1] = VALUE;
#define STACK_PUSH(NAME, VALUE) \
do { \
increase_##NAME##_stack_size (1); \
NAME.data[NAME.current - 1] = VALUE; \
} while (0)
#define POP(VALUE, NAME) \
decrease_##NAME##_stack_size (1); \
VALUE = NAME.data[NAME.current];
#define STACK_POP(NAME, VALUE) \
do { \
decrease_##NAME##_stack_size (1); \
VALUE = NAME.data[NAME.current]; \
} while (0)
#define DROP(NAME, I) \
decrease_##NAME##_stack_size (I);
#define STACK_DROP(NAME, I) \
do { decrease_##NAME##_stack_size (I); } while (0)
#define CLEAN(NAME) \
DROP (NAME, NAME.current - NAME##_global_size);
#define STACK_CLEAN(NAME) \
STACK_DROP (NAME, NAME.current - NAME##_global_size);
#define HEAD(NAME, I) \
#define STACK_HEAD(NAME, I) \
NAME.data[NAME.current - I]
#define STACK_SIZE(NAME) \
NAME.current
#define STACK(TYPE, NAME) \
TYPE##_stack NAME; \
DEFINE_DECREASE_STACE_SIZE (NAME) \
DEFINE_INCREASE_STACK_SIZE (TYPE, NAME)
#define STACK_ELEMENT(NAME, I) \
NAME.data[I]
#define STATIC_STACK(TYPE, NAME) \
static TYPE##_stack NAME; \
#define STACK_RAW_DATA(NAME) \
NAME.data
#define STACK(NAME, DATA_TYPE, TYPE) \
DEFINE_STACK_TYPE(NAME, DATA_TYPE, TYPE) \
NAME##_stack NAME; \
DEFINE_DECREASE_STACE_SIZE (NAME) \
DEFINE_INCREASE_STACK_SIZE (TYPE, NAME)
DEFINE_INCREASE_STACK_SIZE (NAME, TYPE)
#define STATIC_STACK(NAME, DATA_TYPE, TYPE) \
DEFINE_STACK_TYPE(NAME, DATA_TYPE, TYPE) \
static NAME##_stack NAME; \
DEFINE_DECREASE_STACE_SIZE (NAME) \
DEFINE_INCREASE_STACK_SIZE (NAME, TYPE)
#ifndef JERRY_NDEBUG
#define DECLARE_USAGE(NAME) \
uint8_t NAME##_current = NAME.current;
#define CHECK_USAGE(NAME) \
JERRY_ASSERT (NAME.current == NAME##_current);
#define STACK_DECLARE_USAGE(NAME) \
__typeof__(NAME.current) NAME##_current = NAME.current;
#define STACK_CHECK_USAGE(NAME) \
do { \
JERRY_ASSERT (NAME.current == NAME##_current); \
} while (0);
#else
#define DECLARE_USAGE(NAME) ;
#define CHECK_USAGE(NAME) ;
#define STACK_DECLARE_USAGE(NAME) ;
#define STACK_CHECK_USAGE(NAME) ;
#endif /* JERRY_NDEBUG */
#endif /* STACK_H */
+122 -288
View File
@@ -17,31 +17,43 @@
#include "jerry-libc.h"
#include "lexer.h"
#include "parser.h"
#include "stack.h"
#include "opcodes.h"
static token saved_token;
static token empty_token =
{
.type =
TOK_EMPTY,
.type = TOK_EMPTY,
.uid = 0
};
static bool allow_dump_lines = false;
static size_t buffer_size = 0;
typedef struct
/* Represents the contents of a script. */
static const char *buffer_start = NULL;
static const char *buffer = NULL;
static const char *token_start;
#define LA(I) (get_char (I))
enum
{
ecma_number_t num;
token tok;
}
num_and_token;
strings_global_size
};
STATIC_STACK (strings, uint8_t, lp_string)
#define MAX_NUMS 25
enum
{
numbers_global_size
};
STATIC_STACK (numbers, uint8_t, ecma_number_t)
static uint8_t seen_names_count = 0;
static num_and_token seen_nums[MAX_NUMS];
static uint8_t seen_nums_count = 0;
enum
{
num_ids_global_size
};
STATIC_STACK (num_ids, uint8_t, idx_t)
static bool
is_empty (token tok)
@@ -49,11 +61,6 @@ is_empty (token tok)
return tok.type == TOK_EMPTY;
}
/* Represents the contents of a script. */
static const char *buffer_start = NULL;
static const char *buffer = NULL;
static const char *token_start;
static char
get_char (size_t i)
{
@@ -64,44 +71,6 @@ get_char (size_t i)
return *(buffer + i);
}
#define LA(I) (get_char (I))
/* Continuous array of NULL-terminated strings. */
static char *strings_cache = NULL;
static size_t strings_cache_size = 0;
static void
increase_strings_cache (void)
{
char *new_cache;
size_t new_cache_size;
// if strings_cache_size == 0, allocator recommends minimum size that is more than 0
new_cache_size = mem_heap_recommend_allocation_size (strings_cache_size * 2);
new_cache = (char *) mem_heap_alloc_block (new_cache_size, MEM_HEAP_ALLOC_SHORT_TERM);
if (!new_cache)
{
// Allocator alligns recommended memory size
new_cache_size = mem_heap_recommend_allocation_size (strings_cache_size + 1);
new_cache = (char *) mem_heap_alloc_block (new_cache_size, MEM_HEAP_ALLOC_SHORT_TERM);
if (!new_cache)
{
parser_fatal (ERR_MEMORY);
}
}
if (strings_cache)
{
__memcpy (new_cache, strings_cache, strings_cache_size);
mem_heap_free_block ((uint8_t *) strings_cache);
}
strings_cache = new_cache;
strings_cache_size = new_cache_size;
}
#ifdef __TARGET_HOST_x64
static void
dump_current_line (void)
@@ -137,6 +106,20 @@ current_token_equals_to (const char *str)
return false;
}
static bool
current_token_equals_to_lp (lp_string str)
{
if (str.length != (ecma_length_t) (buffer - token_start))
{
return false;
}
if (!__strncmp ((const char *) str.str, token_start, str.length))
{
return true;
}
return false;
}
/* If TOKEN represents a keyword, return decoded keyword,
if TOKEN represents a Future Reserved Word, return KW_RESERVED,
otherwise return KW_NONE. */
@@ -507,171 +490,121 @@ decode_keyword (void)
}
static token
convert_seen_name_to_token (token_type tt, const char *string)
convert_current_token_to_token (token_type tt)
{
uint8_t i;
char *current_string = strings_cache;
JERRY_ASSERT (strings_cache);
token ret_val = empty_token;
JERRY_ASSERT (token_start);
for (i = 0; i < seen_names_count; i++)
for (uint8_t i = 0; i < STACK_SIZE (strings); i++)
{
if ((string == NULL && current_token_equals_to (current_string))
|| (string != NULL && !__strcmp (current_string, string)))
if (current_token_equals_to_lp (strings.data[i]))
{
ret_val = (token)
return (token)
{
.type = tt,
.uid = i
};
break;
}
current_string += __strlen (current_string) + 1;
}
return ret_val;
}
static token
add_token_to_seen_names (token_type tt, const char *string)
{
size_t i;
char *current_string = strings_cache;
size_t required_size;
size_t len = (string == NULL ? (size_t) (buffer - token_start) : __strlen (string));
token ret_val = empty_token;
// Go to unused memory of cache
for (i = 0; i < seen_names_count; i++)
const lp_string str = (lp_string)
{
current_string += __strlen (current_string) + 1;
}
required_size = (size_t) (current_string - strings_cache) + len + 1;
if (required_size > strings_cache_size)
{
size_t offset = (size_t) (current_string - strings_cache);
increase_strings_cache ();
// Now our pointer are invalid, adjust it
current_string = strings_cache + offset;
}
if (string == NULL)
{
// Copy current token with terminating NULL
__strncpy (current_string, token_start, (size_t) (buffer - token_start));
current_string += buffer - token_start;
*current_string = '\0';
}
else
{
__memcpy (current_string, string, __strlen (string) + 1);
}
ret_val = (token)
{
.type = tt,
.uid = seen_names_count++
.length = (uint8_t) (buffer - token_start),
.str = (const ecma_char_t *) token_start
};
return ret_val;
STACK_PUSH (strings, str);
return (token)
{
.type = tt,
.uid = (idx_t) (STACK_SIZE (strings) - 1)
};
}
static token
convert_seen_num_to_token (ecma_number_t num)
{
size_t i;
uint8_t num_id;
for (i = 0; i < seen_nums_count; i++)
JERRY_ASSERT (STACK_SIZE (num_ids) == STACK_SIZE (numbers));
for (uint8_t i = 0; i < STACK_SIZE (numbers); i++)
{
// token must be exactly the same as seen
if (seen_nums[i].num == num)
if (numbers.data[i] == num)
{
return seen_nums[i].tok;
return (token)
{
.type = TOK_NUMBER,
.uid = num_ids.data[i]
};
}
}
return empty_token;
num_id = STACK_SIZE (num_ids);
STACK_PUSH (num_ids, num_id);
STACK_PUSH (numbers, num);
return (token)
{
.type = TOK_NUMBER,
.uid = num_id
};
}
static void
add_num_to_seen_tokens (num_and_token nat)
const lp_string *
lexer_get_strings (void)
{
JERRY_ASSERT (seen_nums_count < MAX_NUMS);
seen_nums[seen_nums_count++] = nat;
return STACK_RAW_DATA (strings);
}
uint8_t
lexer_get_strings (const char **strings)
lexer_get_strings_count (void)
{
if (strings)
{
char *current_string = strings_cache;
int i;
for (i = 0; i < seen_names_count; i++)
{
strings[i] = current_string;
current_string += __strlen (current_string) + 1;
}
}
return seen_names_count;
return STACK_SIZE (strings);
}
uint8_t
lexer_get_reserved_ids_count (void)
{
return (uint8_t) (seen_names_count + seen_nums_count);
return (uint8_t) (STACK_SIZE (strings) + STACK_SIZE (numbers));
}
const char *
lp_string
lexer_get_string_by_id (uint8_t id)
{
int i;
char *current_string = strings_cache;
JERRY_ASSERT (id < seen_names_count);
JERRY_ASSERT (id < STACK_SIZE (strings));
return STACK_ELEMENT (strings, id);
}
for (i = 0 ; i < id; i++)
{
current_string += __strlen (current_string) + 1;
}
return current_string;
const ecma_number_t *
lexer_get_nums (void)
{
return STACK_RAW_DATA (numbers);
}
uint8_t
lexer_get_nums (ecma_number_t *nums)
lexer_get_nums_count (void)
{
int i;
if (!nums)
{
return seen_nums_count;
}
for (i = 0; i < seen_nums_count; i++)
{
nums[i] = seen_nums[i].num;
}
return seen_nums_count;
return STACK_SIZE (numbers);
}
void
lexer_adjust_num_ids (void)
{
size_t i;
for (i = 0; i < seen_nums_count; i++)
JERRY_ASSERT (STACK_SIZE (numbers) == STACK_SIZE (num_ids));
for (uint8_t i = 0; i < STACK_SIZE (numbers); i++)
{
seen_nums[i].tok.uid = (uint8_t) (seen_nums[i].tok.uid + seen_names_count);
STACK_ELEMENT (num_ids, i) = (uint8_t) (STACK_ELEMENT (num_ids, i) + STACK_SIZE (strings));
}
}
ecma_number_t
lexer_get_num_by_id (uint8_t id)
{
JERRY_ASSERT (id >= lexer_get_strings_count () && id < lexer_get_reserved_ids_count ());
JERRY_ASSERT (STACK_ELEMENT (num_ids, id - lexer_get_strings_count ()) == id);
return STACK_ELEMENT (numbers, id - lexer_get_strings_count ());
}
static void
new_token (void)
{
@@ -773,20 +706,14 @@ parse_name (void)
}
}
known_token = convert_seen_name_to_token (TOK_NAME, NULL);
if (!is_empty (known_token))
{
goto end;
}
known_token = add_token_to_seen_names (TOK_NAME, NULL);
known_token = convert_current_token_to_token (TOK_NAME);
end:
token_start = NULL;
return known_token;
}
static int32_t
static uint32_t
hex_to_int (char hex)
{
switch (hex)
@@ -827,7 +754,7 @@ parse_number (void)
bool is_fp = false;
bool is_exp = false;
size_t tok_length = 0, i;
int32_t res = 0;
uint32_t res = 0;
token known_token;
JERRY_ASSERT (__isdigit (c) || c == '.');
@@ -868,10 +795,17 @@ parse_number (void)
}
tok_length = (size_t) (buffer - token_start);
// OK, I know that integer overflow can occur here
for (i = 0; i < tok_length; i++)
{
#ifndef JERRY_NDEBUG
uint32_t old_res = res;
#endif
res = (res << 4) + hex_to_int (token_start[i]);
FIXME (Replace with conversion to ecma_number_t)
#ifndef JERRY_NDEBUG
JERRY_ASSERT (old_res <= res);
#endif
}
token_start = NULL;
@@ -886,23 +820,8 @@ parse_number (void)
}
known_token = convert_seen_num_to_token ((ecma_number_t) res);
if (!is_empty (known_token))
{
return known_token;
}
JERRY_ASSERT (!is_empty (known_token));
known_token = (token)
{
.type = TOK_NUMBER,
.uid = seen_nums_count
};
add_num_to_seen_tokens (
(num_and_token)
{
.num = (ecma_number_t) res,
.tok = known_token
}
);
return known_token;
}
@@ -973,23 +892,7 @@ parse_number (void)
token_start = NULL;
known_token = convert_seen_num_to_token (res);
if (!is_empty (known_token))
{
return known_token;
}
known_token = (token)
{
.type = TOK_NUMBER,
.uid = seen_nums_count
};
add_num_to_seen_tokens (
(num_and_token)
{
.num = res,
.tok = known_token
}
);
return known_token;
}
@@ -1011,54 +914,15 @@ parse_number (void)
}
known_token = convert_seen_num_to_token ((ecma_number_t) res);
if (!is_empty (known_token))
{
return known_token;
}
known_token = (token)
{
.type = TOK_NUMBER,
.uid = seen_nums_count
};
add_num_to_seen_tokens (
(num_and_token)
{
.num = (ecma_number_t) res,
.tok = known_token
}
);
return known_token;
}
static char
escape_char (char c)
{
switch (c)
{
case 'b': return '\b';
case 'f': return '\f';
case 'n': return '\n';
case 'r': return '\r';
case 't': return '\t';
case 'v': return '\v';
case '\'':
case '"':
case '\\':
default: return c;
}
}
static token
parse_string (void)
{
char c = LA (0);
bool is_double_quoted;
char *tok = NULL;
char *index = NULL;
const char *i;
size_t length;
token known_token = empty_token;
token result;
JERRY_ASSERT (c == '\'' || c == '"');
@@ -1104,46 +968,13 @@ parse_string (void)
consume_char ();
}
length = (size_t) (buffer - token_start);
tok = (char *) mem_heap_alloc_block (length + 1, MEM_HEAP_ALLOC_SHORT_TERM);
__memset (tok, '\0', length + 1);
index = tok;
// Copy current token to TOK and replace escape sequences by there meanings
for (i = token_start; i < buffer; i++)
{
if (*i == '\\')
{
if (*(i+1) == '\n')
{
i++;
continue;
}
*index = escape_char (*(i+1));
index++;
i++;
continue;
}
*index = *i;
index++;
}
// Eat up '"'
result = convert_current_token_to_token (TOK_STRING);
consume_char ();
known_token = convert_seen_name_to_token (TOK_STRING, tok);
if (!is_empty (known_token))
{
goto end;
}
known_token = add_token_to_seen_names (TOK_STRING, tok);
end:
mem_heap_free_block ((uint8_t *) tok);
token_start = NULL;
return known_token;
return result;
}
static void
@@ -1421,7 +1252,10 @@ lexer_init (const char *source, size_t source_size, bool show_opcodes)
allow_dump_lines = show_opcodes;
buffer_size = source_size;
lexer_set_source (source);
increase_strings_cache ();
STACK_INIT (lp_string, strings);
STACK_INIT (ecma_number_t, numbers);
STACK_INIT (idx_t, num_ids);
}
void
@@ -1439,7 +1273,7 @@ lexer_run_first_pass (void)
void
lexer_free (void)
{
mem_heap_free_block ((uint8_t *) strings_cache);
strings_cache = NULL;
strings_cache_size = 0;
STACK_FREE (strings);
STACK_FREE (numbers);
STACK_FREE (num_ids);
}
+14 -3
View File
@@ -18,6 +18,7 @@
#include "globals.h"
#include "ecma-globals.h"
#include "lp-string.h"
/* Keywords. */
typedef uint8_t keyword;
@@ -145,14 +146,24 @@ token;
void lexer_init (const char *, size_t, bool);
void lexer_free (void);
void lexer_run_first_pass (void);
token lexer_next_token (void);
void lexer_save_token (token);
void lexer_dump_buffer_state (void);
uint8_t lexer_get_strings (const char **);
uint8_t lexer_get_reserved_ids_count (void);
const char *lexer_get_string_by_id (uint8_t);
uint8_t lexer_get_nums (ecma_number_t *);
const lp_string *lexer_get_strings (void);
uint8_t lexer_get_strings_count (void);
lp_string lexer_get_string_by_id (uint8_t);
const ecma_number_t *lexer_get_nums (void);
ecma_number_t lexer_get_num_by_id (uint8_t);
uint8_t lexer_get_nums_count (void);
void lexer_adjust_num_ids (void);
#endif
+699 -549
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -18,7 +18,7 @@
#include "globals.h"
void parser_init (void);
void parser_init (const char *, size_t, bool);
void parser_parse_program (void);
void parser_free (void);
+12 -7
View File
@@ -19,11 +19,7 @@
#include "opcodes.h"
#include "stack.h"
#include "jerry-libc.h"
#ifndef OPCODE_T_STACK_DEFINED
DEFINE_STACK_TYPE (opcode_counter_t, opcode_t)
#define OPCODE_T_STACK_DEFINED
#endif
#include "lp-string.h"
/* bytecode_data contains identifiers, string and num literals.
Memory map if the following.
@@ -36,12 +32,21 @@ DEFINE_STACK_TYPE (opcode_counter_t, opcode_t)
U8 nums_count;
U32 nums[nums_count];
} */
extern uint8_t *bytecode_data;
struct
{
uint8_t strs_count;
uint8_t nums_count;
const lp_string *strings;
const ecma_number_t *nums;
}
__packed
bytecode_data;
enum
{
bytecode_opcodes_global_size
};
STACK (opcode_t, bytecode_opcodes)
STACK (bytecode_opcodes, opcode_counter_t, opcode_t)
#endif // BYTECODE_DATA_H
+13 -56
View File
@@ -16,70 +16,34 @@
#include "deserializer.h"
#include "bytecode-data.h"
ecma_number_t *num_data = NULL;
uint8_t num_size = 0;
const ecma_char_t *
deserialize_string_by_id (uint8_t id)
{
uint8_t size, *data;
uint16_t offset;
JERRY_ASSERT (bytecode_data.strings[id].str[bytecode_data.strings[id].length] == '\0');
if (bytecode_data == NULL)
if (id >= bytecode_data.strs_count)
{
return NULL;
}
size = *bytecode_data;
if (id >= size)
{
return NULL;
}
data = bytecode_data;
data += id * 2 + 1;
offset = *((uint16_t *) data);
return ((const ecma_char_t *) bytecode_data + offset);
return ((const ecma_char_t *) bytecode_data.strings[id].str);
}
ecma_number_t
deserialize_num_by_id (uint8_t id)
{
uint16_t str_size;
str_size = *bytecode_data;
if (id < str_size)
{
return 0;
}
id = (uint8_t) (id - str_size);
if (num_data == NULL)
{
// Go to last string's offset
uint8_t *data = (uint8_t *) (bytecode_data + str_size * 2 - 1);
uint16_t str_offset = *((uint16_t *) data);
data = bytecode_data + str_offset;
while (*data)
{
data++;
}
num_size = *(++data);
num_data = (ecma_number_t *) ++data;
}
if (id >= num_size)
if (id < bytecode_data.strs_count)
{
return 0;
}
return num_data[id];
id = (uint8_t) (id - bytecode_data.strs_count);
if (id >= bytecode_data.nums_count)
{
return 0;
}
return bytecode_data.nums[id];
}
const void *
@@ -92,12 +56,5 @@ deserialize_bytecode (void)
uint8_t
deserialize_min_temp (void)
{
uint8_t str_size = *bytecode_data;
if (num_size == 0)
{
deserialize_num_by_id (str_size); // Init num_data and num_size
}
return (uint8_t) (str_size + num_size);
return (uint8_t) (bytecode_data.strs_count + bytecode_data.nums_count);
}
+24 -17
View File
@@ -15,7 +15,7 @@
#include "pretty-printer.h"
#include "jerry-libc.h"
#include "deserializer.h"
#include "lexer.h"
#define NAME_TO_ID(op) (__op__idx_##op)
@@ -39,17 +39,24 @@ static uint8_t opcode_sizes[] =
0
};
void
pp_strings (const char *strings[], uint8_t size)
static void
dump_lp (lp_string lp)
{
uint8_t i;
uint16_t offset = (uint16_t) (size * 2 + 1);
__printf ("STRINGS %d:\n", size);
for (i = 0; i < size; i++)
for (ecma_length_t i = 0; i < lp.length; i++)
{
__printf ("%3d %5d %20s\n", i, offset, strings[i]);
offset = (uint16_t) (offset + __strlen (strings[i]) + 1);
__putchar (lp.str[i]);
}
}
void
pp_strings (const lp_string strings[], uint8_t size)
{
__printf ("STRINGS %d:\n", size);
for (uint8_t i = 0; i < size; i++)
{
__printf ("%3d ", i);
dump_lp (strings[i]);
__putchar ('\n');
}
}
@@ -77,17 +84,17 @@ dump_arg_list (idx_t id)
static void
dump_variable (idx_t id)
{
if (id >= deserialize_min_temp ())
if (id >= lexer_get_reserved_ids_count ())
{
__printf ("tmp%d", id);
}
else if (deserialize_string_by_id (id))
else if (id < lexer_get_strings_count ())
{
__printf ("%s", deserialize_string_by_id (id));
dump_lp (lexer_get_string_by_id (id));
}
else
{
__printf ("%d", (int) deserialize_num_by_id (id));
__printf ("%d", (int) lexer_get_num_by_id (id));
}
}
@@ -154,14 +161,14 @@ dump_variable (idx_t id)
} \
__printf (": SIMPLE"); \
} else if (opcode.data.op.type_value_right == OPCODE_ARG_TYPE_STRING) { \
__printf ("'%s'", deserialize_string_by_id (opcode.data.op.op2)); \
dump_lp (lexer_get_string_by_id (opcode.data.op.op2)); \
__printf (": STRING"); \
} else if (opcode.data.op.type_value_right == OPCODE_ARG_TYPE_NUMBER) {\
__printf ("%d", (int) deserialize_num_by_id (opcode.data.op.op2)); \
__printf ("%d", (int) lexer_get_num_by_id (opcode.data.op.op2)); \
__printf (": NUMBER"); \
} else if (opcode.data.op.type_value_right == OPCODE_ARG_TYPE_SMALLINT) {\
__printf ("%d", opcode.data.op.op2); \
__printf (": NUMBER"); \
__printf (": SMALLINT"); \
} else if (opcode.data.op.type_value_right == OPCODE_ARG_TYPE_VARIABLE) {\
dump_variable (opcode.data.op.op2); \
__printf (": TYPEOF("); \
+2 -1
View File
@@ -17,9 +17,10 @@
#define PRETTY_PRINTER
#include "interpreter.h"
#include "lp-string.h"
void pp_opcode (opcode_counter_t, opcode_t, bool);
void pp_strings (const char **, uint8_t);
void pp_strings (const lp_string *, uint8_t);
void pp_nums (const ecma_number_t *, uint8_t, uint8_t);
#endif // PRETTY_PRINTER
+29 -92
View File
@@ -22,94 +22,19 @@
static bool print_opcodes;
uint8_t *bytecode_data = NULL;
void
serializer_init (bool show_opcodes)
serializer_dump_strings_and_nums (const lp_string strings[], uint8_t strs_count,
const ecma_number_t nums[], uint8_t nums_count)
{
print_opcodes = show_opcodes;
INIT_STACK (opcode_t, bytecode_opcodes);
}
uint16_t
serializer_dump_strings (const char *strings[], uint8_t size)
{
uint8_t i;
uint16_t offset = (uint16_t) (size * 2 + 1), res;
if (print_opcodes)
{
pp_strings (strings, size);
pp_strings (strings, strs_count);
}
for (i = 0; i < size; i++)
{
offset = (uint16_t) (offset + __strlen (strings[i]) + 1);
}
bytecode_data = mem_heap_alloc_block (offset, MEM_HEAP_ALLOC_SHORT_TERM);
res = offset;
bytecode_data[0] = size;
offset = (uint16_t) (size * 2 + 1);
for (i = 0; i < size; i++)
{
*((uint16_t *) (bytecode_data + i * 2 + 1)) = offset;
offset = (uint16_t) (offset + __strlen (strings[i]) + 1);
}
for (i = 0; i < size; i++)
{
offset = *((uint16_t *) (bytecode_data + i * 2 + 1));
__strncpy ((char *) (bytecode_data + offset), strings[i], __strlen (strings[i]) + 1);
}
#ifndef JERRY_NDEBUG
for (i = 0; i < size; i++)
{
JERRY_ASSERT (!__strcmp (strings[i], (const char *) deserialize_string_by_id (i)));
}
#endif
return res;
}
void
serializer_dump_nums (const ecma_number_t nums[], uint8_t size, uint16_t offset, uint8_t strings_num)
{
uint8_t i, *data, type_size = sizeof (ecma_number_t);
if (print_opcodes)
{
pp_nums (nums, size, strings_num);
}
data = mem_heap_alloc_block ((size_t) (offset + size * type_size + 1), MEM_HEAP_ALLOC_LONG_TERM);
if (!data)
{
parser_fatal (ERR_MEMORY);
}
__memcpy (data, bytecode_data, offset);
mem_heap_free_block (bytecode_data);
bytecode_data = data;
data += offset;
data[0] = size;
data++;
for (i = 0; i < size; i++)
{
__memcpy (data, nums + i, type_size);
data += type_size;
}
#ifndef JERRY_NDEBUG
for (i = 0; i < size; i++)
{
JERRY_ASSERT (nums[i] == deserialize_num_by_id ((uint8_t) (i + strings_num)));
}
JERRY_ASSERT (deserialize_min_temp () == (uint8_t) (size + strings_num));
#endif
bytecode_data.strs_count = strs_count;
bytecode_data.nums_count = nums_count;
bytecode_data.strings = strings;
bytecode_data.nums = nums;
}
void
@@ -122,14 +47,14 @@ serializer_dump_opcode (opcode_t opcode)
pp_opcode (STACK_SIZE (bytecode_opcodes), opcode, false);
}
PUSH (bytecode_opcodes, opcode)
STACK_PUSH (bytecode_opcodes, opcode);
}
void
serializer_rewrite_opcode (const opcode_counter_t loc, opcode_t opcode)
{
JERRY_ASSERT (loc < STACK_SIZE (bytecode_opcodes));
bytecode_opcodes.data[loc] = opcode;
STACK_ELEMENT (bytecode_opcodes, loc) = opcode;
if (print_opcodes)
{
@@ -151,18 +76,30 @@ serializer_print_opcodes (void)
for (loc = 0; loc < STACK_SIZE (bytecode_opcodes); loc++)
{
pp_opcode (loc, bytecode_opcodes.data[loc], false);
pp_opcode (loc, STACK_ELEMENT (bytecode_opcodes, loc), false);
}
}
/* Make lp_strings also zero-terminated. */
void
serializer_adjust_strings (void)
{
for (uint8_t i = 0; i < bytecode_data.strs_count; i++)
{
const ecma_length_t len = bytecode_data.strings[i].length;
((ecma_char_t *) (bytecode_data.strings[i]).str)[len] = '\0';
}
}
void
serializer_init (bool show_opcodes)
{
print_opcodes = show_opcodes;
STACK_INIT (opcode_t, bytecode_opcodes);
}
void
serializer_free (void)
{
mem_heap_free_block (bytecode_data);
bytecode_data = NULL;
if (bytecode_opcodes.data)
{
FREE_STACK (bytecode_opcodes);
}
STACK_FREE (bytecode_opcodes);
}
+5 -3
View File
@@ -19,12 +19,12 @@
#include "globals.h"
#include "opcodes.h"
#include "interpreter.h"
#include "lp-string.h"
void serializer_init (bool show_opcodes);
uint16_t serializer_dump_strings (const char **, uint8_t);
void serializer_dump_nums (const ecma_number_t *, uint8_t, uint16_t, uint8_t);
void serializer_dump_strings_and_nums (const lp_string *, uint8_t,
const ecma_number_t *, uint8_t);
void serializer_dump_opcode (opcode_t);
@@ -32,6 +32,8 @@ void serializer_rewrite_opcode (const opcode_counter_t, opcode_t);
void serializer_print_opcodes (void);
void serializer_adjust_strings (void);
void serializer_free (void);
#endif // SERIALIZER_H
+8 -36
View File
@@ -32,32 +32,17 @@
#define MAX_STRINGS 100
#define MAX_NUMS 25
static const opcode_t *
parser_run (const char *script_source, size_t script_source_size, bool is_show_opcodes)
static bool
jerry_run (const char *script_source, size_t script_source_size,
bool is_parse_only, bool is_show_opcodes, bool is_show_mem_stats)
{
const char *strings[MAX_STRINGS];
ecma_number_t nums[MAX_NUMS];
uint8_t strings_num, nums_count;
uint16_t offset;
const opcode_t *opcodes;
lexer_init (script_source, script_source_size, is_show_opcodes);
mem_init ();
lexer_run_first_pass ();
strings_num = lexer_get_strings (strings);
nums_count = lexer_get_nums (nums);
lexer_adjust_num_ids ();
offset = serializer_dump_strings (strings, strings_num);
serializer_dump_nums (nums, nums_count, offset, strings_num);
parser_init ();
parser_init (script_source, script_source_size, is_show_opcodes);
parser_parse_program ();
lexer_free ();
parser_free ();
opcodes = deserialize_bytecode ();
optimizer_run_passes ((opcode_t *) opcodes);
@@ -66,23 +51,10 @@ parser_run (const char *script_source, size_t script_source_size, bool is_show_o
serializer_print_opcodes ();
#endif
return opcodes;
}
static bool
jerry_run (const char *script_source, size_t script_source_size,
bool is_parse_only, bool is_show_opcodes, bool is_show_mem_stats)
{
const opcode_t *opcodes;
mem_init ();
serializer_init (is_show_opcodes);
opcodes = parser_run (script_source, script_source_size, is_show_opcodes);
if (is_parse_only)
{
parser_free ();
mem_finalize (is_show_mem_stats);
return true;
}
@@ -90,7 +62,7 @@ jerry_run (const char *script_source, size_t script_source_size,
bool is_success = run_int ();
serializer_free ();
parser_free ();
mem_finalize (is_show_mem_stats);
+6
View File
@@ -16,16 +16,22 @@
#ifndef COMMON_H
#define COMMON_H
#include "jerry-libc.h"
#define NAME_TO_ID(op) (__op__idx_##op)
#define __OPCODE_SIZE(name, arg1, arg2, arg3) \
sizeof (__op_##name) + 1,
#define LP(s) (lp_string) { .length = (uint8_t) __strlen(s), .str = (ecma_char_t *) s }
static uint8_t opcode_sizes[] = {
OP_LIST (OPCODE_SIZE)
0
};
static bool opcodes_equal (const opcode_t *, opcode_t *, uint16_t) __unused;
static bool
opcodes_equal (const opcode_t *opcodes1, opcode_t *opcodes2, uint16_t size)
{
@@ -18,6 +18,7 @@
#include "mem-allocator.h"
#include "opcodes.h"
#include "serializer.h"
#include "common.h"
/**
* Unit test's main function.
@@ -39,11 +40,10 @@ main( int __unused argc,
mem_init();
serializer_init (false);
const char *strings[] = { "a",
"b" };
const lp_string strings[] = { LP("a"),
LP("b") };
ecma_number_t nums [] = { 2.0 };
uint16_t offset = serializer_dump_strings( strings, 2);
serializer_dump_nums( nums, 1, offset, 2);
serializer_dump_strings_and_nums (strings, 2, nums, 1);
init_int( test_program, false);
+6 -6
View File
@@ -18,6 +18,7 @@
#include "mem-allocator.h"
#include "opcodes.h"
#include "serializer.h"
#include "common.h"
/**
* Unit test's main function.
@@ -171,15 +172,14 @@ main( int __unused argc,
mem_init();
serializer_init (false);
const char *strings[] = { "a",
"b",
"length",
"1" };
const lp_string strings[] = { LP("a"),
LP("b"),
LP("length"),
LP("1") };
ecma_number_t nums [] = { 2.0,
12.0,
2.5 };
uint16_t offset = serializer_dump_strings( strings, 4);
serializer_dump_nums( nums, 3, offset, 4);
serializer_dump_strings_and_nums (strings, 4, nums, 3);
init_int( test_program, false);
+5 -4
View File
@@ -18,6 +18,7 @@
#include "mem-allocator.h"
#include "opcodes.h"
#include "serializer.h"
#include "common.h"
/**
* Unit test's main function.
@@ -42,12 +43,12 @@ main( int __unused argc,
};
mem_init();
serializer_init (false);
const char *strings[] = { "a",
"b" };
const lp_string strings[] = { LP("a"),
LP("b") };
ecma_number_t nums [] = { 2.0 };
uint16_t offset = serializer_dump_strings( strings, 2);
serializer_dump_nums( nums, 1, offset, 2);
serializer_dump_strings_and_nums (strings, 2, nums, 1);
init_int( test_program, false);
+6 -5
View File
@@ -18,6 +18,7 @@
#include "mem-allocator.h"
#include "opcodes.h"
#include "serializer.h"
#include "common.h"
/**
* Unit test's main function.
@@ -37,12 +38,12 @@ main( int __unused argc,
};
mem_init();
serializer_init (false);
const char *strings[] = { "a",
"b" };
ecma_number_t nums [] = { 2 };
uint16_t offset = serializer_dump_strings( strings, 2);
serializer_dump_nums( nums, 1, offset, 2);
const lp_string strings[] = { LP("a"),
LP("b") };
ecma_number_t nums [] = { 2.0 };
serializer_dump_strings_and_nums (strings, 2, nums, 1);
init_int( test_program, false);
+6 -5
View File
@@ -18,6 +18,7 @@
#include "mem-allocator.h"
#include "opcodes.h"
#include "serializer.h"
#include "common.h"
/**
* Unit test's main function.
@@ -37,12 +38,12 @@ main( int __unused argc,
};
mem_init();
serializer_init (false);
const char *strings[] = { "a",
"b" };
ecma_number_t nums [] = { 2 };
uint16_t offset = serializer_dump_strings( strings, 2);
serializer_dump_nums( nums, 1, offset, 2);
const lp_string strings[] = { LP("a"),
LP("b") };
ecma_number_t nums [] = { 2.0 };
serializer_dump_strings_and_nums (strings, 2, nums, 1);
init_int( test_program, false);
+9 -9
View File
@@ -18,6 +18,7 @@
#include "mem-allocator.h"
#include "opcodes.h"
#include "serializer.h"
#include "common.h"
/**
* Unit test's main function.
@@ -136,16 +137,15 @@ main( int __unused argc,
mem_init();
serializer_init (false);
const char *strings[] = { "a",
"b",
"property1",
"property2",
"property3",
"value1",
"value2" };
const lp_string strings[] = { LP("a"),
LP("b"),
LP("property1"),
LP("property2"),
LP("property3"),
LP("value1"),
LP("value2") };
ecma_number_t nums [] = { 2.5 };
uint16_t offset = serializer_dump_strings( strings, 7);
serializer_dump_nums( nums, 1, offset, 7);
serializer_dump_strings_and_nums (strings, 7, nums, 1);
init_int( test_program, false);
+6 -5
View File
@@ -18,6 +18,7 @@
#include "mem-allocator.h"
#include "opcodes.h"
#include "serializer.h"
#include "common.h"
/**
* Unit test's main function.
@@ -37,12 +38,12 @@ main( int __unused argc,
};
mem_init();
serializer_init (false);
const char *strings[] = { "a",
"b" };
ecma_number_t nums [] = { 2 };
uint16_t offset = serializer_dump_strings( strings, 2);
serializer_dump_nums( nums, 1, offset, 2);
const lp_string strings[] = { LP("a"),
LP("b") };
ecma_number_t nums [] = { 2.0 };
serializer_dump_strings_and_nums (strings, 2, nums, 1);
init_int( test_program, false);
+6 -5
View File
@@ -18,6 +18,7 @@
#include "mem-allocator.h"
#include "opcodes.h"
#include "serializer.h"
#include "common.h"
/**
* Unit test's main function.
@@ -37,12 +38,12 @@ main( int __unused argc,
};
mem_init();
serializer_init (false);
const char *strings[] = { "a",
"b" };
ecma_number_t nums [] = { 2 };
uint16_t offset = serializer_dump_strings( strings, 2);
serializer_dump_nums( nums, 1, offset, 2);
const lp_string strings[] = { LP("a"),
LP("b") };
ecma_number_t nums [] = { 2.0 };
serializer_dump_strings_and_nums (strings, 2, nums, 1);
init_int( test_program, false);
+6 -5
View File
@@ -18,6 +18,7 @@
#include "mem-allocator.h"
#include "opcodes.h"
#include "serializer.h"
#include "common.h"
/**
* Unit test's main function.
@@ -50,13 +51,13 @@ main( int __unused argc,
};
mem_init();
serializer_init (false);
const char *strings[] = { "a",
"b",
"c" };
const lp_string strings[] = { LP("a"),
LP("b"),
LP("c") };
ecma_number_t nums [] = { 2.0 };
uint16_t offset = serializer_dump_strings( strings, 3);
serializer_dump_nums( nums, 1, offset, 3);
serializer_dump_strings_and_nums (strings, 3, nums, 1);
init_int( test_program, false);
@@ -18,6 +18,7 @@
#include "mem-allocator.h"
#include "opcodes.h"
#include "serializer.h"
#include "common.h"
/**
* Unit test's main function.
@@ -35,12 +36,12 @@ main( int __unused argc,
};
mem_init();
serializer_init (false);
const char *strings[] = { "a",
"b" };
ecma_number_t nums [] = { 2 };
uint16_t offset = serializer_dump_strings( strings, 2);
serializer_dump_nums( nums, 1, offset, 2);
const lp_string strings[] = { LP("a"),
LP("b") };
ecma_number_t nums [] = { 2.0 };
serializer_dump_strings_and_nums (strings, 2, nums, 1);
init_int( test_program, false);