Add try-catch-finally support: parse and generate opcodes for this construct

Fix varg generation: generate *_n opcodes with parameters in following meta opcodes
Add stack internal structure: dimanically allocated stack.
Use dynamically allocated memory in parser: every local and global variables are stored in dinamically allocated stacks.
Use dynamically allocated memory in serializer: opcodes are also stored in stack.
Change is_true_jmp and is_false_jmp opcodes to relative.
Change *jmp* opcodes to be able to store opcode_counter_t instead of idx_t.
This commit is contained in:
Ilmir Usmanov 2014-09-16 21:22:11 +04:00
parent cd41b236d9
commit e77bd4f4e5
26 changed files with 1644 additions and 1710 deletions

1
.gitignore vendored
View File

@ -27,6 +27,7 @@ core
vgcore.*
**.orig
**.directory
**.patch
# ctags and ID database
tags

View File

@ -285,8 +285,9 @@ SOURCES_JERRY_H = \
$(wildcard ./src/libecmaoperations/*.h) \
$(wildcard ./src/liballocator/*.h) \
$(wildcard ./src/libcoreint/*.h) \
$(wildcard ./src/liboptimizer/*.h) ) \
$(wildcard ./src/libruntime/target/$(TARGET_SYSTEM)/*.h)
$(wildcard ./src/liboptimizer/*.h) \
$(wildcard ./src/libintstructs/*.h) \
$(wildcard ./src/libruntime/target/$(TARGET_SYSTEM)/*.h) )
SOURCES_JERRY_ASM = \
$(wildcard src/libruntime/target/$(TARGET_SYSTEM)/*.S)
@ -302,7 +303,8 @@ INCLUDES_JERRY = \
-I src/libecmaoperations \
-I src/liballocator \
-I src/liboptimizer \
-I src/libcoreint
-I src/libcoreint \
-I src/libintstructs
# libc
ifeq ($(OPTION_LIBC),musl)

View File

@ -55,7 +55,7 @@
/**
* Size of heap
*/
#define CONFIG_MEM_HEAP_AREA_SIZE (2 * 1024 + 512)
#define CONFIG_MEM_HEAP_AREA_SIZE (4 * 1024 + 512)
/**
* Log2 of maximum possible offset in the heap

View File

@ -20,15 +20,16 @@
* 'Jump if true' opcode handler.
*
* Note:
* the opcode changes current opcode position to specified opcode index
* current opcode's position changes by adding specified offset
* if argument evaluates to true.
*/
ecma_completion_value_t
opfunc_is_true_jmp (opcode_t opdata, /**< operation data */
int_data_t *int_data) /**< interpreter context */
opfunc_is_true_jmp_down (opcode_t opdata, /**< operation data */
int_data_t *int_data) /**< interpreter context */
{
const idx_t cond_var_idx = opdata.data.is_true_jmp.value;
const idx_t dst_opcode_idx = opdata.data.is_true_jmp.opcode;
const idx_t cond_var_idx = opdata.data.is_true_jmp_down.value;
const opcode_counter_t offset = calc_opcode_counter_from_idx_idx (opdata.data.is_true_jmp_down.opcode_1,
opdata.data.is_true_jmp_down.opcode_2);
ecma_completion_value_t ret_value;
@ -39,7 +40,8 @@ opfunc_is_true_jmp (opcode_t opdata, /**< operation data */
if (ecma_is_value_true (to_bool_completion.u.value))
{
int_data->pos = dst_opcode_idx;
JERRY_ASSERT (offset != 0);
int_data->pos = (opcode_counter_t) (int_data->pos + offset);
}
else
{
@ -51,21 +53,55 @@ opfunc_is_true_jmp (opcode_t opdata, /**< operation data */
ECMA_FINALIZE (cond_value);
return ret_value;
} /* opfunc_is_true_jmp */
}
/* Likewise to opfunc_is_true_jmp_down, but jumps up. */
ecma_completion_value_t
opfunc_is_true_jmp_up (opcode_t opdata, /**< operation data */
int_data_t *int_data) /**< interpreter context */
{
const idx_t cond_var_idx = opdata.data.is_true_jmp_up.value;
const opcode_counter_t offset = calc_opcode_counter_from_idx_idx (opdata.data.is_true_jmp_up.opcode_1,
opdata.data.is_true_jmp_up.opcode_2);
ecma_completion_value_t ret_value;
ECMA_TRY_CATCH (cond_value, get_variable_value (int_data, cond_var_idx, false), ret_value);
ecma_completion_value_t to_bool_completion = ecma_op_to_boolean (cond_value.u.value);
JERRY_ASSERT (ecma_is_completion_value_normal (to_bool_completion));
if (ecma_is_value_true (to_bool_completion.u.value))
{
JERRY_ASSERT (offset != 0 && int_data->pos >= offset);
int_data->pos = (opcode_counter_t) (int_data->pos - offset);
}
else
{
int_data->pos++;
}
ret_value = ecma_make_empty_completion_value ();
ECMA_FINALIZE (cond_value);
return ret_value;
}
/**
* 'Jump if false' opcode handler.
*
* Note:
* the opcode changes current opcode position to specified opcode index
* current opcode's position changes by adding specified offset
* if argument evaluates to false.
*/
ecma_completion_value_t
opfunc_is_false_jmp (opcode_t opdata, /**< operation data */
int_data_t *int_data) /**< interpreter context */
opfunc_is_false_jmp_down (opcode_t opdata, /**< operation data */
int_data_t *int_data) /**< interpreter context */
{
const idx_t cond_var_idx = opdata.data.is_false_jmp.value;
const idx_t dst_opcode_idx = opdata.data.is_false_jmp.opcode;
const idx_t cond_var_idx = opdata.data.is_false_jmp_down.value;
const opcode_counter_t offset = calc_opcode_counter_from_idx_idx (opdata.data.is_false_jmp_down.opcode_1,
opdata.data.is_false_jmp_down.opcode_2);
ecma_completion_value_t ret_value;
@ -76,7 +112,8 @@ opfunc_is_false_jmp (opcode_t opdata, /**< operation data */
if (!ecma_is_value_true (to_bool_completion.u.value))
{
int_data->pos = dst_opcode_idx;
JERRY_ASSERT (offset != 0);
int_data->pos = (opcode_counter_t) (int_data->pos + offset);
}
else
{
@ -88,22 +125,40 @@ opfunc_is_false_jmp (opcode_t opdata, /**< operation data */
ECMA_FINALIZE (cond_value);
return ret_value;
} /* opfunc_is_false_jmp */
}
/**
* 'Jump' opcode handler.
*
* Note:
* the opcode changes current opcode position to specified opcode index
*/
/* Likewise to opfunc_is_false_jmp_down, but jumps up. */
ecma_completion_value_t
opfunc_jmp (opcode_t opdata, /**< operation data */
int_data_t *int_data) /**< interpreter context */
opfunc_is_false_jmp_up (opcode_t opdata, /**< operation data */
int_data_t *int_data) /**< interpreter context */
{
int_data->pos = opdata.data.jmp.opcode_idx;
const idx_t cond_var_idx = opdata.data.is_false_jmp_up.value;
const opcode_counter_t offset = calc_opcode_counter_from_idx_idx (opdata.data.is_false_jmp_up.opcode_1,
opdata.data.is_false_jmp_up.opcode_2);
return ecma_make_empty_completion_value ();
} /* opfunc_jmp */
ecma_completion_value_t ret_value;
ECMA_TRY_CATCH (cond_value, get_variable_value (int_data, cond_var_idx, false), ret_value);
ecma_completion_value_t to_bool_completion = ecma_op_to_boolean (cond_value.u.value);
JERRY_ASSERT (ecma_is_completion_value_normal (to_bool_completion));
if (!ecma_is_value_true (to_bool_completion.u.value))
{
JERRY_ASSERT (offset != 0 && int_data->pos >= offset);
int_data->pos = (opcode_counter_t) (int_data->pos - offset);
}
else
{
int_data->pos++;
}
ret_value = ecma_make_empty_completion_value ();
ECMA_FINALIZE (cond_value);
return ret_value;
}
/**
* 'Jump down' opcode handler.
@ -115,12 +170,15 @@ ecma_completion_value_t
opfunc_jmp_down (opcode_t opdata, /**< operation data */
int_data_t *int_data) /**< interpreter context */
{
JERRY_ASSERT (int_data->pos <= int_data->pos + opdata.data.jmp_up.opcode_count);
const opcode_counter_t offset = calc_opcode_counter_from_idx_idx (opdata.data.jmp_down.opcode_1,
opdata.data.jmp_down.opcode_2);
int_data->pos = (opcode_counter_t) (int_data->pos + opdata.data.jmp_down.opcode_count);
JERRY_ASSERT (offset != 0);
int_data->pos = (opcode_counter_t) (int_data->pos + offset);
return ecma_make_empty_completion_value ();
} /* opfunc_jmp_down */
}
/**
* 'Jump up' opcode handler.
@ -132,9 +190,11 @@ ecma_completion_value_t
opfunc_jmp_up (opcode_t opdata, /**< operation data */
int_data_t *int_data) /**< interpreter context */
{
JERRY_ASSERT (int_data->pos >= opdata.data.jmp_up.opcode_count);
const opcode_counter_t offset = calc_opcode_counter_from_idx_idx (opdata.data.jmp_up.opcode_1,
opdata.data.jmp_up.opcode_2);
JERRY_ASSERT (offset != 0 && int_data->pos >= offset);
int_data->pos = (opcode_counter_t) (int_data->pos - opdata.data.jmp_down.opcode_count);
int_data->pos = (opcode_counter_t) (int_data->pos - offset);
return ecma_make_empty_completion_value ();
} /* opfunc_jmp_up */
}

