mirror of
https://github.com/jerryscript-project/jerryscript.git
synced 2025-12-15 16:29:21 +00:00
Implementing register variables.
This commit is contained in:
parent
c837c7d435
commit
b7a3a13bc9
@ -13,8 +13,11 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "ecma-globals.h"
|
||||
#include "ecma-helpers.h"
|
||||
#include "globals.h"
|
||||
#include "interpreter.h"
|
||||
#include "jerry-libc.h"
|
||||
|
||||
#define INIT_OP_FUNC(name) [ __op__idx_##name ] = opfunc_##name,
|
||||
static const opfunc __opfuncs[LAST_OP] = {
|
||||
@ -42,15 +45,17 @@ run_int (void)
|
||||
{
|
||||
JERRY_ASSERT( __program != NULL );
|
||||
|
||||
struct __int_data int_data;
|
||||
int_data.pos = 0;
|
||||
int_data.this_binding_p = NULL;
|
||||
int_data.lex_env_p = ecma_create_lexical_environment( NULL,
|
||||
ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE);
|
||||
const int start_pos = 0;
|
||||
ecma_object_t *this_binding_p = NULL;
|
||||
ecma_object_t *lex_env_p = ecma_create_lexical_environment (NULL,
|
||||
ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE);
|
||||
FIXME( Strict mode );
|
||||
int_data.is_strict = false;
|
||||
const bool is_strict = false;
|
||||
|
||||
ecma_completion_value_t completion = run_int_from_pos( &int_data);
|
||||
ecma_completion_value_t completion = run_int_from_pos (start_pos,
|
||||
this_binding_p,
|
||||
lex_env_p,
|
||||
is_strict);
|
||||
|
||||
switch ( (ecma_completion_type_t)completion.type )
|
||||
{
|
||||
@ -82,16 +87,43 @@ run_int (void)
|
||||
}
|
||||
|
||||
ecma_completion_value_t
|
||||
run_int_from_pos (struct __int_data *int_data)
|
||||
run_int_from_pos (int start_pos,
|
||||
ecma_object_t *this_binding_p,
|
||||
ecma_object_t *lex_env_p,
|
||||
bool is_strict)
|
||||
{
|
||||
ecma_completion_value_t completion;
|
||||
|
||||
const OPCODE *curr = &__program[start_pos];
|
||||
JERRY_ASSERT( curr->op_idx == __op__idx_reg_var_decl );
|
||||
|
||||
const T_IDX min_reg_num = curr->data.reg_var_decl.min;
|
||||
const T_IDX max_reg_num = curr->data.reg_var_decl.max;
|
||||
JERRY_ASSERT( max_reg_num >= min_reg_num );
|
||||
|
||||
const uint32_t regs_num = (uint32_t) (max_reg_num - min_reg_num + 1);
|
||||
|
||||
ecma_value_t regs[ regs_num ];
|
||||
|
||||
/* memseting with zero initializes each 'register' to empty value */
|
||||
__memset (regs, 0, sizeof(regs));
|
||||
JERRY_ASSERT( ecma_is_value_empty( regs[0]) );
|
||||
|
||||
struct __int_data int_data;
|
||||
int_data.pos = start_pos + 1;
|
||||
int_data.this_binding_p = this_binding_p;
|
||||
int_data.lex_env_p = lex_env_p;
|
||||
int_data.is_strict = is_strict;
|
||||
int_data.min_reg_num = min_reg_num;
|
||||
int_data.max_reg_num = max_reg_num;
|
||||
int_data.regs_p = regs;
|
||||
|
||||
while ( true )
|
||||
{
|
||||
do
|
||||
{
|
||||
const OPCODE *curr = &__program[int_data->pos];
|
||||
completion = __opfuncs[curr->op_idx](*curr, int_data);
|
||||
const OPCODE *curr = &__program[int_data.pos];
|
||||
completion = __opfuncs[curr->op_idx](*curr, &int_data);
|
||||
|
||||
JERRY_ASSERT( !ecma_is_completion_value_normal( completion)
|
||||
|| ecma_is_completion_value_normal_simple_value(completion,
|
||||
@ -111,6 +143,13 @@ run_int_from_pos (struct __int_data *int_data)
|
||||
continue;
|
||||
}
|
||||
|
||||
for ( uint32_t reg_index = 0;
|
||||
reg_index < regs_num;
|
||||
reg_index++ )
|
||||
{
|
||||
ecma_free_value( regs[ reg_index ] );
|
||||
}
|
||||
|
||||
return completion;
|
||||
}
|
||||
}
|
||||
|
||||
@ -26,11 +26,17 @@ struct __int_data
|
||||
ecma_object_t *this_binding_p; /**< this binding for current context */
|
||||
ecma_object_t *lex_env_p; /**< current lexical environment */
|
||||
bool is_strict; /**< is current code execution mode strict? */
|
||||
T_IDX min_reg_num; /**< minimum idx used for register identification */
|
||||
T_IDX max_reg_num; /**< maximum idx used for register identification */
|
||||
ecma_value_t *regs_p; /**< register variables */
|
||||
};
|
||||
|
||||
void init_int (const OPCODE* program_p);
|
||||
bool run_int (void);
|
||||
ecma_completion_value_t run_int_from_pos (struct __int_data *);
|
||||
ecma_completion_value_t run_int_from_pos (int start_pos,
|
||||
ecma_object_t *this_binding_p,
|
||||
ecma_object_t *lex_env_p,
|
||||
bool is_strict);
|
||||
|
||||
ssize_t try_get_string_by_idx( T_IDX idx, ecma_char_t *buffer_p, ssize_t buffer_size);
|
||||
ecma_number_t get_number_by_idx(T_IDX idx);
|
||||
|
||||
@ -183,27 +183,42 @@ get_variable_value(struct __int_data *int_data, /**< interpreter context */
|
||||
bool do_eval_or_arguments_check) /** run 'strict eval or arguments reference' check
|
||||
See also: do_strict_eval_arguments_check */
|
||||
{
|
||||
string_literal_copy var_name;
|
||||
ecma_reference_t ref;
|
||||
ecma_completion_value_t ret_value;
|
||||
|
||||
init_string_literal_copy( var_idx, &var_name);
|
||||
ref = ecma_op_get_identifier_reference( int_data->lex_env_p,
|
||||
var_name.str_p,
|
||||
int_data->is_strict);
|
||||
if ( var_idx >= int_data->min_reg_num
|
||||
&& var_idx <= int_data->max_reg_num )
|
||||
{
|
||||
ecma_value_t reg_value = int_data->regs_p[ var_idx - int_data->min_reg_num ];
|
||||
|
||||
if ( unlikely( do_eval_or_arguments_check
|
||||
&& do_strict_eval_arguments_check( ref) ) )
|
||||
JERRY_ASSERT( !ecma_is_value_empty( reg_value) );
|
||||
|
||||
ret_value = ecma_make_completion_value (ECMA_COMPLETION_TYPE_NORMAL,
|
||||
ecma_copy_value( reg_value),
|
||||
ECMA_TARGET_ID_RESERVED);
|
||||
}
|
||||
else
|
||||
{
|
||||
string_literal_copy var_name;
|
||||
ecma_reference_t ref;
|
||||
|
||||
init_string_literal_copy( var_idx, &var_name);
|
||||
ref = ecma_op_get_identifier_reference( int_data->lex_env_p,
|
||||
var_name.str_p,
|
||||
int_data->is_strict);
|
||||
|
||||
if ( unlikely( do_eval_or_arguments_check
|
||||
&& do_strict_eval_arguments_check( ref) ) )
|
||||
{
|
||||
ret_value = ecma_make_throw_value( ecma_new_standard_error( ECMA_ERROR_SYNTAX));
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
ret_value = ecma_op_get_value( ref);
|
||||
}
|
||||
|
||||
ecma_free_reference( ref);
|
||||
free_string_literal_copy( &var_name);
|
||||
ecma_free_reference( ref);
|
||||
free_string_literal_copy( &var_name);
|
||||
}
|
||||
|
||||
return ret_value;
|
||||
} /* get_variable_value */
|
||||
@ -219,26 +234,44 @@ set_variable_value(struct __int_data *int_data, /**< interpreter context */
|
||||
T_IDX var_idx, /**< variable identifier */
|
||||
ecma_value_t value) /**< value to set */
|
||||
{
|
||||
string_literal_copy var_name;
|
||||
ecma_reference_t ref;
|
||||
ecma_completion_value_t ret_value;
|
||||
|
||||
init_string_literal_copy( var_idx, &var_name);
|
||||
ref = ecma_op_get_identifier_reference( int_data->lex_env_p,
|
||||
var_name.str_p,
|
||||
int_data->is_strict);
|
||||
if ( var_idx >= int_data->min_reg_num
|
||||
&& var_idx <= int_data->max_reg_num )
|
||||
{
|
||||
ecma_value_t reg_value = int_data->regs_p[ var_idx - int_data->min_reg_num ];
|
||||
|
||||
if ( unlikely( do_strict_eval_arguments_check( ref) ) )
|
||||
if ( !ecma_is_value_empty( reg_value) )
|
||||
{
|
||||
ecma_free_value( reg_value);
|
||||
}
|
||||
|
||||
int_data->regs_p[ var_idx - int_data->min_reg_num ] = ecma_copy_value( value);
|
||||
|
||||
ret_value = ecma_make_empty_completion_value();
|
||||
}
|
||||
else
|
||||
{
|
||||
string_literal_copy var_name;
|
||||
ecma_reference_t ref;
|
||||
|
||||
init_string_literal_copy( var_idx, &var_name);
|
||||
ref = ecma_op_get_identifier_reference( int_data->lex_env_p,
|
||||
var_name.str_p,
|
||||
int_data->is_strict);
|
||||
|
||||
if ( unlikely( do_strict_eval_arguments_check( ref) ) )
|
||||
{
|
||||
ret_value = ecma_make_throw_value( ecma_new_standard_error( ECMA_ERROR_SYNTAX));
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
ret_value = ecma_op_put_value( ref, value);
|
||||
}
|
||||
|
||||
ecma_free_reference( ref);
|
||||
free_string_literal_copy( &var_name);
|
||||
ecma_free_reference( ref);
|
||||
free_string_literal_copy( &var_name);
|
||||
}
|
||||
|
||||
return ret_value;
|
||||
} /* set_variable_value */
|
||||
@ -372,13 +405,13 @@ do_number_arithmetic(struct __int_data *int_data, /**< interpreter context */
|
||||
op(b_not) \
|
||||
op(instanceof) \
|
||||
op(in) \
|
||||
op(reg_var_decl)
|
||||
static char __unused unimplemented_list_end
|
||||
|
||||
#define DEFINE_UNIMPLEMENTED_OP(op) \
|
||||
ecma_completion_value_t opfunc_ ## op(OPCODE opdata, struct __int_data *int_data) { \
|
||||
JERRY_UNIMPLEMENTED_REF_UNUSED_VARS( opdata, int_data); \
|
||||
}
|
||||
OP_UNIMPLEMENTED_LIST(DEFINE_UNIMPLEMENTED_OP)
|
||||
OP_UNIMPLEMENTED_LIST(DEFINE_UNIMPLEMENTED_OP);
|
||||
#undef DEFINE_UNIMPLEMENTED_OP
|
||||
|
||||
ecma_completion_value_t
|
||||
@ -804,6 +837,18 @@ opfunc_remainder(OPCODE opdata, /**< operation data */
|
||||
return ret_value;
|
||||
} /* opfunc_remainder */
|
||||
|
||||
/**
|
||||
* 'Register variable declaration' opcode handler.
|
||||
*
|
||||
* The opcode is meta-opcode that is not supposed to be executed.
|
||||
*/
|
||||
ecma_completion_value_t
|
||||
opfunc_reg_var_decl(OPCODE opdata __unused, /**< operation data */
|
||||
struct __int_data *int_data __unused) /**< interpreter context */
|
||||
{
|
||||
JERRY_UNREACHABLE();
|
||||
} /* opfunc_reg_var_decl */
|
||||
|
||||
/**
|
||||
* 'Variable declaration' opcode handler.
|
||||
*
|
||||
@ -815,25 +860,25 @@ opfunc_remainder(OPCODE opdata, /**< operation data */
|
||||
*/
|
||||
ecma_completion_value_t
|
||||
opfunc_var_decl(OPCODE opdata, /**< operation data */
|
||||
struct __int_data *int_data __unused) /**< interpreter context */
|
||||
struct __int_data *int_data) /**< interpreter context */
|
||||
{
|
||||
string_literal_copy variable_name;
|
||||
init_string_literal_copy( opdata.data.var_decl.variable_name, &variable_name);
|
||||
|
||||
if ( ecma_is_completion_value_normal_false( ecma_op_has_binding( int_data->lex_env_p,
|
||||
variable_name.str_p)) )
|
||||
if ( ecma_is_completion_value_normal_false( ecma_op_has_binding (int_data->lex_env_p,
|
||||
variable_name.str_p)) )
|
||||
{
|
||||
FIXME( Pass configurableBindings that is true if and only if current code is eval code );
|
||||
ecma_op_create_mutable_binding( int_data->lex_env_p,
|
||||
variable_name.str_p,
|
||||
false);
|
||||
ecma_op_create_mutable_binding (int_data->lex_env_p,
|
||||
variable_name.str_p,
|
||||
false);
|
||||
|
||||
/* Skipping SetMutableBinding as we have already checked that there were not
|
||||
* any binding with specified name in current lexical environment
|
||||
* and CreateMutableBinding sets the created binding's value to undefined */
|
||||
JERRY_ASSERT( ecma_is_completion_value_normal_simple_value( ecma_op_get_binding_value( int_data->lex_env_p,
|
||||
variable_name.str_p,
|
||||
true),
|
||||
JERRY_ASSERT( ecma_is_completion_value_normal_simple_value( ecma_op_get_binding_value (int_data->lex_env_p,
|
||||
variable_name.str_p,
|
||||
true),
|
||||
ECMA_SIMPLE_VALUE_UNDEFINED) );
|
||||
}
|
||||
|
||||
|
||||
@ -63,11 +63,11 @@ typedef enum {
|
||||
* Simple ecma-values
|
||||
*/
|
||||
typedef enum {
|
||||
ECMA_SIMPLE_VALUE_EMPTY, /**< empty value (see also: ECMA-262 v5, 8.9 Completion specification type) */
|
||||
ECMA_SIMPLE_VALUE_UNDEFINED, /**< undefined value */
|
||||
ECMA_SIMPLE_VALUE_NULL, /**< null value */
|
||||
ECMA_SIMPLE_VALUE_FALSE, /**< boolean false */
|
||||
ECMA_SIMPLE_VALUE_TRUE, /**< boolean true */
|
||||
ECMA_SIMPLE_VALUE_EMPTY, /**< empty value (see also: ECMA-262 v5, 8.9 Completion specification type) */
|
||||
ECMA_SIMPLE_VALUE_ARRAY_REDIRECT, /**< special value for an array's elements that exists,
|
||||
but is stored directly in the array's property list
|
||||
(used for array elements with non-default attribute values) */
|
||||
|
||||
@ -26,6 +26,18 @@
|
||||
#include "ecma-helpers.h"
|
||||
#include "globals.h"
|
||||
|
||||
/**
|
||||
* Check if the value is empty.
|
||||
*
|
||||
* @return true - if the value contains implementation-defined empty simple value,
|
||||
* false - otherwise.
|
||||
*/
|
||||
bool
|
||||
ecma_is_value_empty( ecma_value_t value) /**< ecma-value */
|
||||
{
|
||||
return ( value.value_type == ECMA_TYPE_SIMPLE && value.value == ECMA_SIMPLE_VALUE_EMPTY );
|
||||
} /* ecma_is_value_empty */
|
||||
|
||||
/**
|
||||
* Check if the value is undefined.
|
||||
*
|
||||
|
||||
@ -42,6 +42,7 @@ extern void* ecma_decompress_pointer(uintptr_t compressed_pointer);
|
||||
(field) = ecma_compress_pointer( non_compressed_pointer) & ( ( 1u << ECMA_POINTER_FIELD_WIDTH ) - 1)
|
||||
|
||||
/* ecma-helpers-value.c */
|
||||
extern bool ecma_is_value_empty( ecma_value_t value);
|
||||
extern bool ecma_is_value_undefined( ecma_value_t value);
|
||||
extern bool ecma_is_value_null( ecma_value_t value);
|
||||
extern bool ecma_is_value_boolean( ecma_value_t value);
|
||||
|
||||
@ -26,6 +26,7 @@ main( int __unused argc,
|
||||
char __unused **argv)
|
||||
{
|
||||
const OPCODE test_program[] = {
|
||||
getop_reg_var_decl( 255, 255),
|
||||
getop_var_decl( 0),
|
||||
getop_var_decl( 1),
|
||||
getop_assignment( 0, OPCODE_ARG_TYPE_SMALLINT, 253),
|
||||
|
||||
@ -26,17 +26,18 @@ main( int __unused argc,
|
||||
char __unused **argv)
|
||||
{
|
||||
const OPCODE test_program[] = {
|
||||
/* 0: */ getop_var_decl( 0),
|
||||
/* 1: */ getop_var_decl( 1),
|
||||
/* 2: */ getop_assignment( 0, OPCODE_ARG_TYPE_STRING, 1),
|
||||
/* 3: */ getop_assignment( 1, OPCODE_ARG_TYPE_VARIABLE, 0),
|
||||
/* 4: */ getop_is_true_jmp( 1, 6),
|
||||
/* 5: */ getop_jmp_down( 5),
|
||||
/* 6: */ getop_assignment( 0, OPCODE_ARG_TYPE_SMALLINT, 253),
|
||||
/* 7: */ getop_assignment( 1, OPCODE_ARG_TYPE_NUMBER, 2),
|
||||
/* 8: */ getop_is_false_jmp( 1, 10),
|
||||
/* 9: */ getop_exitval( 0),
|
||||
/* 10: */ getop_exitval( 1)
|
||||
/* 0: */ getop_reg_var_decl( 255, 255),
|
||||
/* 1: */ getop_var_decl( 0),
|
||||
/* 2: */ getop_var_decl( 1),
|
||||
/* 3: */ getop_assignment( 0, OPCODE_ARG_TYPE_STRING, 1),
|
||||
/* 4: */ getop_assignment( 1, OPCODE_ARG_TYPE_VARIABLE, 0),
|
||||
/* 5: */ getop_is_true_jmp( 1, 7),
|
||||
/* 6: */ getop_jmp_down( 5),
|
||||
/* 7: */ getop_assignment( 0, OPCODE_ARG_TYPE_SMALLINT, 253),
|
||||
/* 8: */ getop_assignment( 1, OPCODE_ARG_TYPE_NUMBER, 2),
|
||||
/* 9: */ getop_is_false_jmp( 1, 11),
|
||||
/* 10: */ getop_exitval( 0),
|
||||
/* 11: */ getop_exitval( 1)
|
||||
};
|
||||
|
||||
mem_init();
|
||||
|
||||
@ -26,6 +26,7 @@ main( int __unused argc,
|
||||
char __unused **argv)
|
||||
{
|
||||
const OPCODE test_program[] = {
|
||||
getop_reg_var_decl( 255, 255),
|
||||
getop_var_decl( 0),
|
||||
getop_var_decl( 1),
|
||||
getop_assignment( 0, OPCODE_ARG_TYPE_SMALLINT, 253),
|
||||
|
||||
@ -26,6 +26,7 @@ main( int __unused argc,
|
||||
char __unused **argv)
|
||||
{
|
||||
const OPCODE test_program[] = {
|
||||
getop_reg_var_decl( 255, 255),
|
||||
getop_var_decl( 0),
|
||||
getop_var_decl( 1),
|
||||
getop_assignment( 0, OPCODE_ARG_TYPE_SMALLINT, 253),
|
||||
|
||||
@ -26,6 +26,7 @@ main( int __unused argc,
|
||||
char __unused **argv)
|
||||
{
|
||||
const OPCODE test_program[] = {
|
||||
getop_reg_var_decl( 255, 255),
|
||||
getop_var_decl( 0),
|
||||
getop_var_decl( 1),
|
||||
getop_assignment( 0, OPCODE_ARG_TYPE_SMALLINT, 253),
|
||||
|
||||
@ -26,6 +26,7 @@ main( int __unused argc,
|
||||
char __unused **argv)
|
||||
{
|
||||
const OPCODE test_program[] = {
|
||||
getop_reg_var_decl( 255, 255),
|
||||
getop_var_decl( 0),
|
||||
getop_var_decl( 1),
|
||||
getop_assignment( 0, OPCODE_ARG_TYPE_SMALLINT, 253),
|
||||
|
||||
@ -26,10 +26,11 @@ main( int __unused argc,
|
||||
char __unused **argv)
|
||||
{
|
||||
const OPCODE test_program[] = {
|
||||
getop_var_decl( 0),
|
||||
getop_is_true_jmp( 0, 3),
|
||||
getop_exitval( 0),
|
||||
getop_exitval( 1)
|
||||
/* 0: */ getop_reg_var_decl( 255, 255),
|
||||
/* 1: */ getop_var_decl( 0),
|
||||
/* 2: */ getop_is_true_jmp( 0, 4),
|
||||
/* 3: */ getop_exitval( 0),
|
||||
/* 4: */ getop_exitval( 1)
|
||||
};
|
||||
|
||||
mem_init();
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user