Implementing 'with' opcode; replacing 'end_with' opcode with 'meta' opcode of corresponding type.
This commit is contained in:
@@ -45,8 +45,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#define OP_UNIMPLEMENTED_LIST(op) \
|
#define OP_UNIMPLEMENTED_LIST(op) \
|
||||||
op (with) \
|
|
||||||
op (end_with) \
|
|
||||||
static char __unused unimplemented_list_end
|
static char __unused unimplemented_list_end
|
||||||
|
|
||||||
#define DEFINE_UNIMPLEMENTED_OP(op) \
|
#define DEFINE_UNIMPLEMENTED_OP(op) \
|
||||||
@@ -1402,6 +1400,68 @@ opfunc_this (opcode_t opdata, /**< operation data */
|
|||||||
return ret_value;
|
return ret_value;
|
||||||
} /* opfunc_this */
|
} /* opfunc_this */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 'With' opcode handler.
|
||||||
|
*
|
||||||
|
* See also: ECMA-262 v5, 12.10
|
||||||
|
*
|
||||||
|
* @return completion value
|
||||||
|
* Returned value must be freed with ecma_free_completion_value
|
||||||
|
*/
|
||||||
|
ecma_completion_value_t
|
||||||
|
opfunc_with (opcode_t opdata, /**< operation data */
|
||||||
|
int_data_t *int_data) /**< interpreter context */
|
||||||
|
{
|
||||||
|
const idx_t expr_var_idx = opdata.data.with.expr;
|
||||||
|
|
||||||
|
int_data->pos++;
|
||||||
|
|
||||||
|
ecma_completion_value_t ret_value;
|
||||||
|
|
||||||
|
ECMA_TRY_CATCH (expr_value,
|
||||||
|
get_variable_value (int_data,
|
||||||
|
expr_var_idx,
|
||||||
|
false),
|
||||||
|
ret_value);
|
||||||
|
ECMA_TRY_CATCH (obj_expr_value,
|
||||||
|
ecma_op_to_object (expr_value.value),
|
||||||
|
ret_value);
|
||||||
|
|
||||||
|
ecma_object_t *obj_p = ECMA_GET_POINTER (obj_expr_value.value.value);
|
||||||
|
|
||||||
|
ecma_object_t *old_env_p = int_data->lex_env_p;
|
||||||
|
ecma_object_t *new_env_p = ecma_create_object_lex_env (old_env_p,
|
||||||
|
obj_p,
|
||||||
|
true);
|
||||||
|
int_data->lex_env_p = new_env_p;
|
||||||
|
|
||||||
|
ecma_completion_value_t evaluation_completion = run_int_loop (int_data);
|
||||||
|
|
||||||
|
if (evaluation_completion.type == ECMA_COMPLETION_TYPE_META)
|
||||||
|
{
|
||||||
|
opcode_t meta_opcode = read_opcode (int_data->pos);
|
||||||
|
JERRY_ASSERT (meta_opcode.op_idx == __op__idx_meta);
|
||||||
|
JERRY_ASSERT (meta_opcode.data.meta.type == OPCODE_META_TYPE_END_WITH);
|
||||||
|
|
||||||
|
int_data->pos++;
|
||||||
|
|
||||||
|
ret_value = ecma_make_empty_completion_value ();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ret_value = evaluation_completion;
|
||||||
|
}
|
||||||
|
|
||||||
|
int_data->lex_env_p = old_env_p;
|
||||||
|
|
||||||
|
ecma_deref_object (new_env_p);
|
||||||
|
|
||||||
|
ECMA_FINALIZE (obj_expr_value);
|
||||||
|
ECMA_FINALIZE (expr_value);
|
||||||
|
|
||||||
|
return ret_value;
|
||||||
|
} /* opfunc_with */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Evaluate argument of typeof.
|
* Evaluate argument of typeof.
|
||||||
*
|
*
|
||||||
@@ -1682,6 +1742,7 @@ opfunc_meta (opcode_t opdata, /**< operation data */
|
|||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
case OPCODE_META_TYPE_VARG:
|
case OPCODE_META_TYPE_VARG:
|
||||||
|
case OPCODE_META_TYPE_END_WITH:
|
||||||
{
|
{
|
||||||
return ecma_make_completion_value (ECMA_COMPLETION_TYPE_META,
|
return ecma_make_completion_value (ECMA_COMPLETION_TYPE_META,
|
||||||
ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY),
|
ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY),
|
||||||
|
|||||||
@@ -56,7 +56,8 @@ typedef enum
|
|||||||
OPCODE_META_TYPE_VARG, /**< element (var_idx) of arguments' list */
|
OPCODE_META_TYPE_VARG, /**< element (var_idx) of arguments' list */
|
||||||
OPCODE_META_TYPE_VARG_PROP_DATA, /**< name (lit_idx) and value (var_idx) for a data property descriptor */
|
OPCODE_META_TYPE_VARG_PROP_DATA, /**< name (lit_idx) and value (var_idx) for a data property descriptor */
|
||||||
OPCODE_META_TYPE_VARG_PROP_GETTER, /**< name (lit_idx) and getter (var_idx) for an accessor property descriptor */
|
OPCODE_META_TYPE_VARG_PROP_GETTER, /**< name (lit_idx) and getter (var_idx) for an accessor property descriptor */
|
||||||
OPCODE_META_TYPE_VARG_PROP_SETTER /**< name (lit_idx) and setter (var_idx) for an accessor property descriptor */
|
OPCODE_META_TYPE_VARG_PROP_SETTER, /**< name (lit_idx) and setter (var_idx) for an accessor property descriptor */
|
||||||
|
OPCODE_META_TYPE_END_WITH /**< end of with statement */
|
||||||
} opcode_meta_type;
|
} opcode_meta_type;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
@@ -95,8 +96,7 @@ typedef struct
|
|||||||
p##_2 (a, delete_var, lhs, name) \
|
p##_2 (a, delete_var, lhs, name) \
|
||||||
p##_3 (a, delete_prop, lhs, base, name) \
|
p##_3 (a, delete_prop, lhs, base, name) \
|
||||||
p##_2 (a, typeof, lhs, obj) \
|
p##_2 (a, typeof, lhs, obj) \
|
||||||
p##_1 (a, with, expr) \
|
p##_1 (a, with, expr)
|
||||||
p##_0 (a, end_with)
|
|
||||||
|
|
||||||
#define OP_ASSIGNMENTS(p, a) \
|
#define OP_ASSIGNMENTS(p, a) \
|
||||||
p##_3 (a, assignment, var_left, type_value_right, value_right)
|
p##_3 (a, assignment, var_left, type_value_right, value_right)
|
||||||
|
|||||||
@@ -93,7 +93,8 @@ ecma_create_object_lex_env (ecma_object_t *outer_lexical_environment_p, /**< out
|
|||||||
ecma_object_t *binding_obj_p, /**< binding object */
|
ecma_object_t *binding_obj_p, /**< binding object */
|
||||||
bool provide_this) /**< provideThis flag */
|
bool provide_this) /**< provideThis flag */
|
||||||
{
|
{
|
||||||
JERRY_ASSERT(binding_obj_p != NULL);
|
JERRY_ASSERT(binding_obj_p != NULL
|
||||||
|
&& !binding_obj_p->is_lexical_environment);
|
||||||
|
|
||||||
ecma_object_t *new_lexical_environment_p = ecma_alloc_object ();
|
ecma_object_t *new_lexical_environment_p = ecma_alloc_object ();
|
||||||
ecma_init_gc_info (new_lexical_environment_p);
|
ecma_init_gc_info (new_lexical_environment_p);
|
||||||
|
|||||||
@@ -391,7 +391,24 @@ ecma_op_to_string (ecma_value_t value) /**< ecma-value */
|
|||||||
ecma_completion_value_t
|
ecma_completion_value_t
|
||||||
ecma_op_to_object (ecma_value_t value) /**< ecma-value */
|
ecma_op_to_object (ecma_value_t value) /**< ecma-value */
|
||||||
{
|
{
|
||||||
JERRY_UNIMPLEMENTED_REF_UNUSED_VARS(value);
|
switch ((ecma_type_t)value.value_type)
|
||||||
|
{
|
||||||
|
case ECMA_TYPE_SIMPLE:
|
||||||
|
case ECMA_TYPE_NUMBER:
|
||||||
|
case ECMA_TYPE_STRING:
|
||||||
|
{
|
||||||
|
JERRY_UNIMPLEMENTED ();
|
||||||
|
}
|
||||||
|
|
||||||
|
case ECMA_TYPE_OBJECT:
|
||||||
|
{
|
||||||
|
return ecma_make_completion_value (ECMA_COMPLETION_TYPE_NORMAL,
|
||||||
|
ecma_copy_value (value, true),
|
||||||
|
ECMA_TARGET_ID_RESERVED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
JERRY_UNREACHABLE ();
|
||||||
} /* ecma_op_to_object */
|
} /* ecma_op_to_object */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -36,6 +36,9 @@
|
|||||||
ecma_object_t*
|
ecma_object_t*
|
||||||
ecma_new_standard_error (ecma_standard_error_t error_type) /**< native error type */
|
ecma_new_standard_error (ecma_standard_error_t error_type) /**< native error type */
|
||||||
{
|
{
|
||||||
|
/* SyntaxError should be treated as an early error */
|
||||||
|
JERRY_ASSERT (error_type != ECMA_ERROR_SYNTAX);
|
||||||
|
|
||||||
JERRY_UNIMPLEMENTED_REF_UNUSED_VARS(error_type);
|
JERRY_UNIMPLEMENTED_REF_UNUSED_VARS(error_type);
|
||||||
} /* ecma_new_standard_error */
|
} /* ecma_new_standard_error */
|
||||||
|
|
||||||
|
|||||||
@@ -2083,7 +2083,7 @@ parse_with_statement (void)
|
|||||||
skip_newlines ();
|
skip_newlines ();
|
||||||
parse_statement ();
|
parse_statement ();
|
||||||
|
|
||||||
DUMP_VOID_OPCODE (end_with);
|
DUMP_OPCODE_3 (meta, OPCODE_META_TYPE_END_WITH, INVALID_VALUE, INVALID_VALUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* switch_statement
|
/* switch_statement
|
||||||
|
|||||||
@@ -347,8 +347,7 @@ pp_opcode (opcode_counter_t oc, opcode_t opcode, bool is_rewrite)
|
|||||||
uint8_t opcode_num = opcode.op_idx;
|
uint8_t opcode_num = opcode.op_idx;
|
||||||
|
|
||||||
__printf ("%3d: %20s ", oc, opcode_names[opcode_num]);
|
__printf ("%3d: %20s ", oc, opcode_names[opcode_num]);
|
||||||
if (opcode_num != NAME_TO_ID (nop) && opcode_num != NAME_TO_ID (ret)
|
if (opcode_num != NAME_TO_ID (nop) && opcode_num != NAME_TO_ID (ret))
|
||||||
&& opcode_num != NAME_TO_ID (end_with))
|
|
||||||
{
|
{
|
||||||
for (i = 1; i < opcode_sizes[opcode_num]; i++)
|
for (i = 1; i < opcode_sizes[opcode_num]; i++)
|
||||||
{
|
{
|
||||||
@@ -415,7 +414,6 @@ pp_opcode (opcode_counter_t oc, opcode_t opcode, bool is_rewrite)
|
|||||||
CASE_EXIT (exitval, "exit", status_code)
|
CASE_EXIT (exitval, "exit", status_code)
|
||||||
CASE_SINGLE_ADDRESS (retval, "return", ret_value)
|
CASE_SINGLE_ADDRESS (retval, "return", ret_value)
|
||||||
CASE_ZERO_ADDRESS (ret, "return")
|
CASE_ZERO_ADDRESS (ret, "return")
|
||||||
CASE_ZERO_ADDRESS (end_with, "")
|
|
||||||
CASE_ZERO_ADDRESS (nop, "")
|
CASE_ZERO_ADDRESS (nop, "")
|
||||||
TODO (Refine to match new opcodes)
|
TODO (Refine to match new opcodes)
|
||||||
CASE_VARG_1_LHS (array_decl, lhs, "=", "[", list, "]")
|
CASE_VARG_1_LHS (array_decl, lhs, "=", "[", list, "]")
|
||||||
|
|||||||
+2
-3
@@ -38,8 +38,7 @@ opcodes_equal (const opcode_t *opcodes1, opcode_t *opcodes2, uint16_t size)
|
|||||||
if (opcode_num1 != opcode_num2)
|
if (opcode_num1 != opcode_num2)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (opcode_num1 == NAME_TO_ID (nop) || opcode_num1 == NAME_TO_ID (ret)
|
if (opcode_num1 == NAME_TO_ID (nop) || opcode_num1 == NAME_TO_ID (ret))
|
||||||
|| opcode_num1 == NAME_TO_ID (end_with))
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
for (j = 1; j < opcode_sizes[opcode_num1]; j++)
|
for (j = 1; j < opcode_sizes[opcode_num1]; j++)
|
||||||
@@ -50,4 +49,4 @@ opcodes_equal (const opcode_t *opcodes1, opcode_t *opcodes2, uint16_t size)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // COMMON_H
|
#endif // COMMON_H
|
||||||
|
|||||||
Reference in New Issue
Block a user