View File

@ -165,12 +165,13 @@ opcode_counter_t read_meta_opcode_counter (opcode_meta_type expected_type, int_d
p##_3 (a, remainder, dst, var_left, var_right)
#define OP_JUMPS(p, a) \
p##_1 (a, jmp, opcode_idx) \
p##_1 (a, jmp_up, opcode_count) \
p##_1 (a, jmp_down, opcode_count) \
p##_2 (a, jmp_up, opcode_1, opcode_2) \
p##_2 (a, jmp_down, opcode_1, opcode_2) \
p##_0 (a, nop) \
p##_2 (a, is_true_jmp, value, opcode) \
p##_2 (a, is_false_jmp, value, opcode)
p##_3 (a, is_true_jmp_up, value, opcode_1, opcode_2) \
p##_3 (a, is_true_jmp_down, value, opcode_1, opcode_2) \
p##_3 (a, is_false_jmp_up, value, opcode_1, opcode_2) \
p##_3 (a, is_false_jmp_down, value, opcode_1, opcode_2)
#define OP_LIST_FULL(p, a) \
OP_CALLS_AND_ARGS (p, a) \

180
src/libintstructs/stack.h Normal file
View File

@ -0,0 +1,180 @@
/* 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 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.
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.
Example (parser.c):
#ifndef UINT8_T_STACK_DEFINED
#define UINT8_T_STACK_DEFINED
DEFINE_STACK_TYPE (uint8_t)
#endif
enum
{
temp_name,
min_temp_name,
max_temp_name,
temp_names_global_size
};
STACK(uint8_t, temp_names)
#define GLOBAL(NAME, VAR) \
NAME.data[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)
{
INIT_STACK(uint8_t, temp_names)
}
void
parser_free (void)
{
FREE_STACK(temp_names)
}
*/
#ifndef STACK_H
#define STACK_H
#define DEFINE_STACK_TYPE(DATA_TYPE, TYPE) \
typedef struct \
{ \
DATA_TYPE length; \
DATA_TYPE current; \
TYPE *data; \
} \
__packed \
TYPE##_stack;
#define INIT_STACK(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)); \
} while (0)
#define FREE_STACK(NAME) \
do { \
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.
However, in serializer, there is a need for reallocation of memory.
Do this in several steps:
1) Allocate already allocated memory size twice.
2) Copy used memory to the last.
3) Dealocate first two chuncks.
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) \
static void increase_##NAME##_stack_size (__typeof__ (NAME.length)) __unused; \
static void \
increase_##NAME##_stack_size (__typeof__ (NAME.length) elements_count) { \
if (NAME.current + elements_count >= NAME.length) \
{ \
size_t old_size = NAME.length * sizeof (TYPE); \
size_t temp1_size = mem_heap_recommend_allocation_size ( \
(size_t) (elements_count * sizeof (TYPE))); \
size_t new_size = mem_heap_recommend_allocation_size ( \
(size_t) (temp1_size + old_size)); \
TYPE *temp1 = (TYPE *) mem_heap_alloc_block (temp1_size, MEM_HEAP_ALLOC_SHORT_TERM); \
TYPE *temp2 = (TYPE *) mem_heap_alloc_block (old_size, MEM_HEAP_ALLOC_SHORT_TERM); \
if (temp2 == NULL) \
{ \
mem_heap_print (true, false, true); \
JERRY_UNREACHABLE (); \
} \
__memcpy (temp2, NAME.data, old_size); \
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); \
__memcpy (NAME.data, temp2, old_size); \
mem_heap_free_block ((uint8_t *) temp2); \
NAME.length = (__typeof__ (NAME.length)) (new_size / sizeof (TYPE)); \
} \
NAME.current = (__typeof__ (NAME.current)) (NAME.current + elements_count); \
}
#define DEFINE_DECREASE_STACE_SIZE(NAME) \
static void decrease_##NAME##_stack_size (uint8_t) __unused; \
static void \
decrease_##NAME##_stack_size (uint8_t elements_count) { \
JERRY_ASSERT (NAME.current - elements_count >= NAME##_global_size); \
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 POP(VALUE, NAME) \
decrease_##NAME##_stack_size (1); \
VALUE = NAME.data[NAME.current];
#define DROP(NAME, I) \
decrease_##NAME##_stack_size (I);
#define CLEAN(NAME) \
DROP (NAME, NAME.current - NAME##_global_size);
#define 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 STATIC_STACK(TYPE, NAME) \
static TYPE##_stack NAME; \
DEFINE_DECREASE_STACE_SIZE (NAME) \
DEFINE_INCREASE_STACK_SIZE (TYPE, NAME)
#ifndef JERRY_NDEBUG
#define DECLARE_USAGE(NAME) \
uint8_t NAME##_current = NAME.current;
#define CHECK_USAGE(NAME) \
JERRY_ASSERT (NAME.current == NAME##_current);
#else
#define DECLARE_USAGE(NAME) ;
#define CHECK_USAGE(NAME) ;
#endif /* JERRY_NDEBUG */
#endif /* STACK_H */

View File

@ -23,7 +23,7 @@ static token empty_token =
{
.type =
TOK_EMPTY,
.data.uid = 0
.uid = 0
};
static bool allow_dump_lines = false;
@ -148,7 +148,7 @@ decode_keyword (void)
return (token)
{
.type = TOK_KEYWORD,
.data.kw = KW_BREAK
.uid = KW_BREAK
};
}
if (current_token_equals_to ("case"))
@ -156,7 +156,7 @@ decode_keyword (void)
return (token)
{
.type = TOK_KEYWORD,
.data.kw = KW_CASE
.uid = KW_CASE
};
}
if (current_token_equals_to ("catch"))
@ -164,7 +164,7 @@ decode_keyword (void)
return (token)
{
.type = TOK_KEYWORD,
.data.kw = KW_CATCH
.uid = KW_CATCH
};
}
if (current_token_equals_to ("class"))
@ -172,7 +172,7 @@ decode_keyword (void)
return (token)
{
.type = TOK_KEYWORD,
.data.kw = KW_RESERVED
.uid = KW_RESERVED
};
}
if (current_token_equals_to ("const"))
@ -180,7 +180,7 @@ decode_keyword (void)
return (token)
{
.type = TOK_KEYWORD,
.data.kw = KW_RESERVED
.uid = KW_RESERVED
};
}
if (current_token_equals_to ("continue"))
@ -188,7 +188,7 @@ decode_keyword (void)
return (token)
{
.type = TOK_KEYWORD,
.data.kw = KW_CONTINUE
.uid = KW_CONTINUE
};
}
if (current_token_equals_to ("debugger"))
@ -196,7 +196,7 @@ decode_keyword (void)
return (token)
{
.type = TOK_KEYWORD,
.data.kw = KW_DEBUGGER
.uid = KW_DEBUGGER
};
}
if (current_token_equals_to ("default"))
@ -204,7 +204,7 @@ decode_keyword (void)
return (token)
{
.type = TOK_KEYWORD,
.data.kw = KW_DEFAULT
.uid = KW_DEFAULT
};
}
if (current_token_equals_to ("delete"))
@ -212,7 +212,7 @@ decode_keyword (void)
return (token)
{
.type = TOK_KEYWORD,
.data.kw = KW_DELETE
.uid = KW_DELETE
};
}
if (current_token_equals_to ("do"))
@ -220,7 +220,7 @@ decode_keyword (void)
return (token)
{
.type = TOK_KEYWORD,
.data.kw = KW_DO
.uid = KW_DO
};
}
if (current_token_equals_to ("else"))
@ -228,7 +228,7 @@ decode_keyword (void)
return (token)
{
.type = TOK_KEYWORD,
.data.kw = KW_ELSE
.uid = KW_ELSE
};
}
if (current_token_equals_to ("enum"))
@ -236,7 +236,7 @@ decode_keyword (void)
return (token)
{
.type = TOK_KEYWORD,
.data.kw = KW_RESERVED
.uid = KW_RESERVED
};
}
if (current_token_equals_to ("export"))
@ -244,7 +244,7 @@ decode_keyword (void)
return (token)
{
.type = TOK_KEYWORD,
.data.kw = KW_RESERVED
.uid = KW_RESERVED
};
}
if (current_token_equals_to ("extends"))
@ -252,7 +252,7 @@ decode_keyword (void)
return (token)
{
.type = TOK_KEYWORD,
.data.kw = KW_RESERVED
.uid = KW_RESERVED
};
}
if (current_token_equals_to ("false"))
@ -260,7 +260,7 @@ decode_keyword (void)
return (token)
{
.type = TOK_BOOL,
.data.uid = false
.uid = false
};
}
if (current_token_equals_to ("finally"))
@ -268,7 +268,7 @@ decode_keyword (void)
return (token)
{
.type = TOK_KEYWORD,
.data.kw = KW_FINALLY
.uid = KW_FINALLY
};
}
if (current_token_equals_to ("for"))
@ -276,7 +276,7 @@ decode_keyword (void)
return (token)
{
.type = TOK_KEYWORD,
.data.kw = KW_FOR
.uid = KW_FOR
};
}
if (current_token_equals_to ("function"))
@ -284,7 +284,7 @@ decode_keyword (void)
return (token)
{
.type = TOK_KEYWORD,
.data.kw = KW_FUNCTION
.uid = KW_FUNCTION
};
}
if (current_token_equals_to ("if"))
@ -292,7 +292,7 @@ decode_keyword (void)
return (token)
{
.type = TOK_KEYWORD,
.data.kw = KW_IF
.uid = KW_IF
};
}
if (current_token_equals_to ("instanceof"))
@ -300,7 +300,7 @@ decode_keyword (void)
return (token)
{
.type = TOK_KEYWORD,
.data.kw = KW_INSTANCEOF
.uid = KW_INSTANCEOF
};
}
if (current_token_equals_to ("interface"))
@ -308,7 +308,7 @@ decode_keyword (void)
return (token)
{
.type = TOK_KEYWORD,
.data.kw = KW_RESERVED
.uid = KW_RESERVED
};
}
if (current_token_equals_to ("in"))
@ -316,7 +316,7 @@ decode_keyword (void)
return (token)
{
.type = TOK_KEYWORD,
.data.kw = KW_IN
.uid = KW_IN
};
}
if (current_token_equals_to ("import"))
@ -324,7 +324,7 @@ decode_keyword (void)
return (token)
{
.type = TOK_KEYWORD,
.data.kw = KW_RESERVED
.uid = KW_RESERVED
};
}
if (current_token_equals_to ("implements"))
@ -332,7 +332,7 @@ decode_keyword (void)
return (token)
{
.type = TOK_KEYWORD,
.data.kw = KW_RESERVED
.uid = KW_RESERVED
};
}
if (current_token_equals_to ("let"))
@ -340,7 +340,7 @@ decode_keyword (void)
return (token)
{
.type = TOK_KEYWORD,
.data.kw = KW_RESERVED
.uid = KW_RESERVED
};
}
if (current_token_equals_to ("new"))
@ -348,7 +348,7 @@ decode_keyword (void)
return (token)
{
.type = TOK_KEYWORD,
.data.kw = KW_NEW
.uid = KW_NEW
};
}
if (current_token_equals_to ("null"))
@ -356,7 +356,7 @@ decode_keyword (void)
return (token)
{
.type = TOK_NULL,
.data.uid = 0
.uid = 0
};
}
if (current_token_equals_to ("package"))
@ -364,7 +364,7 @@ decode_keyword (void)
return (token)
{
.type = TOK_KEYWORD,
.data.kw = KW_RESERVED
.uid = KW_RESERVED
};
}
if (current_token_equals_to ("private"))
@ -372,7 +372,7 @@ decode_keyword (void)
return (token)
{
.type = TOK_KEYWORD,
.data.kw = KW_RESERVED
.uid = KW_RESERVED
};
}
if (current_token_equals_to ("protected"))
@ -380,7 +380,7 @@ decode_keyword (void)
return (token)
{
.type = TOK_KEYWORD,
.data.kw = KW_RESERVED
.uid = KW_RESERVED
};
}
if (current_token_equals_to ("public"))
@ -388,7 +388,7 @@ decode_keyword (void)
return (token)
{
.type = TOK_KEYWORD,
.data.kw = KW_RESERVED
.uid = KW_RESERVED
};
}
if (current_token_equals_to ("return"))
@ -396,7 +396,7 @@ decode_keyword (void)
return (token)
{
.type = TOK_KEYWORD,
.data.kw = KW_RETURN
.uid = KW_RETURN
};
}
if (current_token_equals_to ("static"))
@ -404,7 +404,7 @@ decode_keyword (void)
return (token)
{
.type = TOK_KEYWORD,
.data.kw = KW_RESERVED
.uid = KW_RESERVED
};
}
if (current_token_equals_to ("super"))
@ -412,7 +412,7 @@ decode_keyword (void)
return (token)
{
.type = TOK_KEYWORD,
.data.kw = KW_RESERVED
.uid = KW_RESERVED
};
}
if (current_token_equals_to ("switch"))
@ -420,7 +420,7 @@ decode_keyword (void)
return (token)
{
.type = TOK_KEYWORD,
.data.kw = KW_SWITCH
.uid = KW_SWITCH
};
}
if (current_token_equals_to ("this"))
@ -428,7 +428,7 @@ decode_keyword (void)
return (token)
{
.type = TOK_KEYWORD,
.data.kw = KW_THIS
.uid = KW_THIS
};
}
if (current_token_equals_to ("throw"))
@ -436,7 +436,7 @@ decode_keyword (void)
return (token)
{
.type = TOK_KEYWORD,
.data.kw = KW_THROW
.uid = KW_THROW
};
}
if (current_token_equals_to ("true"))
@ -444,7 +444,7 @@ decode_keyword (void)
return (token)
{
.type = TOK_BOOL,
.data.uid = true
.uid = true
};
}
if (current_token_equals_to ("try"))
@ -452,7 +452,7 @@ decode_keyword (void)
return (token)
{
.type = TOK_KEYWORD,
.data.kw = KW_TRY
.uid = KW_TRY
};
}
if (current_token_equals_to ("typeof"))
@ -460,7 +460,7 @@ decode_keyword (void)
return (token)
{
.type = TOK_KEYWORD,
.data.kw = KW_TYPEOF
.uid = KW_TYPEOF
};
}
if (current_token_equals_to ("var"))
@ -468,7 +468,7 @@ decode_keyword (void)
return (token)
{
.type = TOK_KEYWORD,
.data.kw = KW_VAR
.uid = KW_VAR
};
}
if (current_token_equals_to ("void"))
@ -476,7 +476,7 @@ decode_keyword (void)
return (token)
{
.type = TOK_KEYWORD,
.data.kw = KW_VOID
.uid = KW_VOID
};
}
if (current_token_equals_to ("while"))
@ -484,7 +484,7 @@ decode_keyword (void)
return (token)
{
.type = TOK_KEYWORD,
.data.kw = KW_WHILE
.uid = KW_WHILE
};
}
if (current_token_equals_to ("with"))
@ -492,7 +492,7 @@ decode_keyword (void)
return (token)
{
.type = TOK_KEYWORD,
.data.kw = KW_WITH
.uid = KW_WITH
};
}
if (current_token_equals_to ("yield"))
@ -500,7 +500,7 @@ decode_keyword (void)
return (token)
{
.type = TOK_KEYWORD,
.data.kw = KW_RESERVED
.uid = KW_RESERVED
};
}
return empty_token;
@ -522,7 +522,7 @@ convert_seen_name_to_token (token_type tt, const char *string)
ret_val = (token)
{
.type = tt,
.data.uid = i
.uid = i
};
break;
@ -574,7 +574,7 @@ add_token_to_seen_names (token_type tt, const char *string)
ret_val = (token)
{
.type = tt,
.data.uid = seen_names_count++
.uid = seen_names_count++
};
return ret_val;
@ -668,7 +668,7 @@ lexer_adjust_num_ids (void)
for (i = 0; i < seen_nums_count; i++)
{
seen_nums[i].tok.data.uid = (uint8_t) (seen_nums[i].tok.data.uid + seen_names_count);
seen_nums[i].tok.uid = (uint8_t) (seen_nums[i].tok.uid + seen_names_count);
}
}
@ -693,7 +693,7 @@ consume_char (void)
return (token) \
{ \
.type = TOK, \
.data.uid = 0 \
.uid = 0 \
}; \
} \
while (0)
@ -881,7 +881,7 @@ parse_number (void)
return (token)
{
.type = TOK_SMALL_INT,
.data.uid = (uint8_t) res
.uid = (uint8_t) res
};
}
@ -894,7 +894,7 @@ parse_number (void)
known_token = (token)
{
.type = TOK_NUMBER,
.data.uid = seen_nums_count
.uid = seen_nums_count
};
add_num_to_seen_tokens (
(num_and_token)
@ -981,7 +981,7 @@ parse_number (void)
known_token = (token)
{
.type = TOK_NUMBER,
.data.uid = seen_nums_count
.uid = seen_nums_count
};
add_num_to_seen_tokens (
(num_and_token)
@ -1006,7 +1006,7 @@ parse_number (void)
return (token)
{
.type = TOK_SMALL_INT,
.data.uid = (uint8_t) res
.uid = (uint8_t) res
};
}
@ -1019,7 +1019,7 @@ parse_number (void)
known_token = (token)
{
.type = TOK_NUMBER,
.data.uid = seen_nums_count
.uid = seen_nums_count
};
add_num_to_seen_tokens (
(num_and_token)
@ -1251,7 +1251,7 @@ lexer_next_token_private (void)
return (token)
{
.type = TOK_NEWLINE,
.data.uid = 0
.uid = 0
};
}
@ -1260,7 +1260,7 @@ lexer_next_token_private (void)
return (token)
{
.type = TOK_EOF,
.data.uid = 0
.uid = 0
};
}
@ -1282,7 +1282,7 @@ lexer_next_token_private (void)
return (token)
{
.type = TOK_NEWLINE,
.data.uid = 0
.uid = 0
};
}
else

