Add generation of prop_setter.

This commit is contained in:
Ilmir Usmanov
2014-09-24 15:30:37 +04:00
parent 25ec2bea17
commit 0738ec6a54
9 changed files with 510 additions and 270 deletions
+150
View File
@@ -0,0 +1,150 @@
/* 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 create and manipulate hash-tables.
In order to define a hash use HASH_TABLE or STATIC_HASH_TABLE macro.
DO NOT FORGET to define KEY_TYPE##_hash and KEY_TYPE##_equal functions, they will be used
for internal purposes.
Before using the hash initialize it by calling HASH_INIT macro.
To insert a key-value pair, use HASH_INSERT macro.
To lookup a value by the key, use HASH_LOOKUP macro.
After using the hash, delete it by calling HASH_FREE macro.
*/
#ifndef HASH_TABLE_H
#define HASH_TABLE_H
#define DEFINE_BACKET_TYPE(NAME, KEY_TYPE, VALUE_TYPE) \
typedef struct \
{ \
KEY_TYPE key; \
VALUE_TYPE value; \
} \
__packed \
NAME##_backet;
#define DEFINE_HASH_TYPE(NAME, KEY_TYPE, VALUE_TYPE) \
typedef struct \
{ \
uint8_t size; \
NAME##_backet_stack *backets; \
} \
__packed \
NAME##_hash_table;
#define HASH_INIT(NAME, SIZE) \
do { \
NAME.size = SIZE; \
size_t size = mem_heap_recommend_allocation_size (SIZE * sizeof (NAME##_backet_stack)); \
NAME.backets = (NAME##_backet_stack *) mem_heap_alloc_block (size, MEM_HEAP_ALLOC_SHORT_TERM); \
__memset (NAME.backets, 0, size); \
} while (0);
#define HASH_FREE(NAME) \
do { \
for (uint8_t i = 0; i < NAME.size; i++) { \
if (NAME.backets[i].length != 0) { \
mem_heap_free_block ((uint8_t *) NAME.backets[i].data); \
} \
} \
mem_heap_free_block ((uint8_t *) NAME.backets); \
} while (0)
#define DEFINE_HASH_INSERT(NAME, KEY_TYPE, VALUE_TYPE) \
static void hash_insert_##NAME (KEY_TYPE key, VALUE_TYPE value) __unused; \
static void hash_insert_##NAME (KEY_TYPE key, VALUE_TYPE value) { \
NAME##_backet backet = (NAME##_backet) { .key = key, .value = value }; \
uint8_t hash = KEY_TYPE##_hash (key); \
JERRY_ASSERT (hash < NAME.size); \
JERRY_ASSERT (NAME.backets != NULL); \
if (NAME.backets[hash].length == 0) \
{ \
size_t stack_size = mem_heap_recommend_allocation_size (0); \
NAME.backets[hash].data = (NAME##_backet *) mem_heap_alloc_block \
(stack_size, MEM_HEAP_ALLOC_SHORT_TERM); \
NAME.backets[hash].current = 0; \
NAME.backets[hash].length = (__typeof__ (NAME.backets[hash].length)) \
(stack_size / sizeof (NAME##_backet)); \
} \
else if (NAME.backets[hash].current == NAME.backets[hash].length) \
{ \
size_t old_size = NAME.backets[hash].length * sizeof (NAME##_backet); \
size_t temp1_size = mem_heap_recommend_allocation_size ( \
(size_t) (sizeof (NAME##_backet))); \
size_t new_size = mem_heap_recommend_allocation_size ( \
(size_t) (temp1_size + old_size)); \
NAME##_backet *temp1 = (NAME##_backet *) mem_heap_alloc_block \
(temp1_size, MEM_HEAP_ALLOC_SHORT_TERM); \
NAME##_backet *temp2 = (NAME##_backet *) 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.backets[hash].data, old_size); \
mem_heap_free_block ((uint8_t *) NAME.backets[hash].data); \
mem_heap_free_block ((uint8_t *) temp1); \
NAME.backets[hash].data = (NAME##_backet *) mem_heap_alloc_block \
(new_size, MEM_HEAP_ALLOC_SHORT_TERM); \
__memcpy (NAME.backets[hash].data, temp2, old_size); \
mem_heap_free_block ((uint8_t *) temp2); \
NAME.backets[hash].length = (__typeof__ (NAME.backets[hash].length)) \
(new_size / sizeof (NAME##_backet)); \
} \
NAME.backets[hash].data[NAME.backets[hash].current++] = backet; \
}
#define HASH_INSERT(NAME, KEY, VALUE) \
do { \
hash_insert_##NAME (KEY, VALUE); \
} while (0)
#define DEFINE_HASH_LOOKUP(NAME, KEY_TYPE, VALUE_TYPE) \
static VALUE_TYPE *lookup_##NAME (KEY_TYPE key) __unused; \
static VALUE_TYPE *lookup_##NAME (KEY_TYPE key) { \
uint8_t hash = KEY_TYPE##_hash (key); \
JERRY_ASSERT (hash < NAME.size); \
if (NAME.backets[hash].length == 0) { \
return NULL; \
} \
for (size_t i = 0; i < NAME.backets[hash].current; i++) { \
if (KEY_TYPE##_equal (NAME.backets[hash].data[i].key, key)) { \
return &NAME.backets[hash].data[i].value; \
} \
} \
return NULL; \
}
#define HASH_LOOKUP(NAME, KEY) \
lookup_##NAME (KEY)
#define HASH_TABLE(NAME, KEY_TYPE, VALUE_TYPE) \
DEFINE_BACKET_TYPE (NAME, KEY_TYPE, VALUE_TYPE) \
DEFINE_STACK_TYPE (NAME##_backet, uint8_t, NAME##_backet) \
DEFINE_HASH_TYPE (NAME, KEY_TYPE, VALUE_TYPE) \
NAME##_hash_table NAME; \
DEFINE_HASH_INSERT (NAME, KEY_TYPE, VALUE_TYPE) \
DEFINE_HASH_LOOKUP (NAME, KEY_TYPE, VALUE_TYPE)
#define STATIC_HASH_TABLE(NAME, KEY_TYPE, VALUE_TYPE) \
DEFINE_BACKET_TYPE (NAME, KEY_TYPE, VALUE_TYPE) \
DEFINE_STACK_TYPE (NAME##_backet, uint8_t, NAME##_backet) \
DEFINE_HASH_TYPE (NAME, KEY_TYPE, VALUE_TYPE) \
static NAME##_hash_table NAME; \
DEFINE_HASH_INSERT (NAME, KEY_TYPE, VALUE_TYPE) \
DEFINE_HASH_LOOKUP (NAME, KEY_TYPE, VALUE_TYPE)
#endif /* HASH_TABLE_H */
+3 -3
View File
@@ -130,9 +130,9 @@ increase_##NAME##_stack_size (__typeof__ (NAME.length) elements_count) { \
}
#define DEFINE_DECREASE_STACE_SIZE(NAME) \
static void decrease_##NAME##_stack_size (uint8_t) __unused; \
static void decrease_##NAME##_stack_size (__typeof__ (NAME.length)) __unused; \
static void \
decrease_##NAME##_stack_size (uint8_t elements_count) { \
decrease_##NAME##_stack_size (__typeof__ (NAME.length) elements_count) { \
JERRY_ASSERT (NAME.current - elements_count >= NAME##_global_size); \
NAME.current = (__typeof__ (NAME.current)) (NAME.current - elements_count); \
}
@@ -150,7 +150,7 @@ do { \
} while (0)
#define STACK_DROP(NAME, I) \
do { decrease_##NAME##_stack_size (I); } while (0)
do { decrease_##NAME##_stack_size ((__typeof__(NAME.current))(I)); } while (0)
#define STACK_CLEAN(NAME) \
STACK_DROP (NAME, NAME.current - NAME##_global_size);
+324 -246
View File
@@ -21,6 +21,8 @@
#include "serializer.h"
#include "interpreter.h"
#include "stack.h"
#include "hash-table.h"
#include "deserializer.h"
#define INVALID_VALUE 255
#define INTRINSICS_COUNT 1
@@ -135,10 +137,125 @@ JERRY_ASSERT (IDX.current == IDX_current + 1);
#define STACK_CHECK_USAGE_LHS() ;
#endif
static uint8_t lp_string_hash (lp_string);
STATIC_HASH_TABLE (intrinsics, lp_string, intrinsic_dumper)
#define LAST_OPCODE_IS(OP) (deserialize_opcode((opcode_counter_t)(OPCODE_COUNTER()-1)).op_idx == __op__idx_##OP)
JERRY_STATIC_ASSERT (sizeof (idx_t) == sizeof (uint8_t));
JERRY_STATIC_ASSERT (sizeof (opcode_counter_t) == sizeof (uint16_t));
static void skip_newlines (void);
#define NEXT(TYPE) \
do { skip_newlines (); parse_##TYPE (); } while (0)
#define DUMP_VOID_OPCODE(GETOP) \
do { \
OPCODE()=getop_##GETOP (); \
serializer_dump_opcode (OPCODE()); \
OPCODE_COUNTER()++; \
} while (0)
#define DUMP_OPCODE_1(GETOP, OP1) \
do { \
JERRY_ASSERT (0+OP1 <= 255); \
OPCODE()=getop_##GETOP ((idx_t) (OP1)); \
serializer_dump_opcode (OPCODE()); \
OPCODE_COUNTER()++; \
} while (0)
#define DUMP_OPCODE_2(GETOP, OP1, OP2) \
do { \
JERRY_ASSERT (0+OP1 <= 255); \
JERRY_ASSERT (0+OP2 <= 255); \
OPCODE()=getop_##GETOP ((idx_t) (OP1), (idx_t) (OP2)); \
serializer_dump_opcode (OPCODE()); \
OPCODE_COUNTER()++; \
} while (0)
#define DUMP_OPCODE_3(GETOP, OP1, OP2, OP3) \
do { \
JERRY_ASSERT (0+OP1 <= 255); \
JERRY_ASSERT (0+OP2 <= 255); \
JERRY_ASSERT (0+OP3 <= 255); \
OPCODE()=getop_##GETOP ((idx_t) (OP1), (idx_t) (OP2), (idx_t) (OP3)); \
serializer_dump_opcode (OPCODE()); \
OPCODE_COUNTER()++; \
} while (0)
#define REWRITE_VOID_OPCODE(OC, GETOP) \
do { \
OPCODE()=getop_##GETOP (); \
serializer_rewrite_opcode (OC, OPCODE()); \
} while (0)
#define REWRITE_OPCODE_1(OC, GETOP, OP1) \
do { \
JERRY_ASSERT (0+OP1 <= 255); \
OPCODE()=getop_##GETOP ((idx_t) (OP1)); \
serializer_rewrite_opcode (OC, OPCODE()); \
} while (0)
#define REWRITE_OPCODE_2(OC, GETOP, OP1, OP2) \
do { \
JERRY_ASSERT (0+OP1 <= 255); \
JERRY_ASSERT (0+OP2 <= 255); \
OPCODE()=getop_##GETOP ((idx_t) (OP1), (idx_t) (OP2)); \
serializer_rewrite_opcode (OC, OPCODE()); \
} while (0)
#define REWRITE_OPCODE_3(OC, GETOP, OP1, OP2, OP3) \
do { \
JERRY_ASSERT (0+OP1 <= 255); \
JERRY_ASSERT (0+OP2 <= 255); \
JERRY_ASSERT (0+OP3 <= 255); \
OPCODE()=getop_##GETOP ((idx_t) (OP1), (idx_t) (OP2), (idx_t) (OP3)); \
serializer_rewrite_opcode (OC, OPCODE()); \
} while (0)
#define REWRITE_COND_JMP(OC, GETOP, DIFF) \
do { \
JERRY_ASSERT (0+DIFF <= 256*256 - 1); \
STACK_DECLARE_USAGE (IDX); \
JERRY_STATIC_ASSERT (sizeof (idx_t) == 1); \
STACK_PUSH (IDX, (idx_t) ((DIFF) >> JERRY_BITSINBYTE)); \
STACK_PUSH (IDX, (idx_t) ((DIFF) & ((1 << JERRY_BITSINBYTE) - 1))); \
JERRY_ASSERT ((DIFF) == calc_opcode_counter_from_idx_idx (STACK_HEAD (IDX, 2), STACK_HEAD (IDX, 1))); \
OPCODE()=getop_##GETOP (STACK_HEAD (IDX, 3), STACK_HEAD (IDX, 2), STACK_HEAD (IDX, 1)); \
serializer_rewrite_opcode (OC, OPCODE()); \
STACK_DROP (IDX, 2); \
STACK_CHECK_USAGE (IDX); \
} while (0)
#define REWRITE_JMP(OC, GETOP, DIFF) \
do { \
JERRY_ASSERT (0+DIFF <= 256*256 - 1); \
STACK_DECLARE_USAGE (IDX) \
JERRY_STATIC_ASSERT (sizeof (idx_t) == 1); \
STACK_PUSH (IDX, (idx_t) ((DIFF) >> JERRY_BITSINBYTE)); \
STACK_PUSH (IDX, (idx_t) ((DIFF) & ((1 << JERRY_BITSINBYTE) - 1))); \
JERRY_ASSERT ((DIFF) == calc_opcode_counter_from_idx_idx (STACK_HEAD (IDX, 2), STACK_HEAD (IDX, 1))); \
OPCODE()=getop_##GETOP (STACK_HEAD (IDX, 2), STACK_HEAD (IDX, 1)); \
serializer_rewrite_opcode (OC, OPCODE()); \
STACK_DROP (IDX, 2); \
STACK_CHECK_USAGE (IDX); \
} while (0)
#define REWRITE_TRY(OC) \
do { \
STACK_DECLARE_USAGE (IDX) \
JERRY_STATIC_ASSERT (sizeof (idx_t) == 1); \
STACK_PUSH (IDX, (idx_t) ((OPCODE_COUNTER ()) >> JERRY_BITSINBYTE)); \
STACK_PUSH (IDX, (idx_t) ((OPCODE_COUNTER ()) & ((1 << JERRY_BITSINBYTE) - 1))); \
JERRY_ASSERT ((OPCODE_COUNTER ()) \
== calc_opcode_counter_from_idx_idx (STACK_HEAD (IDX, 2), STACK_HEAD (IDX, 1))); \
OPCODE()=getop_try (STACK_HEAD (IDX, 2), STACK_HEAD (IDX, 1)); \
serializer_rewrite_opcode ((OC), OPCODE()); \
STACK_DROP (IDX, 2); \
STACK_CHECK_USAGE (IDX); \
} while (0)
typedef enum
{
AL_FUNC_DECL,
@@ -150,131 +267,6 @@ typedef enum
}
argument_list_type;
#define DEFINE_BACKET_TYPE(NAME, KEY_TYPE, VALUE_TYPE) \
typedef struct \
{ \
KEY_TYPE key; \
VALUE_TYPE value; \
} \
__packed \
NAME##_backet;
#define DEFINE_HASH_TYPE(NAME, KEY_TYPE, VALUE_TYPE) \
typedef struct \
{ \
uint8_t size; \
NAME##_backet_stack *backets; \
} \
__packed \
NAME##_hash_table;
#define HASH_INIT(NAME, SIZE) \
do { \
NAME.size = SIZE; \
size_t size = mem_heap_recommend_allocation_size (SIZE * sizeof (NAME##_backet_stack)); \
NAME.backets = (NAME##_backet_stack *) mem_heap_alloc_block (size, MEM_HEAP_ALLOC_SHORT_TERM); \
__memset (NAME.backets, 0, size); \
} while (0);
#define HASH_FREE(NAME) \
do { \
for (uint8_t i = 0; i < NAME.size; i++) { \
if (NAME.backets[i].length != 0) { \
mem_heap_free_block ((uint8_t *) NAME.backets[i].data); \
} \
} \
mem_heap_free_block ((uint8_t *) NAME.backets); \
} while (0)
#define DEFINE_HASH_INSERT(NAME, KEY_TYPE, VALUE_TYPE) \
static void hash_insert_##NAME (KEY_TYPE key, VALUE_TYPE value) __unused; \
static void hash_insert_##NAME (KEY_TYPE key, VALUE_TYPE value) { \
NAME##_backet backet = (NAME##_backet) { .key = key, .value = value }; \
uint8_t hash = KEY_TYPE##_hash (key); \
JERRY_ASSERT (hash < NAME.size); \
JERRY_ASSERT (NAME.backets != NULL); \
if (NAME.backets[hash].length == 0) \
{ \
size_t stack_size = mem_heap_recommend_allocation_size (0); \
NAME.backets[hash].data = (NAME##_backet *) mem_heap_alloc_block \
(stack_size, MEM_HEAP_ALLOC_SHORT_TERM); \
NAME.backets[hash].current = 0; \
NAME.backets[hash].length = (__typeof__ (NAME.backets[hash].length)) \
(stack_size / sizeof (NAME##_backet)); \
} \
else if (NAME.backets[hash].current == NAME.backets[hash].length) \
{ \
size_t old_size = NAME.backets[hash].length * sizeof (NAME##_backet); \
size_t temp1_size = mem_heap_recommend_allocation_size ( \
(size_t) (sizeof (NAME##_backet))); \
size_t new_size = mem_heap_recommend_allocation_size ( \
(size_t) (temp1_size + old_size)); \
NAME##_backet *temp1 = (NAME##_backet *) mem_heap_alloc_block \
(temp1_size, MEM_HEAP_ALLOC_SHORT_TERM); \
NAME##_backet *temp2 = (NAME##_backet *) 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.backets[hash].data, old_size); \
mem_heap_free_block ((uint8_t *) NAME.backets[hash].data); \
mem_heap_free_block ((uint8_t *) temp1); \
NAME.backets[hash].data = (NAME##_backet *) mem_heap_alloc_block \
(new_size, MEM_HEAP_ALLOC_SHORT_TERM); \
__memcpy (NAME.backets[hash].data, temp2, old_size); \
mem_heap_free_block ((uint8_t *) temp2); \
NAME.backets[hash].length = (__typeof__ (NAME.backets[hash].length)) \
(new_size / sizeof (NAME##_backet)); \
} \
NAME.backets[hash].data[NAME.backets[hash].current++] = backet; \
}
#define HASH_INSERT(NAME, KEY, VALUE) \
do { \
hash_insert_##NAME (KEY, VALUE); \
} while (0)
#define DEFINE_HASH_LOOKUP(NAME, KEY_TYPE, VALUE_TYPE) \
static VALUE_TYPE *lookup_##NAME (KEY_TYPE key) __unused; \
static VALUE_TYPE *lookup_##NAME (KEY_TYPE key) { \
uint8_t hash = KEY_TYPE##_hash (key); \
JERRY_ASSERT (hash < NAME.size); \
if (NAME.backets[hash].length == 0) { \
return NULL; \
} \
for (size_t i = 0; i < NAME.backets[hash].current; i++) { \
if (KEY_TYPE##_equal (NAME.backets[hash].data[i].key, key)) { \
return &NAME.backets[hash].data[i].value; \
} \
} \
return NULL; \
}
#define HASH_LOOKUP(NAME, KEY) \
lookup_##NAME (KEY)
#define HASH_TABLE(NAME, KEY_TYPE, VALUE_TYPE) \
DEFINE_BACKET_TYPE (NAME, KEY_TYPE, VALUE_TYPE) \
DEFINE_STACK_TYPE (NAME##_backet, uint8_t, NAME##_backet) \
DEFINE_HASH_TYPE (NAME, KEY_TYPE, VALUE_TYPE) \
NAME##_hash_table NAME; \
DEFINE_HASH_INSERT (NAME, KEY_TYPE, VALUE_TYPE) \
DEFINE_HASH_LOOKUP (NAME, KEY_TYPE, VALUE_TYPE)
#define STATIC_HASH_TABLE(NAME, KEY_TYPE, VALUE_TYPE) \
DEFINE_BACKET_TYPE (NAME, KEY_TYPE, VALUE_TYPE) \
DEFINE_STACK_TYPE (NAME##_backet, uint8_t, NAME##_backet) \
DEFINE_HASH_TYPE (NAME, KEY_TYPE, VALUE_TYPE) \
static NAME##_hash_table NAME; \
DEFINE_HASH_INSERT (NAME, KEY_TYPE, VALUE_TYPE) \
DEFINE_HASH_LOOKUP (NAME, KEY_TYPE, VALUE_TYPE)
static uint8_t lp_string_hash (lp_string);
STATIC_HASH_TABLE (intrinsics, lp_string, intrinsic_dumper)
static void parse_expression (void);
static void parse_statement (void);
static void parse_assignment_expression (void);
@@ -461,109 +453,6 @@ token_after_newlines_must_be_keyword (keyword kw)
}
}
#define NEXT(TYPE) \
do { skip_newlines (); parse_##TYPE (); } while (0)
#define DUMP_VOID_OPCODE(GETOP) \
do { \
OPCODE()=getop_##GETOP (); \
serializer_dump_opcode (OPCODE()); \
OPCODE_COUNTER()++; \
} while (0)
#define DUMP_OPCODE_1(GETOP, OP1) \
do { \
JERRY_ASSERT (0+OP1 <= 255); \
OPCODE()=getop_##GETOP ((idx_t) (OP1)); \
serializer_dump_opcode (OPCODE()); \
OPCODE_COUNTER()++; \
} while (0)
#define DUMP_OPCODE_2(GETOP, OP1, OP2) \
do { \
JERRY_ASSERT (0+OP1 <= 255); \
JERRY_ASSERT (0+OP2 <= 255); \
OPCODE()=getop_##GETOP ((idx_t) (OP1), (idx_t) (OP2)); \
serializer_dump_opcode (OPCODE()); \
OPCODE_COUNTER()++; \
} while (0)
#define DUMP_OPCODE_3(GETOP, OP1, OP2, OP3) \
do { \
JERRY_ASSERT (0+OP1 <= 255); \
JERRY_ASSERT (0+OP2 <= 255); \
JERRY_ASSERT (0+OP3 <= 255); \
OPCODE()=getop_##GETOP ((idx_t) (OP1), (idx_t) (OP2), (idx_t) (OP3)); \
serializer_dump_opcode (OPCODE()); \
OPCODE_COUNTER()++; \
} while (0)
#define REWRITE_OPCODE_1(OC, GETOP, OP1) \
do { \
JERRY_ASSERT (0+OP1 <= 255); \
OPCODE()=getop_##GETOP ((idx_t) (OP1)); \
serializer_rewrite_opcode (OC, OPCODE()); \
} while (0)
#define REWRITE_OPCODE_2(OC, GETOP, OP1, OP2) \
do { \
JERRY_ASSERT (0+OP1 <= 255); \
JERRY_ASSERT (0+OP2 <= 255); \
OPCODE()=getop_##GETOP ((idx_t) (OP1), (idx_t) (OP2)); \
serializer_rewrite_opcode (OC, OPCODE()); \
} while (0)
#define REWRITE_OPCODE_3(OC, GETOP, OP1, OP2, OP3) \
do { \
JERRY_ASSERT (0+OP1 <= 255); \
JERRY_ASSERT (0+OP2 <= 255); \
JERRY_ASSERT (0+OP3 <= 255); \
OPCODE()=getop_##GETOP ((idx_t) (OP1), (idx_t) (OP2), (idx_t) (OP3)); \
serializer_rewrite_opcode (OC, OPCODE()); \
} while (0)
#define REWRITE_COND_JMP(OC, GETOP, DIFF) \
do { \
JERRY_ASSERT (0+DIFF <= 256*256 - 1); \
STACK_DECLARE_USAGE (IDX); \
JERRY_STATIC_ASSERT (sizeof (idx_t) == 1); \
STACK_PUSH (IDX, (idx_t) ((DIFF) >> JERRY_BITSINBYTE)); \
STACK_PUSH (IDX, (idx_t) ((DIFF) & ((1 << JERRY_BITSINBYTE) - 1))); \
JERRY_ASSERT ((DIFF) == calc_opcode_counter_from_idx_idx (STACK_HEAD (IDX, 2), STACK_HEAD (IDX, 1))); \
OPCODE()=getop_##GETOP (STACK_HEAD (IDX, 3), STACK_HEAD (IDX, 2), STACK_HEAD (IDX, 1)); \
serializer_rewrite_opcode (OC, OPCODE()); \
STACK_DROP (IDX, 2); \
STACK_CHECK_USAGE (IDX); \
} while (0)
#define REWRITE_JMP(OC, GETOP, DIFF) \
do { \
JERRY_ASSERT (0+DIFF <= 256*256 - 1); \
STACK_DECLARE_USAGE (IDX) \
JERRY_STATIC_ASSERT (sizeof (idx_t) == 1); \
STACK_PUSH (IDX, (idx_t) ((DIFF) >> JERRY_BITSINBYTE)); \
STACK_PUSH (IDX, (idx_t) ((DIFF) & ((1 << JERRY_BITSINBYTE) - 1))); \
JERRY_ASSERT ((DIFF) == calc_opcode_counter_from_idx_idx (STACK_HEAD (IDX, 2), STACK_HEAD (IDX, 1))); \
OPCODE()=getop_##GETOP (STACK_HEAD (IDX, 2), STACK_HEAD (IDX, 1)); \
serializer_rewrite_opcode (OC, OPCODE()); \
STACK_DROP (IDX, 2); \
STACK_CHECK_USAGE (IDX); \
} while (0)
#define REWRITE_TRY(OC) \
do { \
STACK_DECLARE_USAGE (IDX) \
JERRY_STATIC_ASSERT (sizeof (idx_t) == 1); \
STACK_PUSH (IDX, (idx_t) ((OPCODE_COUNTER ()) >> JERRY_BITSINBYTE)); \
STACK_PUSH (IDX, (idx_t) ((OPCODE_COUNTER ()) & ((1 << JERRY_BITSINBYTE) - 1))); \
JERRY_ASSERT ((OPCODE_COUNTER ()) \
== calc_opcode_counter_from_idx_idx (STACK_HEAD (IDX, 2), STACK_HEAD (IDX, 1))); \
OPCODE()=getop_try (STACK_HEAD (IDX, 2), STACK_HEAD (IDX, 1)); \
serializer_rewrite_opcode ((OC), OPCODE()); \
STACK_DROP (IDX, 2); \
STACK_CHECK_USAGE (IDX); \
} while (0)
static void
integer_zero (void)
{
@@ -1815,11 +1704,12 @@ PARSE_OF (logical_or_expression, logical_and_expression, DOUBLE_OR, logical_or)
: logical_or_expression (LT!* '?' LT!* assignment_expression LT!* ':' LT!* assignment_expression)?
; */
static void
parse_conditional_expression (bool *was_conditional)
parse_conditional_expression (void)
{
// IDX expr, res, lhs
STACK_DECLARE_USAGE (IDX)
STACK_DECLARE_USAGE (U16)
STACK_DECLARE_USAGE (U8)
parse_logical_or_expression ();
@@ -1844,7 +1734,7 @@ parse_conditional_expression (bool *was_conditional)
DUMP_OPCODE_3 (assignment, STACK_HEAD (IDX, 2), OPCODE_ARG_TYPE_VARIABLE, STACK_HEAD (IDX, 1));
REWRITE_JMP (STACK_HEAD (U16, 1), jmp_down, OPCODE_COUNTER () - STACK_HEAD (U16, 1));
*was_conditional = true;
STACK_HEAD (U8, 1) = 1;
STACK_HEAD (IDX, 3) = STACK_HEAD (IDX, 2);
STACK_DROP (IDX, 2);
}
@@ -1854,6 +1744,7 @@ parse_conditional_expression (bool *was_conditional)
}
STACK_CHECK_USAGE (U16);
STACK_CHECK_USAGE (U8);
STACK_CHECK_USAGE_LHS ();
}
@@ -1866,87 +1757,269 @@ parse_assignment_expression (void)
{
// IDX lhs, rhs;
STACK_DECLARE_USAGE (IDX)
bool was_conditional = false;
STACK_DECLARE_USAGE (U16);
STACK_DECLARE_USAGE (U8);
STACK_DECLARE_USAGE (ops);
parse_conditional_expression (&was_conditional);
if (was_conditional)
STACK_PUSH (U8, 0);
parse_conditional_expression ();
if (STACK_HEAD (U8, 1))
{
STACK_DROP (U8, 1);
goto cleanup;
}
/* Rewrite prop_getter with nop and generate prop_setter in constructions like:
a.b = c; */
if (LAST_OPCODE_IS (prop_getter))
{
STACK_PUSH (U16, (opcode_counter_t) (OPCODE_COUNTER () - 1));
STACK_HEAD (U8, 1) = 1;
}
skip_newlines ();
switch (TOK ().type)
{
case TOK_EQ:
{
NEXT (assignment_expression);
DUMP_OPCODE_3 (assignment, STACK_HEAD (IDX, 2), OPCODE_ARG_TYPE_VARIABLE, STACK_HEAD (IDX, 1));
if (STACK_HEAD (U8, 1))
{
STACK_PUSH (ops, deserialize_opcode (STACK_HEAD (U16, 1)));
JERRY_ASSERT (STACK_HEAD (ops, 1).op_idx == __op__idx_prop_getter);
serializer_set_writing_position (--OPCODE_COUNTER ());
NEXT (assignment_expression);
DUMP_OPCODE_3 (prop_setter, STACK_HEAD (ops, 1).data.prop_getter.obj,
STACK_HEAD (ops, 1).data.prop_getter.prop, STACK_HEAD (IDX, 1));
STACK_DROP (ops, 1);
STACK_DROP (U16, 1);
}
else
{
NEXT (assignment_expression);
DUMP_OPCODE_3 (assignment, STACK_HEAD (IDX, 2), OPCODE_ARG_TYPE_VARIABLE,
STACK_HEAD (IDX, 1));
}
break;
}
case TOK_MULT_EQ:
{
NEXT (assignment_expression);
DUMP_OPCODE_3 (multiplication, STACK_HEAD (IDX, 2), STACK_HEAD (IDX, 2), STACK_HEAD (IDX, 1));
if (STACK_HEAD (U8, 1))
{
STACK_PUSH (ops, deserialize_opcode (STACK_HEAD (U16, 0)));
DUMP_OPCODE_3 (multiplication, STACK_HEAD (IDX, 2), STACK_HEAD (IDX, 2),
STACK_HEAD (IDX, 1));
DUMP_OPCODE_3 (prop_setter, STACK_HEAD (ops, 1).data.prop_getter.obj,
STACK_HEAD (ops, 1).data.prop_getter.prop, STACK_HEAD (IDX, 2));
STACK_DROP (ops, 1);
STACK_DROP (U16, 1);
}
else
{
DUMP_OPCODE_3 (multiplication, STACK_HEAD (IDX, 2), STACK_HEAD (IDX, 2),
STACK_HEAD (IDX, 1));
}
break;
}
case TOK_DIV_EQ:
{
NEXT (assignment_expression);
DUMP_OPCODE_3 (division, STACK_HEAD (IDX, 2), STACK_HEAD (IDX, 2), STACK_HEAD (IDX, 1));
if (STACK_HEAD (U8, 1))
{
STACK_PUSH (ops, deserialize_opcode (STACK_HEAD (U16, 0)));
DUMP_OPCODE_3 (division, STACK_HEAD (IDX, 2), STACK_HEAD (IDX, 2),
STACK_HEAD (IDX, 1));
DUMP_OPCODE_3 (prop_setter, STACK_HEAD (ops, 1).data.prop_getter.obj,
STACK_HEAD (ops, 1).data.prop_getter.prop, STACK_HEAD (IDX, 2));
STACK_DROP (ops, 1);
STACK_DROP (U16, 1);
}
else
{
DUMP_OPCODE_3 (division, STACK_HEAD (IDX, 2), STACK_HEAD (IDX, 2),
STACK_HEAD (IDX, 1));
}
break;
}
case TOK_MOD_EQ:
{
NEXT (assignment_expression);
DUMP_OPCODE_3 (remainder, STACK_HEAD (IDX, 2), STACK_HEAD (IDX, 2), STACK_HEAD (IDX, 1));
if (STACK_HEAD (U8, 1))
{
STACK_PUSH (ops, deserialize_opcode (STACK_HEAD (U16, 0)));
DUMP_OPCODE_3 (remainder, STACK_HEAD (IDX, 2), STACK_HEAD (IDX, 2),
STACK_HEAD (IDX, 1));
DUMP_OPCODE_3 (prop_setter, STACK_HEAD (ops, 1).data.prop_getter.obj,
STACK_HEAD (ops, 1).data.prop_getter.prop, STACK_HEAD (IDX, 2));
STACK_DROP (ops, 1);
STACK_DROP (U16, 1);
}
else
{
DUMP_OPCODE_3 (remainder, STACK_HEAD (IDX, 2), STACK_HEAD (IDX, 2),
STACK_HEAD (IDX, 1));
}
break;
}
case TOK_PLUS_EQ:
{
NEXT (assignment_expression);
DUMP_OPCODE_3 (addition, STACK_HEAD (IDX, 2), STACK_HEAD (IDX, 2), STACK_HEAD (IDX, 1));
if (STACK_HEAD (U8, 1))
{
STACK_PUSH (ops, deserialize_opcode (STACK_HEAD (U16, 0)));
DUMP_OPCODE_3 (addition, STACK_HEAD (IDX, 2), STACK_HEAD (IDX, 2),
STACK_HEAD (IDX, 1));
DUMP_OPCODE_3 (prop_setter, STACK_HEAD (ops, 1).data.prop_getter.obj,
STACK_HEAD (ops, 1).data.prop_getter.prop, STACK_HEAD (IDX, 2));
STACK_DROP (ops, 1);
STACK_DROP (U16, 1);
}
else
{
DUMP_OPCODE_3 (addition, STACK_HEAD (IDX, 2), STACK_HEAD (IDX, 2),
STACK_HEAD (IDX, 1));
}
break;
}
case TOK_MINUS_EQ:
{
NEXT (assignment_expression);
DUMP_OPCODE_3 (substraction, STACK_HEAD (IDX, 2), STACK_HEAD (IDX, 2), STACK_HEAD (IDX, 1));
if (STACK_HEAD (U8, 1))
{
STACK_PUSH (ops, deserialize_opcode (STACK_HEAD (U16, 0)));
DUMP_OPCODE_3 (substraction, STACK_HEAD (IDX, 2), STACK_HEAD (IDX, 2),
STACK_HEAD (IDX, 1));
DUMP_OPCODE_3 (prop_setter, STACK_HEAD (ops, 1).data.prop_getter.obj,
STACK_HEAD (ops, 1).data.prop_getter.prop, STACK_HEAD (IDX, 2));
STACK_DROP (ops, 1);
STACK_DROP (U16, 1);
}
else
{
DUMP_OPCODE_3 (substraction, STACK_HEAD (IDX, 2), STACK_HEAD (IDX, 2),
STACK_HEAD (IDX, 1));
}
break;
}
case TOK_LSHIFT_EQ:
{
NEXT (assignment_expression);
DUMP_OPCODE_3 (b_shift_left, STACK_HEAD (IDX, 2), STACK_HEAD (IDX, 2), STACK_HEAD (IDX, 1));
if (STACK_HEAD (U8, 1))
{
STACK_PUSH (ops, deserialize_opcode (STACK_HEAD (U16, 0)));
DUMP_OPCODE_3 (b_shift_left, STACK_HEAD (IDX, 2), STACK_HEAD (IDX, 2),
STACK_HEAD (IDX, 1));
DUMP_OPCODE_3 (prop_setter, STACK_HEAD (ops, 1).data.prop_getter.obj,
STACK_HEAD (ops, 1).data.prop_getter.prop, STACK_HEAD (IDX, 2));
STACK_DROP (ops, 1);
STACK_DROP (U16, 1);
}
else
{
DUMP_OPCODE_3 (b_shift_left, STACK_HEAD (IDX, 2), STACK_HEAD (IDX, 2),
STACK_HEAD (IDX, 1));
}
break;
}
case TOK_RSHIFT_EQ:
{
NEXT (assignment_expression);
DUMP_OPCODE_3 (b_shift_right, STACK_HEAD (IDX, 2), STACK_HEAD (IDX, 2), STACK_HEAD (IDX, 1));
if (STACK_HEAD (U8, 1))
{
STACK_PUSH (ops, deserialize_opcode (STACK_HEAD (U16, 0)));
DUMP_OPCODE_3 (b_shift_right, STACK_HEAD (IDX, 2), STACK_HEAD (IDX, 2),
STACK_HEAD (IDX, 1));
DUMP_OPCODE_3 (prop_setter, STACK_HEAD (ops, 1).data.prop_getter.obj,
STACK_HEAD (ops, 1).data.prop_getter.prop, STACK_HEAD (IDX, 2));
STACK_DROP (ops, 1);
STACK_DROP (U16, 1);
}
else
{
DUMP_OPCODE_3 (b_shift_right, STACK_HEAD (IDX, 2), STACK_HEAD (IDX, 2),
STACK_HEAD (IDX, 1));
}
break;
}
case TOK_RSHIFT_EX_EQ:
{
NEXT (assignment_expression);
DUMP_OPCODE_3 (b_shift_uright, STACK_HEAD (IDX, 2), STACK_HEAD (IDX, 2), STACK_HEAD (IDX, 1));
if (STACK_HEAD (U8, 1))
{
STACK_PUSH (ops, deserialize_opcode (STACK_HEAD (U16, 0)));
DUMP_OPCODE_3 (b_shift_uright, STACK_HEAD (IDX, 2), STACK_HEAD (IDX, 2),
STACK_HEAD (IDX, 1));
DUMP_OPCODE_3 (prop_setter, STACK_HEAD (ops, 1).data.prop_getter.obj,
STACK_HEAD (ops, 1).data.prop_getter.prop, STACK_HEAD (IDX, 2));
STACK_DROP (ops, 1);
STACK_DROP (U16, 1);
}
else
{
DUMP_OPCODE_3 (b_shift_uright, STACK_HEAD (IDX, 2), STACK_HEAD (IDX, 2),
STACK_HEAD (IDX, 1));
}
break;
}
case TOK_AND_EQ:
{
NEXT (assignment_expression);
DUMP_OPCODE_3 (b_and, STACK_HEAD (IDX, 2), STACK_HEAD (IDX, 2), STACK_HEAD (IDX, 1));
if (STACK_HEAD (U8, 1))
{
STACK_PUSH (ops, deserialize_opcode (STACK_HEAD (U16, 0)));
DUMP_OPCODE_3 (b_and, STACK_HEAD (IDX, 2), STACK_HEAD (IDX, 2),
STACK_HEAD (IDX, 1));
DUMP_OPCODE_3 (prop_setter, STACK_HEAD (ops, 1).data.prop_getter.obj,
STACK_HEAD (ops, 1).data.prop_getter.prop, STACK_HEAD (IDX, 2));
STACK_DROP (ops, 1);
STACK_DROP (U16, 1);
}
else
{
DUMP_OPCODE_3 (b_and, STACK_HEAD (IDX, 2), STACK_HEAD (IDX, 2),
STACK_HEAD (IDX, 1));
}
break;
}
case TOK_XOR_EQ:
{
NEXT (assignment_expression);
DUMP_OPCODE_3 (b_xor, STACK_HEAD (IDX, 2), STACK_HEAD (IDX, 2), STACK_HEAD (IDX, 1));
if (STACK_HEAD (U8, 1))
{
STACK_PUSH (ops, deserialize_opcode (STACK_HEAD (U16, 0)));
DUMP_OPCODE_3 (b_xor, STACK_HEAD (IDX, 2), STACK_HEAD (IDX, 2),
STACK_HEAD (IDX, 1));
DUMP_OPCODE_3 (prop_setter, STACK_HEAD (ops, 1).data.prop_getter.obj,
STACK_HEAD (ops, 1).data.prop_getter.prop, STACK_HEAD (IDX, 2));
STACK_DROP (ops, 1);
STACK_DROP (U16, 1);
}
else
{
DUMP_OPCODE_3 (b_xor, STACK_HEAD (IDX, 2), STACK_HEAD (IDX, 2),
STACK_HEAD (IDX, 1));
}
break;
}
case TOK_OR_EQ:
{
NEXT (assignment_expression);
DUMP_OPCODE_3 (b_or, STACK_HEAD (IDX, 2), STACK_HEAD (IDX, 2), STACK_HEAD (IDX, 1));
if (STACK_HEAD (U8, 1))
{
STACK_PUSH (ops, deserialize_opcode (STACK_HEAD (U16, 0)));
DUMP_OPCODE_3 (b_or, STACK_HEAD (IDX, 2), STACK_HEAD (IDX, 2),
STACK_HEAD (IDX, 1));
DUMP_OPCODE_3 (prop_setter, STACK_HEAD (ops, 1).data.prop_getter.obj,
STACK_HEAD (ops, 1).data.prop_getter.prop, STACK_HEAD (IDX, 2));
STACK_DROP (ops, 1);
STACK_DROP (U16, 1);
}
else
{
DUMP_OPCODE_3 (b_or, STACK_HEAD (IDX, 2), STACK_HEAD (IDX, 2),
STACK_HEAD (IDX, 1));
}
break;
}
default:
@@ -1959,6 +2032,11 @@ parse_assignment_expression (void)
STACK_DROP (IDX, 1);
cleanup:
STACK_DROP (U8, 1);
STACK_CHECK_USAGE (U16);
STACK_CHECK_USAGE (U8);
STACK_CHECK_USAGE (ops);
STACK_CHECK_USAGE_LHS ();
}
+9 -1
View File
@@ -41,7 +41,15 @@ const void *
deserialize_bytecode (void)
{
JERRY_ASSERT (STACK_SIZE (bytecode_opcodes) > 0);
return bytecode_opcodes.data;
return STACK_RAW_DATA (bytecode_opcodes);
}
opcode_t
deserialize_opcode (opcode_counter_t oc)
{
JERRY_ASSERT (STACK_SIZE (bytecode_opcodes) > 0);
JERRY_ASSERT (oc < STACK_SIZE (bytecode_opcodes));
return STACK_ELEMENT (bytecode_opcodes, oc);
}
uint8_t
+2
View File
@@ -18,10 +18,12 @@
#include "globals.h"
#include "ecma-globals.h"
#include "opcodes.h"
const ecma_char_t *deserialize_string_by_id (uint8_t);
ecma_number_t deserialize_num_by_id (uint8_t);
const void *deserialize_bytecode (void);
opcode_t deserialize_opcode (opcode_counter_t);
uint8_t deserialize_min_temp (void);
#endif //DESERIALIZER_H
+1
View File
@@ -430,6 +430,7 @@ pp_opcode (opcode_counter_t oc, opcode_t opcode, bool is_rewrite)
TODO (Refine to match new opcodes)
CASE_VARG_0_LHS (obj_decl, lhs, "=", "{", "}")
CASE_VARG_1_NAME_LHS (prop_getter, lhs, "=", "", obj, "[", prop, "]")
CASE_VARG_1_NAME_LHS (prop_setter, obj, "", "[", prop, " ] = ", rhs, "")
CASE_THIS (this, lhs, "=", "this")
CASE_DOUBLE_ADDRESS (delete_var, lhs, "=", "delete", name)
CASE_TRIPLE_ADDRESS (delete_prop, lhs, "= delete", base, ".", name)
+7
View File
@@ -50,6 +50,13 @@ serializer_dump_opcode (opcode_t opcode)
STACK_PUSH (bytecode_opcodes, opcode);
}
void
serializer_set_writing_position (opcode_counter_t oc)
{
JERRY_ASSERT (oc < STACK_SIZE (bytecode_opcodes));
STACK_DROP (bytecode_opcodes, STACK_SIZE (bytecode_opcodes) - oc);
}
void
serializer_rewrite_opcode (const opcode_counter_t loc, opcode_t opcode)
{
+1 -6
View File
@@ -22,18 +22,13 @@
#include "lp-string.h"
void serializer_init (bool show_opcodes);
void serializer_dump_strings_and_nums (const lp_string *, uint8_t,
const ecma_number_t *, uint8_t);
void serializer_dump_opcode (opcode_t);
void serializer_set_writing_position (opcode_counter_t);
void serializer_rewrite_opcode (const opcode_counter_t, opcode_t);
void serializer_print_opcodes (void);
void serializer_adjust_strings (void);
void serializer_free (void);
#endif // SERIALIZER_H
+13 -14
View File
@@ -28,19 +28,18 @@ assert (person["age"] === 50);
assert (person.eyeColor === "blue");
assert (person["eyeColor"] === "blue");
// FIXME Uncomment when prop_set generation will be ready
// var x = person;
// x.age = 40;
// assert (x.age === 40);
// assert (person.age === 40);
var x = person;
x.age = 40;
assert (x.age === 40);
assert (person.age === 40);
// var john = new Object();
// john.firstName = "John";
// john.lastName = "Doe";
// john.age = 40;
// john.eyeColor = "blue";
var john = new Object();
john.firstName = "John";
john.lastName = "Doe";
john.age = 40;
john.eyeColor = "blue";
// assert (person.firstName === john.firstName);
// assert (person.lastName === john.lastName);
// assert (person.age === john.age);
// assert (person.eyeColor === john.eyeColor);
assert (person.firstName === john.firstName);
assert (person.lastName === john.lastName);
assert (person.age === john.age);
assert (person.eyeColor === john.eyeColor);