Add generation of prop_setter.
This commit is contained in:
@@ -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 */
|
||||
@@ -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
@@ -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 ();
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user