View File

@ -138,12 +138,7 @@ typedef struct
{
token_type type;
union
{
keyword kw;
uint8_t uid;
}
data;
uint8_t uid;
}
__packed
token;

File diff suppressed because it is too large Load Diff

View File

@ -20,6 +20,7 @@
void parser_init (void);
void parser_parse_program (void);
void parser_free (void);
void parser_fatal (jerry_status_t code);

View File

@ -13,12 +13,19 @@
* limitations under the License.
*/
#ifndef BYTECODE_LINUX_H
#define BYTECODE_LINUX_H
#ifndef BYTECODE_DATA_H
#define BYTECODE_DATA_H
#include "opcodes.h"
#include "stack.h"
#include "jerry-libc.h"
#define MAX_OPCODES 255
#define MAX_OPCODES (256*256 - 1)
#ifndef OPCODE_T_STACK_DEFINED
DEFINE_STACK_TYPE (opcode_counter_t, opcode_t)
#define OPCODE_T_STACK_DEFINED
#endif
/* bytecode_data contains identifiers, string and num literals.
Memory map if the following.
@ -32,6 +39,11 @@
U32 nums[nums_count];
} */
extern uint8_t *bytecode_data;
opcode_t bytecode_opcodes[MAX_OPCODES];
#endif // BYTECODE_LINUX_H
enum
{
bytecode_opcodes_global_size
};
STACK (opcode_t, bytecode_opcodes)
#endif // BYTECODE_DATA_H

