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:
+1
-1
@@ -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) \
|
||||
|
||||
@@ -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 */
|
||||
+58
-58
@@ -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;
|
||||
|
||||
+1210
-894
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 ();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user