mirror of
https://github.com/jerryscript-project/jerryscript.git
synced 2025-12-15 16:29:21 +00:00
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:
parent
cd41b236d9
commit
e77bd4f4e5
1
.gitignore
vendored
1
.gitignore
vendored
@ -27,6 +27,7 @@ core
|
||||
vgcore.*
|
||||
**.orig
|
||||
**.directory
|
||||
**.patch
|
||||
|
||||
# ctags and ID database
|
||||
tags
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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 */
|
||||
}
|
||||
|
||||
@ -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
180
src/libintstructs/stack.h
Normal 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 */
|
||||
@ -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
|
||||
|
||||
@ -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
@ -20,6 +20,7 @@
|
||||
|
||||
void parser_init (void);
|
||||
void parser_parse_program (void);
|
||||
void parser_free (void);
|
||||
|
||||
void parser_fatal (jerry_status_t code);
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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)
|
||||
{
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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 ();
|
||||
|
||||
|
||||
@ -37,6 +37,7 @@ main( int __unused argc,
|
||||
};
|
||||
|
||||
mem_init();
|
||||
serializer_init (false);
|
||||
|
||||
const char *strings[] = { "a",
|
||||
"b" };
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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)
|
||||
};
|
||||
|
||||
@ -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;
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
@ -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),
|
||||
|
||||
@ -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();
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user