Files
jerryscript/src/libcoreint/opcodes-ecma-relational.c
T
Ilmir Usmanov dc8ab27900 Split parser into parser itself, opcodes dumper and syntax errors checker.
Add internal hash map of literal indexes:
  In this hash map key is pair of block number and literal's unique identifier in the block, and the value is a literal index that unique in the whole program.
  Block is a continues array of opcodes. So, bytecode is splitted into blocks.
  Each block has its own uid counter. To get literal index the interpreter looks up it in the hash map.
  Thus, now JS program is able to have more than 255 identifiers/string literals.
  The first 128 (0-127) uids are reserved for block's uid counter, the other 128 (128-255) are reserved for tmp variables.
2014-12-10 18:31:59 +03:00

336 lines
11 KiB
C

/* 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.
*/
#include "opcodes.h"
#include "opcodes-ecma-support.h"
/**
* 'Less-than' opcode handler.
*
* See also: ECMA-262 v5, 11.8.1
*
* @return completion value
* Returned value must be freed with ecma_free_completion_value
*/
ecma_completion_value_t
opfunc_less_than (opcode_t opdata, /**< operation data */
int_data_t *int_data) /**< interpreter context */
{
const idx_t dst_var_idx = opdata.data.less_than.dst;
const idx_t left_var_idx = opdata.data.less_than.var_left;
const idx_t right_var_idx = opdata.data.less_than.var_right;
ecma_completion_value_t ret_value;
ECMA_TRY_CATCH (left_value, get_variable_value (int_data, left_var_idx, false), ret_value);
ECMA_TRY_CATCH (right_value, get_variable_value (int_data, right_var_idx, false), ret_value);
ECMA_TRY_CATCH (compare_result,
ecma_op_abstract_relational_compare (ecma_get_completion_value_value (left_value),
ecma_get_completion_value_value (right_value),
true),
ret_value);
ecma_simple_value_t res;
if (ecma_is_value_undefined (ecma_get_completion_value_value (compare_result)))
{
res = ECMA_SIMPLE_VALUE_FALSE;
}
else
{
JERRY_ASSERT (ecma_is_value_boolean (ecma_get_completion_value_value (compare_result)));
res = (ecma_is_completion_value_normal_true (compare_result) ? ECMA_SIMPLE_VALUE_TRUE : ECMA_SIMPLE_VALUE_FALSE);
}
ret_value = set_variable_value (int_data, int_data->pos, dst_var_idx, ecma_make_simple_value (res));
ECMA_FINALIZE (compare_result);
ECMA_FINALIZE (right_value);
ECMA_FINALIZE (left_value);
int_data->pos++;
return ret_value;
} /* opfunc_less_than */
/**
* 'Greater-than' opcode handler.
*
* See also: ECMA-262 v5, 11.8.2
*
* @return completion value
* Returned value must be freed with ecma_free_completion_value
*/
ecma_completion_value_t
opfunc_greater_than (opcode_t opdata, /**< operation data */
int_data_t *int_data) /**< interpreter context */
{
const idx_t dst_var_idx = opdata.data.greater_than.dst;
const idx_t left_var_idx = opdata.data.greater_than.var_left;
const idx_t right_var_idx = opdata.data.greater_than.var_right;
ecma_completion_value_t ret_value;
ECMA_TRY_CATCH (left_value, get_variable_value (int_data, left_var_idx, false), ret_value);
ECMA_TRY_CATCH (right_value, get_variable_value (int_data, right_var_idx, false), ret_value);
ECMA_TRY_CATCH (compare_result,
ecma_op_abstract_relational_compare (ecma_get_completion_value_value (right_value),
ecma_get_completion_value_value (left_value),
false),
ret_value);
ecma_simple_value_t res;
if (ecma_is_value_undefined (ecma_get_completion_value_value (compare_result)))
{
res = ECMA_SIMPLE_VALUE_FALSE;
}
else
{
JERRY_ASSERT (ecma_is_value_boolean (ecma_get_completion_value_value (compare_result)));
res = (ecma_is_completion_value_normal_true (compare_result) ? ECMA_SIMPLE_VALUE_TRUE : ECMA_SIMPLE_VALUE_FALSE);
}
ret_value = set_variable_value (int_data, int_data->pos, dst_var_idx, ecma_make_simple_value (res));
ECMA_FINALIZE (compare_result);
ECMA_FINALIZE (right_value);
ECMA_FINALIZE (left_value);
int_data->pos++;
return ret_value;
} /* opfunc_greater_than */
/**
* 'Less-than-or-equal' opcode handler.
*
* See also: ECMA-262 v5, 11.8.3
*
* @return completion value
* Returned value must be freed with ecma_free_completion_value
*/
ecma_completion_value_t
opfunc_less_or_equal_than (opcode_t opdata, /**< operation data */
int_data_t *int_data) /**< interpreter context */
{
const idx_t dst_var_idx = opdata.data.less_or_equal_than.dst;
const idx_t left_var_idx = opdata.data.less_or_equal_than.var_left;
const idx_t right_var_idx = opdata.data.less_or_equal_than.var_right;
ecma_completion_value_t ret_value;
ECMA_TRY_CATCH (left_value, get_variable_value (int_data, left_var_idx, false), ret_value);
ECMA_TRY_CATCH (right_value, get_variable_value (int_data, right_var_idx, false), ret_value);
ECMA_TRY_CATCH (compare_result,
ecma_op_abstract_relational_compare (ecma_get_completion_value_value (right_value),
ecma_get_completion_value_value (left_value),
false),
ret_value);
ecma_simple_value_t res;
if (ecma_is_value_undefined (ecma_get_completion_value_value (compare_result)))
{
res = ECMA_SIMPLE_VALUE_FALSE;
}
else
{
JERRY_ASSERT (ecma_is_value_boolean (ecma_get_completion_value_value (compare_result)));
if (ecma_is_completion_value_normal_true (compare_result))
{
res = ECMA_SIMPLE_VALUE_FALSE;
}
else
{
res = ECMA_SIMPLE_VALUE_TRUE;
}
}
ret_value = set_variable_value (int_data, int_data->pos, dst_var_idx, ecma_make_simple_value (res));
ECMA_FINALIZE (compare_result);
ECMA_FINALIZE (right_value);
ECMA_FINALIZE (left_value);
int_data->pos++;
return ret_value;
} /* opfunc_less_or_equal_than */
/**
* 'Greater-than-or-equal' opcode handler.
*
* See also: ECMA-262 v5, 11.8.4
*
* @return completion value
* Returned value must be freed with ecma_free_completion_value
*/
ecma_completion_value_t
opfunc_greater_or_equal_than (opcode_t opdata, /**< operation data */
int_data_t *int_data) /**< interpreter context */
{
const idx_t dst_var_idx = opdata.data.greater_or_equal_than.dst;
const idx_t left_var_idx = opdata.data.greater_or_equal_than.var_left;
const idx_t right_var_idx = opdata.data.greater_or_equal_than.var_right;
ecma_completion_value_t ret_value;
ECMA_TRY_CATCH (left_value, get_variable_value (int_data, left_var_idx, false), ret_value);
ECMA_TRY_CATCH (right_value, get_variable_value (int_data, right_var_idx, false), ret_value);
ECMA_TRY_CATCH (compare_result,
ecma_op_abstract_relational_compare (ecma_get_completion_value_value (left_value),
ecma_get_completion_value_value (right_value),
true),
ret_value);
ecma_simple_value_t res;
if (ecma_is_value_undefined (ecma_get_completion_value_value (compare_result)))
{
res = ECMA_SIMPLE_VALUE_FALSE;
}
else
{
JERRY_ASSERT (ecma_is_value_boolean (ecma_get_completion_value_value (compare_result)));
if (ecma_is_completion_value_normal_true (compare_result))
{
res = ECMA_SIMPLE_VALUE_FALSE;
}
else
{
res = ECMA_SIMPLE_VALUE_TRUE;
}
}
ret_value = set_variable_value (int_data, int_data->pos, dst_var_idx, ecma_make_simple_value (res));
ECMA_FINALIZE (compare_result);
ECMA_FINALIZE (right_value);
ECMA_FINALIZE (left_value);
int_data->pos++;
return ret_value;
} /* opfunc_greater_or_equal_than */
/**
* 'instanceof' opcode handler.
*
* See also: ECMA-262 v5, 11.8.6
*
* @return completion value
* returned value must be freed with ecma_free_completion_value.
*/
ecma_completion_value_t
opfunc_instanceof (opcode_t opdata __unused, /**< operation data */
int_data_t *int_data __unused) /**< interpreter context */
{
const idx_t dst_idx = opdata.data.instanceof.dst;
const idx_t left_var_idx = opdata.data.instanceof.var_left;
const idx_t right_var_idx = opdata.data.instanceof.var_right;
ecma_completion_value_t ret_value;
ECMA_TRY_CATCH (left_value, get_variable_value (int_data, left_var_idx, false), ret_value);
ECMA_TRY_CATCH (right_value, get_variable_value (int_data, right_var_idx, false), ret_value);
if (!ecma_is_value_object (ecma_get_completion_value_value (right_value)))
{
ret_value = ecma_make_throw_obj_completion_value (ecma_new_standard_error (ECMA_ERROR_TYPE));
}
else
{
ecma_object_t *right_value_obj_p = ecma_get_object_from_completion_value (right_value);
ECMA_TRY_CATCH (is_instance_of,
ecma_op_object_has_instance (right_value_obj_p,
ecma_get_completion_value_value (left_value)),
ret_value);
ret_value = set_variable_value (int_data, int_data->pos, dst_idx, ecma_get_completion_value_value (is_instance_of));
ECMA_FINALIZE (is_instance_of);
}
ECMA_FINALIZE (right_value);
ECMA_FINALIZE (left_value);
int_data->pos++;
return ret_value;
} /* opfunc_instanceof */
/**
* 'in' opcode handler.
*
* See also: ECMA-262 v5, 11.8.7
*
* @return completion value
* returned value must be freed with ecma_free_completion_value.
*/
ecma_completion_value_t
opfunc_in (opcode_t opdata __unused, /**< operation data */
int_data_t *int_data __unused) /**< interpreter context */
{
const idx_t dst_idx = opdata.data.in.dst;
const idx_t left_var_idx = opdata.data.in.var_left;
const idx_t right_var_idx = opdata.data.in.var_right;
ecma_completion_value_t ret_value;
ECMA_TRY_CATCH (left_value, get_variable_value (int_data, left_var_idx, false), ret_value);
ECMA_TRY_CATCH (right_value, get_variable_value (int_data, right_var_idx, false), ret_value);
if (!ecma_is_value_object (ecma_get_completion_value_value (right_value)))
{
ret_value = ecma_make_throw_obj_completion_value (ecma_new_standard_error (ECMA_ERROR_TYPE));
}
else
{
ECMA_TRY_CATCH (str_left_value, ecma_op_to_string (ecma_get_completion_value_value (left_value)), ret_value);
ecma_simple_value_t is_in = ECMA_SIMPLE_VALUE_UNDEFINED;
ecma_string_t *left_value_prop_name_p = ecma_get_string_from_completion_value (str_left_value);
ecma_object_t *right_value_obj_p = ecma_get_object_from_completion_value (right_value);
if (ecma_op_object_get_property (right_value_obj_p, left_value_prop_name_p) != NULL)
{
is_in = ECMA_SIMPLE_VALUE_TRUE;
}
else
{
is_in = ECMA_SIMPLE_VALUE_FALSE;
}
ret_value = set_variable_value (int_data, int_data->pos,
dst_idx,
ecma_make_simple_value (is_in));
ECMA_FINALIZE (str_left_value);
}
ECMA_FINALIZE (right_value);
ECMA_FINALIZE (left_value);
int_data->pos++;
return ret_value;
} /* opfunc_in */