View File

@ -85,7 +85,8 @@ deserialize_num_by_id (uint8_t id)
const void *
deserialize_bytecode (void)
{
return bytecode_opcodes;
JERRY_ASSERT (STACK_SIZE (bytecode_opcodes) > 0);
return bytecode_opcodes.data;
}
uint8_t

View File

@ -52,382 +52,6 @@ optimize_calls (opcode_t *opcodes)
}
}
/* Move NUMBER opcodes from FROM to TO and adjust opcodes beetwen FROM and TO. */
void
optimizer_move_opcodes (opcode_t *from, opcode_t *to, uint16_t number)
{
opcode_t temp[number], *current_opcode;
uint16_t i;
if (to == from)
{
return;
}
for (i = 0; i < number; i++)
{
temp[i] = from[i];
}
if (to > from)
{
if (number <= to - from)
{
// Adjust opcodes up
for (current_opcode = from; current_opcode != to; current_opcode++)
{
*current_opcode = *(current_opcode + number);
}
}
else
{
optimizer_move_opcodes (from + number, from, (uint16_t) (to - from));
}
}
else
{
if (number <= from - to)
{
// Adjust opcodes down
for (current_opcode = from; current_opcode != to; current_opcode--)
{
*current_opcode = *(current_opcode - number);
}
}
else
{
optimizer_move_opcodes (to, to + number, (uint16_t) (from - to));
}
}
for (i = 0; i < number; i++)
{
to[i] = temp[i];
}
}
static uint16_t
opcode_to_counter (opcode_t *opcode)
{
JERRY_ASSERT (opcode > (opcode_t *) deserialize_bytecode ());
return (uint16_t) (opcode - (opcode_t *) deserialize_bytecode ());
}
void
optimizer_adjust_jumps (opcode_t *first_opcode, opcode_t *last_opcode, int16_t value)
{
opcode_t *current_opcode;
JERRY_ASSERT (first_opcode <= last_opcode);
for (current_opcode = first_opcode; current_opcode != last_opcode; current_opcode++)
{
if (current_opcode->op_idx == NAME_TO_ID (is_true_jmp))
{
/* 19: is_true_jmp 2
20: var_decl ...
becomes
19: var_decl ...
20: is_true_jmp 2
*/
if (current_opcode->data.is_true_jmp.opcode >= opcode_to_counter (last_opcode)
|| current_opcode->data.is_true_jmp.opcode < opcode_to_counter (first_opcode) - value)
{
continue;
}
/* 19: is_true_jmp 20
20: assignment
21: var_decl
becomes
19: var_decl
20: is_true_jmp 21
21: assignment
*/
if (current_opcode->data.is_true_jmp.opcode >= opcode_to_counter (first_opcode)
&& current_opcode->data.is_true_jmp.opcode <= opcode_to_counter (last_opcode) - value)
{
current_opcode->data.is_true_jmp.opcode = (idx_t) (current_opcode->data.is_true_jmp.opcode + value);
continue;
}
/* 19: is_true_jmp 22
20: assignment
21: var_decl
22: var_decl
becomes
19: var_decl
20: var_decl
21: is_true_jmp 23
22: assignment
*/
if (current_opcode->data.is_true_jmp.opcode < opcode_to_counter (last_opcode))
{
current_opcode->data.is_true_jmp.opcode = (idx_t) opcode_to_counter (last_opcode);
continue;
}
JERRY_UNREACHABLE ();
}
if (current_opcode->op_idx == NAME_TO_ID (is_false_jmp))
{
/* 19: is_false_jmp 2
20: var_decl ...
becomes
19: var_decl ...
20: is_false_jmp 2
*/
if (current_opcode->data.is_false_jmp.opcode >= opcode_to_counter (last_opcode)
|| current_opcode->data.is_false_jmp.opcode < opcode_to_counter (first_opcode) - value)
{
continue;
}
/* 19: is_false_jmp 20
20: assignment
21: var_decl
becomes
19: var_decl
20: is_false_jmp 21
21: assignment
*/
if (current_opcode->data.is_false_jmp.opcode >= opcode_to_counter (first_opcode)
&& current_opcode->data.is_false_jmp.opcode <= opcode_to_counter (last_opcode) - value)
{
current_opcode->data.is_false_jmp.opcode = (idx_t) (current_opcode->data.is_false_jmp.opcode + value);
continue;
}
/* 19: is_false_jmp 22
20: assignment
21: var_decl
22: var_decl
becomes
19: var_decl
20: var_decl
21: is_false_jmp 23
22: assignment
*/
if (current_opcode->data.is_false_jmp.opcode < opcode_to_counter (last_opcode))
{
current_opcode->data.is_false_jmp.opcode = (idx_t) opcode_to_counter (last_opcode);
continue;
}
JERRY_UNREACHABLE ();
}
if (current_opcode->op_idx == NAME_TO_ID (jmp_down))
{
/* 19: jmp_down 1
20: assignment
21: var_decl ...
becomes
19: var_decl ...
20: jmp_down 1
21: assignment
*/
if (current_opcode->data.jmp_down.opcode_count < last_opcode - current_opcode)
{
continue;
}
/* 19: jmp_down 3
20: assignment
21: var_decl
becomes
19: var_decl
20: jmp_down 2
21: assignment
*/
if (current_opcode->data.jmp_down.opcode_count >= last_opcode - current_opcode + value)
{
current_opcode->data.jmp_down.opcode_count = (idx_t) (current_opcode->data.jmp_down.opcode_count - value);
continue;
}
/* 19: jmp_down 3
20: assignment
21: var_decl
22: var_decl
becomes
19: var_decl
20: var_decl
21: jmp_down 2
22: assignment
*/
if (current_opcode->data.jmp_down.opcode_count >= last_opcode - current_opcode
&& current_opcode->data.jmp_down.opcode_count < last_opcode - current_opcode + value)
{
current_opcode->data.jmp_down.opcode_count = (idx_t) (last_opcode - current_opcode);
continue;
}
JERRY_UNREACHABLE ();
}
if (current_opcode->op_idx == NAME_TO_ID (jmp_up))
{
/* 19: assignment
20: jmp_up 1
21: var_decl ...
becomes
19: var_decl ...
20: assignment
21: jmp_up 1
*/
if (current_opcode->data.jmp_up.opcode_count < current_opcode - first_opcode)
{
continue;
}
/* 19: jmp_up 1
20: assignment
21: var_decl
becomes
19: var_decl
20: jmp_up 2
21: assignment
*/
if (current_opcode->data.jmp_up.opcode_count >= current_opcode - first_opcode)
{
current_opcode->data.jmp_up.opcode_count = (idx_t) (current_opcode->data.jmp_up.opcode_count + value);
continue;
}
JERRY_UNREACHABLE ();
}
}
}
/* Reorder scope like
"use strict"
func_decl
var_decl
other opcodes
*/
void
optimizer_reorder_scope (uint16_t scope_start, uint16_t scope_end)
{
opcode_t *opcodes = (opcode_t *) deserialize_bytecode ();
opcode_t *first_opcode = opcodes + scope_start;
opcode_t *last_opcode = opcodes + scope_end;
opcode_t *current_opcode, *processed_opcode = first_opcode;
opcode_t *var_decls_start;
for (current_opcode = processed_opcode; current_opcode != last_opcode; current_opcode++)
{
if (current_opcode->op_idx == NAME_TO_ID (assignment)
&& current_opcode->data.assignment.type_value_right == OPCODE_ARG_TYPE_STRING
&& !__strcmp ("use strict", (char *) deserialize_string_by_id (current_opcode->data.assignment.value_right)))
{
optimizer_move_opcodes (current_opcode, processed_opcode, 1);
optimizer_adjust_jumps (processed_opcode + 1, current_opcode + 1, 1);
processed_opcode++;
break;
}
}
for (current_opcode = processed_opcode; current_opcode != last_opcode;)
{
if (current_opcode->op_idx == NAME_TO_ID (func_decl_0)
|| current_opcode->op_idx == NAME_TO_ID (func_decl_1)
|| current_opcode->op_idx == NAME_TO_ID (func_decl_2)
|| current_opcode->op_idx == NAME_TO_ID (func_decl_n))
{
opcode_t *fun_opcode;
int16_t value, jmp_offset = 0;
for (fun_opcode = current_opcode + 1; fun_opcode != last_opcode; fun_opcode++)
{
if (fun_opcode->op_idx == NAME_TO_ID (jmp_down))
{
jmp_offset = (int16_t) (fun_opcode - current_opcode);
fun_opcode += fun_opcode->data.jmp_down.opcode_count;
break;
}
}
JERRY_ASSERT (fun_opcode <= last_opcode);
value = (int16_t) (fun_opcode - current_opcode);
optimizer_move_opcodes (current_opcode, processed_opcode, (uint16_t) value);
// Adjust jumps inside func_decl except end's jmp_down
optimizer_adjust_jumps (processed_opcode + jmp_offset + 1,
processed_opcode + value,
(int16_t) (processed_opcode - current_opcode));
optimizer_adjust_jumps (processed_opcode + value,
fun_opcode,
value);
processed_opcode += value;
current_opcode = fun_opcode;
continue;
}
else
{
current_opcode++;
}
}
var_decls_start = processed_opcode;
for (current_opcode = processed_opcode; current_opcode != last_opcode; current_opcode++)
{
if (current_opcode->op_idx == NAME_TO_ID (var_decl))
{
// If variable already declared, replace it with nop
bool was_decl = false;
if (var_decls_start->op_idx == NAME_TO_ID (var_decl) && var_decls_start != current_opcode)
{
opcode_t *var_decls_iterator;
for (var_decls_iterator = var_decls_start;
var_decls_iterator != processed_opcode;
var_decls_iterator++)
{
JERRY_ASSERT (var_decls_iterator->op_idx == NAME_TO_ID (var_decl));
if (var_decls_iterator->data.var_decl.variable_name
== current_opcode->data.var_decl.variable_name)
{
was_decl = true;
break;
}
}
}
if (was_decl)
{
current_opcode->op_idx = NAME_TO_ID (nop);
}
else
{
optimizer_move_opcodes (current_opcode, processed_opcode, 1);
optimizer_adjust_jumps (processed_opcode + 1, current_opcode + 1, 1);
processed_opcode++;
}
}
}
}
void
optimizer_run_passes (opcode_t *opcodes)
{

View File

@ -19,9 +19,6 @@
#include "globals.h"
#include "opcodes.h"
void optimizer_move_opcodes (opcode_t *, opcode_t *, uint16_t);
void optimizer_adjust_jumps (opcode_t *, opcode_t *, int16_t);
void optimizer_reorder_scope (uint16_t, uint16_t);
void optimizer_run_passes (opcode_t *);
#endif // OPTIMIZER_PASSES_H

View File

@ -91,18 +91,20 @@ dump_variable (idx_t id)
}
}
#define CASE_CONDITIONAL_JUMP(op, string1, field1, string2, field2) \
#define CASE_CONDITIONAL_JUMP(op, string1, field1, string2, oc, sign, field2, field3) \
case NAME_TO_ID (op): \
__printf (string1); \
dump_variable (opcode.data.op.field1); \
__printf (string2); \
__printf (" %d;", opcode.data.op.field2); \
__printf (" %d;", oc sign ((opcode.data.op.field2 << JERRY_BITSINBYTE) \
+ opcode.data.op.field3)); \
break;
#define CASE_UNCONDITIONAL_JUMP(op, string, oc, oper, field) \
#define CASE_UNCONDITIONAL_JUMP(op, string, oc, sign, field2, field3) \
case NAME_TO_ID (op): \
__printf (string); \
__printf (" %d;", oc oper opcode.data.op.field); \
__printf (" %d;", oc sign ((opcode.data.op.field2 << JERRY_BITSINBYTE) \
+ opcode.data.op.field3)); \
break;
#define CASE_TRIPLE_ADDRESS(op, lhs, equals, op1, oper, op2) \
@ -366,12 +368,13 @@ pp_opcode (opcode_counter_t oc, opcode_t opcode, bool is_rewrite)
switch (opcode_num)
{
CASE_CONDITIONAL_JUMP (is_true_jmp, "if (", value, ") goto", opcode)
CASE_CONDITIONAL_JUMP (is_false_jmp, "if (", value, " == false) goto", opcode)
CASE_CONDITIONAL_JUMP (is_true_jmp_up, "if (", value, ") goto", oc, -, opcode_1, opcode_2)
CASE_CONDITIONAL_JUMP (is_false_jmp_up, "if (", value, " == false) goto", oc, -, opcode_1, opcode_2)
CASE_CONDITIONAL_JUMP (is_true_jmp_down, "if (", value, ") goto", oc, +, opcode_1, opcode_2)
CASE_CONDITIONAL_JUMP (is_false_jmp_down, "if (", value, " == false) goto", oc, +, opcode_1, opcode_2)
CASE_UNCONDITIONAL_JUMP (jmp, "goto", 0, +, opcode_idx)
CASE_UNCONDITIONAL_JUMP (jmp_up, "goto", oc, -, opcode_count)
CASE_UNCONDITIONAL_JUMP (jmp_down, "goto", oc, +, opcode_count)
CASE_UNCONDITIONAL_JUMP (jmp_up, "goto", oc, -, opcode_1, opcode_2)
CASE_UNCONDITIONAL_JUMP (jmp_down, "goto", oc, +, opcode_1, opcode_2)
CASE_TRIPLE_ADDRESS (addition, dst, "=", var_left, "+", var_right)
CASE_TRIPLE_ADDRESS (substraction, dst, "=", var_left, "-", var_right)

View File

@ -28,6 +28,7 @@ void
serializer_init (bool show_opcodes)
{
print_opcodes = show_opcodes;
INIT_STACK (opcode_t, bytecode_opcodes);
}
uint16_t
@ -111,25 +112,24 @@ serializer_dump_nums (const ecma_number_t nums[], uint8_t size, uint16_t offset,
#endif
}
static opcode_counter_t opcode_counter = 0;
void
serializer_dump_opcode (opcode_t opcode)
{
JERRY_ASSERT (STACK_SIZE (bytecode_opcodes) < MAX_OPCODES);
if (print_opcodes)
{
pp_opcode (opcode_counter, opcode, false);
pp_opcode (STACK_SIZE (bytecode_opcodes), opcode, false);
}
JERRY_ASSERT (opcode_counter < MAX_OPCODES);
bytecode_opcodes[opcode_counter++] = opcode;
PUSH (bytecode_opcodes, opcode)
}
void
serializer_rewrite_opcode (const opcode_counter_t loc, opcode_t opcode)
{
JERRY_ASSERT (loc < MAX_OPCODES);
bytecode_opcodes[loc] = opcode;
JERRY_ASSERT (loc < STACK_SIZE (bytecode_opcodes));
bytecode_opcodes.data[loc] = opcode;
if (print_opcodes)
{
@ -149,9 +149,9 @@ serializer_print_opcodes (void)
__printf ("AFTER OPTIMIZER:\n");
for (loc = 0; (*(uint32_t *) (bytecode_opcodes + loc) != 0x0); loc++)
for (loc = 0; loc < STACK_SIZE (bytecode_opcodes); loc++)
{
pp_opcode (loc, bytecode_opcodes[loc], false);
pp_opcode (loc, bytecode_opcodes.data[loc], false);
}
}
@ -160,4 +160,9 @@ serializer_free (void)
{
mem_heap_free_block (bytecode_data);
bytecode_data = NULL;
if (bytecode_opcodes.data)
{
FREE_STACK (bytecode_opcodes);
}
}

View File

@ -56,6 +56,7 @@ parser_run (const char *script_source, size_t script_source_size, bool is_show_o
parser_parse_program ();
lexer_free ();
parser_free ();
opcodes = deserialize_bytecode ();

View File

@ -37,6 +37,7 @@ main( int __unused argc,
};
mem_init();
serializer_init (false);
const char *strings[] = { "a",
"b" };

View File

@ -28,7 +28,7 @@ main( int __unused argc,
{
const opcode_t test_program[] = {
[ 0] = getop_reg_var_decl (240, 255),
[ 1] = getop_jmp_down (2),
[ 1] = getop_jmp_down (0, 2),
[ 2] = getop_exitval (1),
/* var a, b; */
@ -52,35 +52,35 @@ main( int __unused argc,
[14] = getop_prop_getter (240, 0, 240),
[15] = getop_assignment (241, OPCODE_ARG_TYPE_SMALLINT, 3),
[16] = getop_equal_value_type (240, 240, 241),
[17] = getop_is_false_jmp (240, 2),
[17] = getop_is_false_jmp_up (240, 0, 15),
/* assert (a[0] === 12.0); */
[18] = getop_assignment (240, OPCODE_ARG_TYPE_SMALLINT, 0),
[19] = getop_prop_getter (240, 0, 240),
[20] = getop_assignment (241, OPCODE_ARG_TYPE_NUMBER, 5),
[21] = getop_equal_value_type (240, 240, 241),
[22] = getop_is_false_jmp (240, 2),
[22] = getop_is_false_jmp_up (240, 0, 20),
/* assert (a['1'] === 'length'); */
[23] = getop_assignment (240, OPCODE_ARG_TYPE_STRING, 3),
[24] = getop_prop_getter (240, 0, 240),
[25] = getop_assignment (241, OPCODE_ARG_TYPE_STRING, 2),
[26] = getop_equal_value_type (240, 240, 241),
[27] = getop_is_false_jmp (240, 2),
[27] = getop_is_false_jmp_up (240, 0, 25),
/* assert (a[2.0] === null); */
[28] = getop_assignment (240, OPCODE_ARG_TYPE_NUMBER, 4),
[29] = getop_prop_getter (240, 0, 240),
[30] = getop_assignment (241, OPCODE_ARG_TYPE_SIMPLE, ECMA_SIMPLE_VALUE_NULL),
[31] = getop_equal_value_type (240, 240, 241),
[32] = getop_is_false_jmp (240, 2),
[32] = getop_is_false_jmp_up (240, 0, 30),
/* assert (a[2.5] === undefined); */
[33] = getop_assignment (240, OPCODE_ARG_TYPE_NUMBER, 6),
[34] = getop_prop_getter (240, 0, 240),
[35] = getop_assignment (241, OPCODE_ARG_TYPE_SIMPLE, ECMA_SIMPLE_VALUE_UNDEFINED),
[36] = getop_equal_value_type (240, 240, 241),
[37] = getop_is_false_jmp (240, 2),
[37] = getop_is_false_jmp_up (240, 0, 35),
/* a.length = 1; */
[38] = getop_assignment (240, OPCODE_ARG_TYPE_STRING, 2),
@ -92,27 +92,27 @@ main( int __unused argc,
[42] = getop_prop_getter (240, 0, 240),
[43] = getop_assignment (241, OPCODE_ARG_TYPE_SMALLINT, 1),
[44] = getop_equal_value_type (240, 240, 241),
[45] = getop_is_false_jmp (240, 2),
[45] = getop_is_false_jmp_up (240, 0, 43),
/* assert (a[0] === 12.0); */
[46] = getop_assignment (240, OPCODE_ARG_TYPE_SMALLINT, 0),
[47] = getop_prop_getter (240, 0, 240),
[48] = getop_assignment (241, OPCODE_ARG_TYPE_NUMBER, 5),
[49] = getop_equal_value_type (240, 240, 241),
[50] = getop_is_false_jmp (240, 2),
[50] = getop_is_false_jmp_up (240, 0, 48),
/* assert (a['1'] === undefined); */
[51] = getop_assignment (240, OPCODE_ARG_TYPE_STRING, 3),
[52] = getop_prop_getter (240, 0, 240),
[53] = getop_assignment (241, OPCODE_ARG_TYPE_SIMPLE, ECMA_SIMPLE_VALUE_UNDEFINED),
[54] = getop_equal_value_type (240, 240, 241),
[55] = getop_is_false_jmp (240, 2),
[55] = getop_is_false_jmp_up (240, 0, 53),
/* assert (a[2.0] === undefined); */
[56] = getop_assignment (240, OPCODE_ARG_TYPE_NUMBER, 4),
[57] = getop_prop_getter (240, 0, 240),
[58] = getop_equal_value_type (240, 240, 241),
[59] = getop_is_false_jmp (240, 2),
[59] = getop_is_false_jmp_up (240, 0, 57),
/* a.length = 8; */
[60] = getop_assignment (240, OPCODE_ARG_TYPE_STRING, 2),
@ -124,7 +124,7 @@ main( int __unused argc,
[64] = getop_prop_getter (240, 0, 240),
[65] = getop_assignment (241, OPCODE_ARG_TYPE_SMALLINT, 8),
[66] = getop_equal_value_type (240, 240, 241),
[67] = getop_is_false_jmp (240, 2),
[67] = getop_is_false_jmp_up (240, 0, 65),
/* a[10] = true; */
[68] = getop_assignment (240, OPCODE_ARG_TYPE_SMALLINT, 10),
@ -136,34 +136,34 @@ main( int __unused argc,
[72] = getop_prop_getter (240, 0, 240),
[73] = getop_assignment (241, OPCODE_ARG_TYPE_SMALLINT, 11),
[74] = getop_equal_value_type (240, 240, 241),
[75] = getop_is_false_jmp (240, 2),
[75] = getop_is_false_jmp_up (240, 0, 73),
/* assert (a[0] === 12.0); */
[76] = getop_assignment (240, OPCODE_ARG_TYPE_SMALLINT, 0),
[77] = getop_prop_getter (240, 0, 240),
[78] = getop_assignment (241, OPCODE_ARG_TYPE_NUMBER, 5),
[79] = getop_equal_value_type (240, 240, 241),
[80] = getop_is_false_jmp (240, 2),
[80] = getop_is_false_jmp_up (240, 0, 78),
/* assert (a['1'] === undefined); */
[81] = getop_assignment (240, OPCODE_ARG_TYPE_STRING, 3),
[82] = getop_prop_getter (240, 0, 240),
[83] = getop_assignment (241, OPCODE_ARG_TYPE_SIMPLE, ECMA_SIMPLE_VALUE_UNDEFINED),
[84] = getop_equal_value_type (240, 240, 241),
[85] = getop_is_false_jmp (240, 2),
[85] = getop_is_false_jmp_up (240, 0, 83),
/* assert (a[2.0] === undefined); */
[86] = getop_assignment (240, OPCODE_ARG_TYPE_NUMBER, 4),
[87] = getop_prop_getter (240, 0, 240),
[88] = getop_equal_value_type (240, 240, 241),
[89] = getop_is_false_jmp (240, 2),
[89] = getop_is_false_jmp_up (240, 0, 87),
/* assert (a[17] === true); */
[90] = getop_assignment (240, OPCODE_ARG_TYPE_SMALLINT, 10),
[91] = getop_prop_getter (240, 0, 240),
[92] = getop_assignment (241, OPCODE_ARG_TYPE_SIMPLE, ECMA_SIMPLE_VALUE_TRUE),
[93] = getop_equal_value_type (240, 240, 241),
[94] = getop_is_false_jmp (240, 2),
[94] = getop_is_false_jmp_up (240, 0, 92),
[95] = getop_exitval (0),
};
@ -186,6 +186,7 @@ main( int __unused argc,
bool status = run_int();
serializer_free ();
mem_heap_print (true, false, true);
mem_finalize (false);
return (status ? 0 : 1);

View File

@ -27,18 +27,18 @@ main( int __unused argc,
char __unused **argv)
{
const opcode_t test_program[] = {
/* 0: */ getop_reg_var_decl( 255, 255),
/* 1: */ getop_var_decl( 0),
/* 2: */ getop_var_decl( 1),
/* 3: */ getop_assignment( 0, OPCODE_ARG_TYPE_STRING, 1),
/* 4: */ getop_assignment( 1, OPCODE_ARG_TYPE_VARIABLE, 0),
/* 5: */ getop_is_true_jmp( 1, 7),
/* 6: */ getop_jmp_down( 5),
/* 7: */ getop_assignment( 0, OPCODE_ARG_TYPE_SMALLINT, 253),
/* 8: */ getop_assignment( 1, OPCODE_ARG_TYPE_NUMBER, 2),
/* 9: */ getop_is_false_jmp( 1, 11),
/* 10: */ getop_exitval( 0),
/* 11: */ getop_exitval( 1)
[ 0] = getop_reg_var_decl (255, 255),
[ 1] = getop_var_decl (0),
[ 2] = getop_var_decl (1),
[ 3] = getop_assignment (0, OPCODE_ARG_TYPE_STRING, 1),
[ 4] = getop_assignment (1, OPCODE_ARG_TYPE_VARIABLE, 0),
[ 5] = getop_is_true_jmp_down (1, 0, 2),
[ 6] = getop_jmp_down (0, 5),
[ 7] = getop_assignment (0, OPCODE_ARG_TYPE_SMALLINT, 253),
[ 8] = getop_assignment (1, OPCODE_ARG_TYPE_NUMBER, 2),
[ 9] = getop_is_false_jmp_down (1, 0, 2),
[10] = getop_exitval (0),
[11] = getop_exitval (1)
};
mem_init();

View File

@ -28,7 +28,7 @@ main( int __unused argc,
{
const opcode_t test_program[] = {
[ 0] = getop_reg_var_decl (240, 255),
[ 1] = getop_jmp_down (2),
[ 1] = getop_jmp_down (0, 2),
[ 2] = getop_exitval (1),
/* var a, b; */
@ -82,14 +82,14 @@ main( int __unused argc,
[36] = getop_prop_getter (240, 0, 240),
[37] = getop_assignment (241, OPCODE_ARG_TYPE_STRING, 5),
[38] = getop_equal_value_type (240, 240, 241),
[39] = getop_is_false_jmp (240, 2),
[39] = getop_is_false_jmp_up (240, 0, 37),
/* assert (a.property2 === 1); */
[40] = getop_assignment (240, OPCODE_ARG_TYPE_STRING, 3),
[41] = getop_prop_getter (240, 0, 240),
[42] = getop_assignment (241, OPCODE_ARG_TYPE_SMALLINT, 1),
[43] = getop_equal_value_type (240, 240, 241),
[44] = getop_is_false_jmp (240, 2),
[44] = getop_is_false_jmp_up (240, 0, 42),
/* a.property3 = 'value2'; */
[45] = getop_assignment (240, OPCODE_ARG_TYPE_STRING, 4),
@ -101,7 +101,7 @@ main( int __unused argc,
[49] = getop_prop_getter (240, 0, 240),
[50] = getop_assignment (241, OPCODE_ARG_TYPE_STRING, 6),
[51] = getop_equal_value_type (240, 240, 241),
[52] = getop_is_false_jmp (240, 2),
[52] = getop_is_false_jmp_up (240, 0, 50),
/* a.property2 = 2.5; */
[53] = getop_assignment (240, OPCODE_ARG_TYPE_STRING, 3),
@ -113,7 +113,7 @@ main( int __unused argc,
[57] = getop_prop_getter (240, 0, 240),
[58] = getop_assignment (241, OPCODE_ARG_TYPE_SMALLINT, 25),
[59] = getop_equal_value_type (240, 240, 241),
[60] = getop_is_false_jmp (240, 2),
[60] = getop_is_false_jmp_up (240, 0, 58),
/* b = delete a[b]; */
[61] = getop_delete_prop (1, 0, 1),
@ -121,14 +121,14 @@ main( int __unused argc,
/* assert (b === true); */
[62] = getop_assignment (240, OPCODE_ARG_TYPE_SIMPLE, ECMA_SIMPLE_VALUE_TRUE),
[63] = getop_equal_value_type (240, 240, 1),
[64] = getop_is_false_jmp (240, 2),
[64] = getop_is_false_jmp_up (240, 0, 62),
/* assert (a.property1 === undefined); */
[65] = getop_assignment (240, OPCODE_ARG_TYPE_STRING, 2),
[66] = getop_prop_getter (240, 0, 240),
[67] = getop_assignment (241, OPCODE_ARG_TYPE_SIMPLE, ECMA_SIMPLE_VALUE_UNDEFINED),
[68] = getop_equal_value_type (240, 240, 241),
[69] = getop_is_false_jmp (240, 2),
[69] = getop_is_false_jmp_up (240, 0, 67),
[70] = getop_exitval (0)
};

View File

@ -1,94 +0,0 @@
/* 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 "globals.h"
#include "interpreter.h"
#include "mem-allocator.h"
#include "opcodes.h"
#include "serializer.h"
#include "optimizer-passes.h"
#include "jerry-libc.h"
#include "deserializer.h"
#include "common.h"
/**
* Unit test's main function.
*/
int
main( int __unused argc,
char __unused **argv)
{
opcode_t test_program[] = {
[0] = getop_assignment( 0, OPCODE_ARG_TYPE_STRING, 1),
[1] = getop_assignment( 1, OPCODE_ARG_TYPE_VARIABLE, 0),
[2] = getop_is_false_jmp (0, 10),
[3] = getop_is_true_jmp (0, 6),
[4] = getop_jmp_up (1),
[5] = getop_jmp_up (4),
[6] = getop_jmp_down (1),
[7] = getop_jmp_down (2),
[8] = getop_jmp_down (2),
[9] = getop_assignment (0, OPCODE_ARG_TYPE_SMALLINT, 253),
[10] = getop_exitval (0)
};
mem_init();
const char *strings[] = { "a",
"b" };
ecma_number_t nums [] = { 2 };
serializer_init (true);
uint16_t offset = serializer_dump_strings (strings, 2);
serializer_dump_nums (nums, 1, offset, 2);
for (int i = 0; i < 11; i++)
serializer_dump_opcode (test_program[i]);
opcode_t * opcodes = (opcode_t *) deserialize_bytecode ();
optimizer_move_opcodes (opcodes + 9, opcodes + 2, 1);
if (!opcodes_equal (opcodes, (opcode_t[]) {
[0] = getop_assignment( 0, OPCODE_ARG_TYPE_STRING, 1),
[1] = getop_assignment( 1, OPCODE_ARG_TYPE_VARIABLE, 0),
[2] = getop_assignment (0, OPCODE_ARG_TYPE_SMALLINT, 253),
[3] = getop_is_false_jmp (0, 10),
[4] = getop_is_true_jmp (0, 6),
[5] = getop_jmp_up (1),
[6] = getop_jmp_up (4),
[7] = getop_jmp_down (1),
[8] = getop_jmp_down (2),
[9] = getop_jmp_down (2),
[10] = getop_exitval (0)
}, 11))
return 1;
optimizer_adjust_jumps (opcodes + 3, opcodes + 10, 1);
if (!opcodes_equal (opcodes, (opcode_t[]) {
[0] = getop_assignment( 0, OPCODE_ARG_TYPE_STRING, 1),
[1] = getop_assignment( 1, OPCODE_ARG_TYPE_VARIABLE, 0),
[2] = getop_assignment (0, OPCODE_ARG_TYPE_SMALLINT, 253),
[3] = getop_is_false_jmp (0, 10),
[4] = getop_is_true_jmp (0, 7),
[5] = getop_jmp_up (1),
[6] = getop_jmp_up (5),
[7] = getop_jmp_down (1),
[8] = getop_jmp_down (2),
[9] = getop_jmp_down (1),
[10] = getop_exitval (0)
}, 11))
return 1;
return 0;
}

View File

@ -1,98 +0,0 @@
/* 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 "globals.h"
#include "serializer.h"
#include "optimizer-passes.h"
#include "jerry-libc.h"
#include "deserializer.h"
#include "common.h"
#include "lexer.h"
#include "parser.h"
#include "mem-allocator.h"
#include "opcodes.h"
#define MAX_STRINGS 100
#define MAX_NUMS 25
/**
* Unit test's main function.
*/
int
main( int __unused argc,
char __unused **argv)
{
const char *strings[MAX_STRINGS];
ecma_number_t nums[MAX_NUMS];
uint8_t strings_num, nums_count;
uint16_t offset;
const opcode_t *opcodes;
const char *source = "for (var i = 0; i < 10; i++) {\n"
" var j = 10;\n"
"}\n"
"for (var i = 0; i < 10; i++) {\n"
" var j = 10;\n"
"}";
mem_init ();
serializer_init (true);
lexer_init (source, __strlen (source), true);
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_parse_program ();
opcodes = deserialize_bytecode ();
serializer_print_opcodes ();
if (!opcodes_equal (opcodes, (opcode_t[]) {
[0] = getop_reg_var_decl (2, 5), // var tmp2 .. tmp5;
[1] = getop_var_decl (0), // var i;
[2] = getop_var_decl (1), // var j;
[3] = getop_assignment (2, 1, 0), // tmp2 = 0;
[4] = getop_assignment (0, 4, 2), // i = tmp2;
[5] = getop_assignment (4, 1, 10),// tmp4 = 10;
[6] = getop_less_than (3, 0, 4), // tmp3 = i < tmp4;
[7] = getop_is_false_jmp (3, 14), // if (!tmp3) goto 14;
[8] = getop_jmp_down (3), // goto 11;
[9] = getop_post_incr (5, 0), // tmp5 = i ++;
[10] = getop_jmp_up (5), // goto 5;
[11] = getop_assignment (2, 1, 10),// tmp2 = 10;
[12] = getop_assignment (1, 4, 2), // j = tmp2;
[13] = getop_jmp_up (5), // goto 8;
[14] = getop_nop (), // ;
[15] = getop_assignment (2, 1, 0), // tmp2 = 0;
[16] = getop_assignment (0, 4, 2), // i = tmp2;
[17] = getop_assignment (4, 1, 10),// tmp7 = 10;
[18] = getop_less_than (3, 0, 4), // tmp3 = i < tmp7;
[19] = getop_is_false_jmp (3, 27), // if (!tmp3) goto 27;
[20] = getop_jmp_down (3), // goto 23;
[21] = getop_post_incr (5, 0), // tmp5 = i ++;
[22] = getop_jmp_up (5), // goto 17;
[23] = getop_nop (), // ;
[24] = getop_assignment (2, 1, 10),// tmp2 = 10;
[25] = getop_assignment (1, 4, 5), // j = tmp2;
[26] = getop_jmp_up (5), // goto 21;
[27] = getop_exitval (0) // exit 0;
}, 28))
return 1;
return 0;
}

View File

@ -1,75 +0,0 @@
/* 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 "globals.h"
#include "interpreter.h"
#include "mem-allocator.h"
#include "opcodes.h"
#include "serializer.h"
#include "optimizer-passes.h"
#include "jerry-libc.h"
#include "deserializer.h"
#include "common.h"
/**
* Unit test's main function.
*/
int
main( int __unused argc,
char __unused **argv)
{
// Honestly, after RETVAL there must be RET
opcode_t test_program[] = {
[0] = getop_reg_var_decl (5, 5), // tmp6
[1] = getop_assignment (0, OPCODE_ARG_TYPE_STRING, 1), // a = "b"
[2] = getop_var_decl (1), // var b
[3] = getop_func_decl_0 (2), // function c()
[4] = getop_jmp_down (3), // {
[5] = getop_var_decl (1), // var b
[6] = getop_retval (1), // return b; }
[7] = getop_assignment (5, OPCODE_ARG_TYPE_STRING, 3), // "use strict"
[8] = getop_exitval (0)
};
mem_init();
const char *strings[] = { "a", "b", "c", "use strict" };
ecma_number_t nums [] = { 2 };
serializer_init (true);
uint16_t offset = serializer_dump_strings (strings, 4);
serializer_dump_nums (nums, 1, offset, 4);
for (int i = 0; i < 9; i++)
serializer_dump_opcode (test_program[i]);
opcode_t * opcodes = (opcode_t *) deserialize_bytecode ();
optimizer_reorder_scope (1, 8);
if (!opcodes_equal (opcodes, (opcode_t[]) {
[0] = getop_reg_var_decl (5, 5), // tmp6
[1] = getop_assignment (5, OPCODE_ARG_TYPE_STRING, 3), // "use strict"
[2] = getop_func_decl_0 (2), // function c()
[3] = getop_jmp_down (3), // {
[4] = getop_var_decl (1), // var b
[5] = getop_retval (1), // return b; }
[6] = getop_var_decl (1), // var b
[7] = getop_assignment (0, OPCODE_ARG_TYPE_STRING, 1), // a = "b"
[8] = getop_exitval (0)
}, 9))
return 1;
return 0;
}

View File

@ -38,11 +38,11 @@ main( int __unused argc,
[ 8] = getop_meta (OPCODE_META_TYPE_CATCH, 0, 14),
[ 9] = getop_meta (OPCODE_META_TYPE_CATCH_EXCEPTION_IDENTIFIER, 2, 255),
[10] = getop_equal_value_type (0, 1, 2),
[11] = getop_is_true_jmp (0, 14),
[11] = getop_is_true_jmp_down (0, 0, 3),
[12] = getop_exitval (1),
[13] = getop_assignment (0, OPCODE_ARG_TYPE_SIMPLE, ECMA_SIMPLE_VALUE_FALSE),
[14] = getop_meta (OPCODE_META_TYPE_FINALLY, 0, 18),
[15] = getop_is_false_jmp (0, 17),
[15] = getop_is_false_jmp_down (0, 0, 2),
[16] = getop_exitval (0),
[17] = getop_exitval (1),
[18] = getop_meta (OPCODE_META_TYPE_END_TRY_CATCH_FINALLY, 255, 255),

View File

@ -27,11 +27,11 @@ main( int __unused argc,
char __unused **argv)
{
const opcode_t test_program[] = {
/* 0: */ getop_reg_var_decl( 255, 255),
/* 1: */ getop_var_decl( 0),
/* 2: */ getop_is_true_jmp( 0, 4),
/* 3: */ getop_exitval( 0),
/* 4: */ getop_exitval( 1)
[0] = getop_reg_var_decl( 255, 255),
[1] = getop_var_decl( 0),
[2] = getop_is_true_jmp_down( 0, 0, 2),
[3] = getop_exitval( 0),
[4] = getop_exitval( 1)
};
mem_init();