Import of the watch repository from Pebble

This commit is contained in:
Matthieu Jeanson 2024-12-12 16:43:03 -08:00 committed by Katharine Berry
commit 3b92768480
10334 changed files with 2564465 additions and 0 deletions

View file

@ -0,0 +1,224 @@
/* Copyright 2014-2016 Samsung Electronics Co., Ltd.
* Copyright 2015-2016 University of Szeged.
*
* 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 "ecma-alloc.h"
#include "ecma-conversion.h"
#include "ecma-helpers.h"
#include "ecma-number-arithmetic.h"
#include "ecma-objects.h"
#include "ecma-try-catch-macro.h"
#include "opcodes.h"
#include "jrt-libc-includes.h"
/** \addtogroup vm Virtual machine
* @{
*
* \addtogroup vm_opcodes Opcodes
* @{
*/
/**
* Perform ECMA number arithmetic operation.
*
* The algorithm of the operation is following:
* leftNum = ToNumber (leftValue);
* rightNum = ToNumber (rightValue);
* result = leftNum ArithmeticOp rightNum;
*
* @return ecma value
* Returned value must be freed with ecma_free_value
*/
ecma_value_t
do_number_arithmetic (number_arithmetic_op op, /**< number arithmetic operation */
ecma_value_t left_value, /**< left value */
ecma_value_t right_value) /**< right value */
{
ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY);
ECMA_OP_TO_NUMBER_TRY_CATCH (num_left, left_value, ret_value);
ECMA_OP_TO_NUMBER_TRY_CATCH (num_right, right_value, ret_value);
ecma_number_t result = ECMA_NUMBER_ZERO;
switch (op)
{
case NUMBER_ARITHMETIC_SUBSTRACTION:
{
result = ecma_number_substract (num_left, num_right);
break;
}
case NUMBER_ARITHMETIC_MULTIPLICATION:
{
result = ecma_number_multiply (num_left, num_right);
break;
}
case NUMBER_ARITHMETIC_DIVISION:
{
result = ecma_number_divide (num_left, num_right);
break;
}
case NUMBER_ARITHMETIC_REMAINDER:
{
result = ecma_op_number_remainder (num_left, num_right);
break;
}
}
ret_value = ecma_make_number_value (result);
ECMA_OP_TO_NUMBER_FINALIZE (num_right);
ECMA_OP_TO_NUMBER_FINALIZE (num_left);
return ret_value;
} /* do_number_arithmetic */
/**
* 'Addition' opcode handler.
*
* See also: ECMA-262 v5, 11.6.1
*
* @return ecma value
* Returned value must be freed with ecma_free_value
*/
ecma_value_t
opfunc_addition (ecma_value_t left_value, /**< left value */
ecma_value_t right_value) /**< right value */
{
bool free_left_value = false;
bool free_right_value = false;
if (ecma_is_value_object (left_value))
{
ecma_object_t *obj_p = ecma_get_object_from_value (left_value);
left_value = ecma_op_object_default_value (obj_p, ECMA_PREFERRED_TYPE_NO);
free_left_value = true;
if (ECMA_IS_VALUE_ERROR (left_value))
{
return left_value;
}
}
if (ecma_is_value_object (right_value))
{
ecma_object_t *obj_p = ecma_get_object_from_value (right_value);
right_value = ecma_op_object_default_value (obj_p, ECMA_PREFERRED_TYPE_NO);
free_right_value = true;
if (ECMA_IS_VALUE_ERROR (right_value))
{
if (free_left_value)
{
ecma_free_value (left_value);
}
return right_value;
}
}
ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY);
if (ecma_is_value_string (left_value)
|| ecma_is_value_string (right_value))
{
ECMA_TRY_CATCH (str_left_value, ecma_op_to_string (left_value), ret_value);
ECMA_TRY_CATCH (str_right_value, ecma_op_to_string (right_value), ret_value);
ecma_string_t *string1_p = ecma_get_string_from_value (str_left_value);
ecma_string_t *string2_p = ecma_get_string_from_value (str_right_value);
ecma_string_t *concat_str_p = ecma_concat_ecma_strings (string1_p, string2_p);
ret_value = ecma_make_string_value (concat_str_p);
ECMA_FINALIZE (str_right_value);
ECMA_FINALIZE (str_left_value);
}
else
{
ECMA_OP_TO_NUMBER_TRY_CATCH (num_left, left_value, ret_value);
ECMA_OP_TO_NUMBER_TRY_CATCH (num_right, right_value, ret_value);
ret_value = ecma_make_number_value (ecma_number_add (num_left, num_right));
ECMA_OP_TO_NUMBER_FINALIZE (num_right);
ECMA_OP_TO_NUMBER_FINALIZE (num_left);
}
if (free_left_value)
{
ecma_free_value (left_value);
}
if (free_right_value)
{
ecma_free_value (right_value);
}
return ret_value;
} /* opfunc_addition */
/**
* 'Unary "+"' opcode handler.
*
* See also: ECMA-262 v5, 11.4, 11.4.6
*
* @return ecma value
* Returned value must be freed with ecma_free_value
*/
ecma_value_t
opfunc_unary_plus (ecma_value_t left_value) /**< left value */
{
ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY);
ECMA_OP_TO_NUMBER_TRY_CATCH (num_var_value,
left_value,
ret_value);
ret_value = ecma_make_number_value (num_var_value);
ECMA_OP_TO_NUMBER_FINALIZE (num_var_value);
return ret_value;
} /* opfunc_unary_plus */
/**
* 'Unary "-"' opcode handler.
*
* See also: ECMA-262 v5, 11.4, 11.4.7
*
* @return ecma value
* Returned value must be freed with ecma_free_value
*/
ecma_value_t
opfunc_unary_minus (ecma_value_t left_value) /**< left value */
{
ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY);
ECMA_OP_TO_NUMBER_TRY_CATCH (num_var_value,
left_value,
ret_value);
ret_value = ecma_make_number_value (ecma_number_negate (num_var_value));
ECMA_OP_TO_NUMBER_FINALIZE (num_var_value);
return ret_value;
} /* opfunc_unary_minus */
/**
* @}
* @}
*/

View file

@ -0,0 +1,157 @@
/* Copyright 2014-2016 Samsung Electronics Co., Ltd.
* Copyright 2015-2016 University of Szeged.
*
* 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 "ecma-alloc.h"
#include "ecma-conversion.h"
#include "ecma-helpers.h"
#include "ecma-try-catch-macro.h"
#include "opcodes.h"
/** \addtogroup vm Virtual machine
* @{
*
* \addtogroup vm_opcodes Opcodes
* @{
*/
/**
* Perform ECMA number logic operation.
*
* The algorithm of the operation is following:
* leftNum = ToNumber (leftValue);
* rightNum = ToNumber (rightValue);
* result = leftNum BitwiseLogicOp rightNum;
*
* @return ecma value
* Returned value must be freed with ecma_free_value
*/
ecma_value_t
do_number_bitwise_logic (number_bitwise_logic_op op, /**< number bitwise logic operation */
ecma_value_t left_value, /**< left value */
ecma_value_t right_value) /**< right value */
{
JERRY_STATIC_ASSERT (ECMA_DIRECT_TYPE_INTEGER_VALUE == 0,
ecma_direct_type_integer_value_must_be_zero_for_bitwise_logic);
JERRY_STATIC_ASSERT ((ECMA_DIRECT_TYPE_MASK | ECMA_VALUE_ERROR_FLAG) == ((1 << ECMA_DIRECT_SHIFT) - 1),
direct_type_mask_and_error_flag_must_fill_all_bits_before_the_value_starts);
JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (left_value)
&& !ECMA_IS_VALUE_ERROR (right_value));
if (ecma_are_values_integer_numbers (left_value, right_value))
{
switch (op)
{
case NUMBER_BITWISE_LOGIC_AND:
{
return left_value & right_value;
}
case NUMBER_BITWISE_LOGIC_OR:
{
return left_value | right_value;
}
case NUMBER_BITWISE_LOGIC_XOR:
{
return (left_value ^ right_value) & (ecma_value_t) (~((1 << ECMA_DIRECT_SHIFT) - 1));
}
case NUMBER_BITWISE_SHIFT_LEFT:
{
ecma_integer_value_t left_integer = ecma_get_integer_from_value (left_value);
ecma_integer_value_t right_integer = ecma_get_integer_from_value (right_value);
return ecma_make_int32_value ((int32_t) (left_integer << (right_integer & 0x1f)));
}
case NUMBER_BITWISE_SHIFT_RIGHT:
{
ecma_integer_value_t left_integer = ecma_get_integer_from_value (left_value);
ecma_integer_value_t right_integer = ecma_get_integer_from_value (right_value);
return ecma_make_integer_value (left_integer >> (right_integer & 0x1f));
}
case NUMBER_BITWISE_SHIFT_URIGHT:
{
uint32_t left_uint32 = (uint32_t) ecma_get_integer_from_value (left_value);
ecma_integer_value_t right_integer = ecma_get_integer_from_value (right_value);
return ecma_make_uint32_value (left_uint32 >> (right_integer & 0x1f));
}
case NUMBER_BITWISE_NOT:
{
return (~right_value) & (ecma_value_t) (~((1 << ECMA_DIRECT_SHIFT) - 1));
}
}
}
ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY);
ECMA_OP_TO_NUMBER_TRY_CATCH (num_left, left_value, ret_value);
ECMA_OP_TO_NUMBER_TRY_CATCH (num_right, right_value, ret_value);
ecma_number_t result = ECMA_NUMBER_ZERO;
uint32_t right_uint32 = ecma_number_to_uint32 (num_right);
switch (op)
{
case NUMBER_BITWISE_LOGIC_AND:
{
uint32_t left_uint32 = ecma_number_to_uint32 (num_left);
result = (ecma_number_t) ((int32_t) (left_uint32 & right_uint32));
break;
}
case NUMBER_BITWISE_LOGIC_OR:
{
uint32_t left_uint32 = ecma_number_to_uint32 (num_left);
result = (ecma_number_t) ((int32_t) (left_uint32 | right_uint32));
break;
}
case NUMBER_BITWISE_LOGIC_XOR:
{
uint32_t left_uint32 = ecma_number_to_uint32 (num_left);
result = (ecma_number_t) ((int32_t) (left_uint32 ^ right_uint32));
break;
}
case NUMBER_BITWISE_SHIFT_LEFT:
{
result = (ecma_number_t) (ecma_number_to_int32 (num_left) << (right_uint32 & 0x1F));
break;
}
case NUMBER_BITWISE_SHIFT_RIGHT:
{
result = (ecma_number_t) (ecma_number_to_int32 (num_left) >> (right_uint32 & 0x1F));
break;
}
case NUMBER_BITWISE_SHIFT_URIGHT:
{
uint32_t left_uint32 = ecma_number_to_uint32 (num_left);
result = (ecma_number_t) (left_uint32 >> (right_uint32 & 0x1F));
break;
}
case NUMBER_BITWISE_NOT:
{
result = (ecma_number_t) ((int32_t) ~right_uint32);
break;
}
}
ret_value = ecma_make_number_value (result);
ECMA_OP_TO_NUMBER_FINALIZE (num_right);
ECMA_OP_TO_NUMBER_FINALIZE (num_left);
return ret_value;
} /* do_number_bitwise_logic */
/**
* @}
* @}
*/

View file

@ -0,0 +1,91 @@
/* Copyright 2014-2016 Samsung Electronics Co., Ltd.
* Copyright 2015-2016 University of Szeged.
*
* 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 "ecma-builtins.h"
#include "ecma-comparison.h"
#include "ecma-exceptions.h"
#include "ecma-function-object.h"
#include "ecma-globals.h"
#include "ecma-helpers.h"
#include "ecma-lex-env.h"
#include "ecma-try-catch-macro.h"
#include "opcodes.h"
#include "vm-defines.h"
/** \addtogroup vm Virtual machine
* @{
*
* \addtogroup vm_opcodes Opcodes
* @{
*/
/**
* 'Equals' opcode handler.
*
* See also: ECMA-262 v5, 11.9.1
*
* @return ecma value
* Returned value must be freed with ecma_free_value
*/
ecma_value_t
opfunc_equal_value (ecma_value_t left_value, /**< left value */
ecma_value_t right_value) /**< right value */
{
JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (left_value)
&& !ECMA_IS_VALUE_ERROR (right_value));
ecma_value_t compare_result = ecma_op_abstract_equality_compare (left_value,
right_value);
JERRY_ASSERT (ecma_is_value_boolean (compare_result)
|| ECMA_IS_VALUE_ERROR (compare_result));
return compare_result;
} /* opfunc_equal_value */
/**
* 'Does-not-equals' opcode handler.
*
* See also: ECMA-262 v5, 11.9.2
*
* @return ecma value
* Returned value must be freed with ecma_free_value
*/
ecma_value_t
opfunc_not_equal_value (ecma_value_t left_value, /**< left value */
ecma_value_t right_value) /**< right value */
{
JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (left_value)
&& !ECMA_IS_VALUE_ERROR (right_value));
ecma_value_t compare_result = ecma_op_abstract_equality_compare (left_value,
right_value);
JERRY_ASSERT (ecma_is_value_boolean (compare_result)
|| ECMA_IS_VALUE_ERROR (compare_result));
if (!ECMA_IS_VALUE_ERROR (compare_result))
{
compare_result = ecma_invert_boolean_value (compare_result);
}
return compare_result;
} /* opfunc_not_equal_value */
/**
* @}
* @}
*/

View file

@ -0,0 +1,249 @@
/* Copyright 2014-2016 Samsung Electronics Co., Ltd.
* Copyright 2015-2016 University of Szeged.
*
* 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 "ecma-comparison.h"
#include "ecma-conversion.h"
#include "ecma-exceptions.h"
#include "ecma-helpers.h"
#include "ecma-objects.h"
#include "ecma-try-catch-macro.h"
#include "opcodes.h"
/** \addtogroup vm Virtual machine
* @{
*
* \addtogroup vm_opcodes Opcodes
* @{
*/
/**
* 'Less-than' opcode handler.
*
* See also: ECMA-262 v5, 11.8.1
*
* @return ecma value
* Returned value must be freed with ecma_free_value
*/
ecma_value_t
opfunc_less_than (ecma_value_t left_value, /**< left value */
ecma_value_t right_value) /**< right value */
{
JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (left_value)
&& !ECMA_IS_VALUE_ERROR (right_value));
ecma_value_t ret_value = ecma_op_abstract_relational_compare (left_value, right_value, true);
if (ECMA_IS_VALUE_ERROR (ret_value))
{
return ret_value;
}
if (ecma_is_value_undefined (ret_value))
{
ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_FALSE);
}
else
{
JERRY_ASSERT (ecma_is_value_boolean (ret_value));
}
return ret_value;
} /* opfunc_less_than */
/**
* 'Greater-than' opcode handler.
*
* See also: ECMA-262 v5, 11.8.2
*
* @return ecma value
* Returned value must be freed with ecma_free_value
*/
ecma_value_t
opfunc_greater_than (ecma_value_t left_value, /**< left value */
ecma_value_t right_value) /**< right value */
{
JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (left_value)
&& !ECMA_IS_VALUE_ERROR (right_value));
ecma_value_t ret_value = ecma_op_abstract_relational_compare (left_value, right_value, false);
if (ECMA_IS_VALUE_ERROR (ret_value))
{
return ret_value;
}
if (ecma_is_value_undefined (ret_value))
{
ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_FALSE);
}
else
{
JERRY_ASSERT (ecma_is_value_boolean (ret_value));
}
return ret_value;
} /* opfunc_greater_than */
/**
* 'Less-than-or-equal' opcode handler.
*
* See also: ECMA-262 v5, 11.8.3
*
* @return ecma value
* Returned value must be freed with ecma_free_value
*/
ecma_value_t
opfunc_less_or_equal_than (ecma_value_t left_value, /**< left value */
ecma_value_t right_value) /**< right value */
{
JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (left_value)
&& !ECMA_IS_VALUE_ERROR (right_value));
ecma_value_t ret_value = ecma_op_abstract_relational_compare (left_value, right_value, false);
if (ECMA_IS_VALUE_ERROR (ret_value))
{
return ret_value;
}
if (ecma_is_value_undefined (ret_value))
{
ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_FALSE);
}
else
{
JERRY_ASSERT (ecma_is_value_boolean (ret_value));
ret_value = ecma_invert_boolean_value (ret_value);
}
return ret_value;
} /* opfunc_less_or_equal_than */
/**
* 'Greater-than-or-equal' opcode handler.
*
* See also: ECMA-262 v5, 11.8.4
*
* @return ecma value
* Returned value must be freed with ecma_free_value
*/
ecma_value_t
opfunc_greater_or_equal_than (ecma_value_t left_value, /**< left value */
ecma_value_t right_value) /**< right value */
{
JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (left_value)
&& !ECMA_IS_VALUE_ERROR (right_value));
ecma_value_t ret_value = ecma_op_abstract_relational_compare (left_value, right_value, true);
if (ECMA_IS_VALUE_ERROR (ret_value))
{
return ret_value;
}
if (ecma_is_value_undefined (ret_value))
{
ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_FALSE);
}
else
{
JERRY_ASSERT (ecma_is_value_boolean (ret_value));
ret_value = ecma_invert_boolean_value (ret_value);
}
return ret_value;
} /* opfunc_greater_or_equal_than */
/**
* 'instanceof' opcode handler.
*
* See also: ECMA-262 v5, 11.8.6
*
* @return ecma value
* returned value must be freed with ecma_free_value.
*/
ecma_value_t
opfunc_instanceof (ecma_value_t left_value, /**< left value */
ecma_value_t right_value) /**< right value */
{
ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY);
if (!ecma_is_value_object (right_value))
{
ret_value = ecma_raise_type_error (ECMA_ERR_MSG (""));
}
else
{
ecma_object_t *right_value_obj_p = ecma_get_object_from_value (right_value);
ECMA_TRY_CATCH (is_instance_of,
ecma_op_object_has_instance (right_value_obj_p, left_value),
ret_value);
ret_value = is_instance_of;
ECMA_FINALIZE (is_instance_of);
}
return ret_value;
} /* opfunc_instanceof */
/**
* 'in' opcode handler.
*
* See also: ECMA-262 v5, 11.8.7
*
* @return ecma value
* returned value must be freed with ecma_free_value.
*/
ecma_value_t
opfunc_in (ecma_value_t left_value, /**< left value */
ecma_value_t right_value) /**< right value */
{
ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY);
if (!ecma_is_value_object (right_value))
{
ret_value = ecma_raise_type_error (ECMA_ERR_MSG (""));
}
else
{
ECMA_TRY_CATCH (str_left_value, ecma_op_to_string (left_value), ret_value);
ecma_string_t *left_value_prop_name_p = ecma_get_string_from_value (str_left_value);
ecma_object_t *right_value_obj_p = ecma_get_object_from_value (right_value);
if (ecma_op_object_has_property (right_value_obj_p, left_value_prop_name_p))
{
ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_TRUE);
}
else
{
ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_FALSE);
}
ECMA_FINALIZE (str_left_value);
}
return ret_value;
} /* opfunc_in */
/**
* @}
* @}
*/

View file

@ -0,0 +1,339 @@
/* Copyright 2015-2016 Samsung Electronics Co., Ltd.
* Copyright 2015-2016 University of Szeged.
*
* 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 "ecma-alloc.h"
#include "ecma-builtins.h"
#include "ecma-conversion.h"
#include "ecma-exceptions.h"
#include "ecma-function-object.h"
#include "ecma-gc.h"
#include "ecma-globals.h"
#include "ecma-helpers.h"
#include "ecma-lex-env.h"
#include "ecma-objects.h"
#include "ecma-try-catch-macro.h"
#include "opcodes.h"
#include "vm-defines.h"
/** \addtogroup vm Virtual machine
* @{
*
* \addtogroup vm_opcodes Opcodes
* @{
*/
/**
* 'Variable declaration' opcode handler.
*
* See also: ECMA-262 v5, 10.5 - Declaration binding instantiation (block 8).
*
* @return ecma value
* Returned value is simple and so need not be freed.
* However, ecma_free_value may be called for it, but it is a no-op.
*/
ecma_value_t
vm_var_decl (vm_frame_ctx_t *frame_ctx_p, /**< interpreter context */
ecma_string_t *var_name_str_p) /**< variable name */
{
if (!ecma_op_has_binding (frame_ctx_p->lex_env_p, var_name_str_p))
{
const bool is_configurable_bindings = frame_ctx_p->is_eval_code;
ecma_value_t completion_value = ecma_op_create_mutable_binding (frame_ctx_p->lex_env_p,
var_name_str_p,
is_configurable_bindings);
JERRY_ASSERT (ecma_is_value_empty (completion_value));
/* 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_value_undefined (ecma_op_get_binding_value (frame_ctx_p->lex_env_p,
var_name_str_p,
true)));
}
return ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY);
} /* vm_var_decl */
/**
* 'Logical NOT Operator' opcode handler.
*
* See also: ECMA-262 v5, 11.4.9
*
* @return ecma value
* Returned value must be freed with ecma_free_value
*/
ecma_value_t
opfunc_logical_not (ecma_value_t left_value) /**< left value */
{
ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_TRUE);
if (ecma_op_to_boolean (left_value))
{
ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_FALSE);
}
return ret_value;
} /* opfunc_logical_not */
/**
* 'typeof' opcode handler.
*
* See also: ECMA-262 v5, 11.4.3
*
* @return ecma value
* Returned value must be freed with ecma_free_value
*/
ecma_value_t
opfunc_typeof (ecma_value_t left_value) /**< left value */
{
ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY);
ecma_string_t *type_str_p = NULL;
if (ecma_is_value_undefined (left_value))
{
type_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_UNDEFINED);
}
else if (ecma_is_value_null (left_value))
{
type_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_OBJECT);
}
else if (ecma_is_value_boolean (left_value))
{
type_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_BOOLEAN);
}
else if (ecma_is_value_number (left_value))
{
type_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_NUMBER);
}
else if (ecma_is_value_string (left_value))
{
type_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_STRING);
}
else
{
JERRY_ASSERT (ecma_is_value_object (left_value));
if (ecma_op_is_callable (left_value))
{
type_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_FUNCTION);
}
else
{
type_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_OBJECT);
}
}
ret_value = ecma_make_string_value (type_str_p);
return ret_value;
} /* opfunc_typeof */
/**
* Update getter or setter for object literals.
*/
void
opfunc_set_accessor (bool is_getter, /**< is getter accessor */
ecma_value_t object, /**< object value */
ecma_value_t accessor_name, /**< accessor name value */
ecma_value_t accessor) /**< accessor value */
{
ecma_object_t *object_p = ecma_get_object_from_value (object);
JERRY_ASSERT (ecma_is_value_string (accessor_name) || ecma_is_value_number (accessor_name));
ecma_string_t *accessor_name_p = ecma_get_string_from_value (ecma_op_to_string (accessor_name));
ecma_property_t *property_p = ecma_find_named_property (object_p, accessor_name_p);
if (property_p != NULL
&& ECMA_PROPERTY_GET_TYPE (*property_p) != ECMA_PROPERTY_TYPE_NAMEDACCESSOR)
{
ecma_delete_property (object_p, ECMA_PROPERTY_VALUE_PTR (property_p));
property_p = NULL;
}
if (property_p == NULL)
{
ecma_object_t *getter_func_p = NULL;
ecma_object_t *setter_func_p = NULL;
if (is_getter)
{
getter_func_p = ecma_get_object_from_value (accessor);
}
else
{
setter_func_p = ecma_get_object_from_value (accessor);
}
ecma_create_named_accessor_property (object_p,
accessor_name_p,
getter_func_p,
setter_func_p,
ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE);
}
else if (is_getter)
{
ecma_object_t *getter_func_p = ecma_get_object_from_value (accessor);
ecma_set_named_accessor_property_getter (object_p,
ECMA_PROPERTY_VALUE_PTR (property_p),
getter_func_p);
}
else
{
ecma_object_t *setter_func_p = ecma_get_object_from_value (accessor);
ecma_set_named_accessor_property_setter (object_p,
ECMA_PROPERTY_VALUE_PTR (property_p),
setter_func_p);
}
ecma_deref_ecma_string (accessor_name_p);
} /* opfunc_set_accessor */
/**
* Deletes an object property.
*
* @return ecma value
* Returned value must be freed with ecma_free_value
*/
ecma_value_t
vm_op_delete_prop (ecma_value_t object, /**< base object */
ecma_value_t property, /**< property name */
bool is_strict) /**< strict mode */
{
ecma_value_t completion_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY);
if (ecma_is_value_undefined (object))
{
completion_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_TRUE);
}
else
{
completion_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY);
ECMA_TRY_CATCH (check_coercible_ret,
ecma_op_check_object_coercible (object),
completion_value);
ECMA_TRY_CATCH (str_name_value,
ecma_op_to_string (property),
completion_value);
JERRY_ASSERT (ecma_is_value_string (str_name_value));
ecma_string_t *name_string_p = ecma_get_string_from_value (str_name_value);
ECMA_TRY_CATCH (obj_value, ecma_op_to_object (object), completion_value);
JERRY_ASSERT (ecma_is_value_object (obj_value));
ecma_object_t *obj_p = ecma_get_object_from_value (obj_value);
JERRY_ASSERT (!ecma_is_lexical_environment (obj_p));
ECMA_TRY_CATCH (delete_op_ret_val,
ecma_op_object_delete (obj_p, name_string_p, is_strict),
completion_value);
completion_value = delete_op_ret_val;
ECMA_FINALIZE (delete_op_ret_val);
ECMA_FINALIZE (obj_value);
ECMA_FINALIZE (str_name_value);
ECMA_FINALIZE (check_coercible_ret);
}
return completion_value;
} /* vm_op_delete_prop */
/**
* Deletes a variable.
*
* @return ecma value
* Returned value must be freed with ecma_free_value
*/
ecma_value_t
vm_op_delete_var (jmem_cpointer_t name_literal, /**< name literal */
ecma_object_t *lex_env_p) /**< lexical environment */
{
ecma_value_t completion_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY);
ecma_string_t *var_name_str_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_string_t, name_literal);
ecma_object_t *ref_base_lex_env_p = ecma_op_resolve_reference_base (lex_env_p, var_name_str_p);
if (ref_base_lex_env_p == NULL)
{
completion_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_TRUE);
}
else
{
JERRY_ASSERT (ecma_is_lexical_environment (ref_base_lex_env_p));
completion_value = ecma_op_delete_binding (ref_base_lex_env_p, var_name_str_p);
}
return completion_value;
} /* vm_op_delete_var */
/**
* 'for-in' opcode handler
*
* See also:
* ECMA-262 v5, 12.6.4
*
* @return completion value
* Returned value must be freed with ecma_free_value
*/
ecma_collection_header_t *
opfunc_for_in (ecma_value_t left_value, /**< left value */
ecma_value_t *result_obj_p) /**< expression object */
{
ecma_value_t compl_val = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY);
ecma_collection_header_t *prop_names_p = NULL;
/* 3. */
if (!ecma_is_value_undefined (left_value)
&& !ecma_is_value_null (left_value))
{
/* 4. */
ECMA_TRY_CATCH (obj_expr_value,
ecma_op_to_object (left_value),
compl_val);
ecma_object_t *obj_p = ecma_get_object_from_value (obj_expr_value);
prop_names_p = ecma_op_object_get_property_names (obj_p, false, true, true);
if (prop_names_p->unit_number != 0)
{
ecma_ref_object (obj_p);
*result_obj_p = ecma_make_object_value (obj_p);
}
else
{
ecma_dealloc_collection_header (prop_names_p);
prop_names_p = NULL;
}
ECMA_FINALIZE (obj_expr_value);
}
JERRY_ASSERT (ecma_is_value_empty (compl_val));
return prop_names_p;
} /* opfunc_for_in */
/**
* @}
* @}
*/

View file

@ -0,0 +1,120 @@
/* Copyright 2015-2016 Samsung Electronics Co., Ltd.
* Copyright 2015-2016 University of Szeged.
*
* 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.
*/
#ifndef OPCODES_H
#define OPCODES_H
#include "ecma-globals.h"
#include "vm-defines.h"
/** \addtogroup vm Virtual machine
* @{
*
* \addtogroup vm_opcodes Opcodes
* @{
*/
/**
* Number arithmetic operations.
*/
typedef enum
{
NUMBER_ARITHMETIC_SUBSTRACTION, /**< substraction */
NUMBER_ARITHMETIC_MULTIPLICATION, /**< multiplication */
NUMBER_ARITHMETIC_DIVISION, /**< division */
NUMBER_ARITHMETIC_REMAINDER, /**< remainder calculation */
} number_arithmetic_op;
/**
* Number bitwise logic operations.
*/
typedef enum
{
NUMBER_BITWISE_LOGIC_AND, /**< bitwise AND calculation */
NUMBER_BITWISE_LOGIC_OR, /**< bitwise OR calculation */
NUMBER_BITWISE_LOGIC_XOR, /**< bitwise XOR calculation */
NUMBER_BITWISE_SHIFT_LEFT, /**< bitwise LEFT SHIFT calculation */
NUMBER_BITWISE_SHIFT_RIGHT, /**< bitwise RIGHT_SHIFT calculation */
NUMBER_BITWISE_SHIFT_URIGHT, /**< bitwise UNSIGNED RIGHT SHIFT calculation */
NUMBER_BITWISE_NOT, /**< bitwise NOT calculation */
} number_bitwise_logic_op;
ecma_value_t
vm_var_decl (vm_frame_ctx_t *, ecma_string_t *);
ecma_value_t
opfunc_equal_value (ecma_value_t, ecma_value_t);
ecma_value_t
opfunc_not_equal_value (ecma_value_t, ecma_value_t);
ecma_value_t
do_number_arithmetic (number_arithmetic_op, ecma_value_t, ecma_value_t);
ecma_value_t
opfunc_unary_plus (ecma_value_t);
ecma_value_t
opfunc_unary_minus (ecma_value_t);
ecma_value_t
do_number_bitwise_logic (number_bitwise_logic_op, ecma_value_t, ecma_value_t);
ecma_value_t
opfunc_addition (ecma_value_t, ecma_value_t);
ecma_value_t
opfunc_less_than (ecma_value_t, ecma_value_t);
ecma_value_t
opfunc_greater_than (ecma_value_t, ecma_value_t);
ecma_value_t
opfunc_less_or_equal_than (ecma_value_t, ecma_value_t);
ecma_value_t
opfunc_greater_or_equal_than (ecma_value_t, ecma_value_t);
ecma_value_t
opfunc_in (ecma_value_t, ecma_value_t);
ecma_value_t
opfunc_instanceof (ecma_value_t, ecma_value_t);
ecma_value_t
opfunc_logical_not (ecma_value_t);
ecma_value_t
opfunc_typeof (ecma_value_t);
void
opfunc_set_accessor (bool, ecma_value_t, ecma_value_t, ecma_value_t);
ecma_value_t
vm_op_delete_prop (ecma_value_t, ecma_value_t, bool);
ecma_value_t
vm_op_delete_var (jmem_cpointer_t, ecma_object_t *);
ecma_collection_header_t *
opfunc_for_in (ecma_value_t, ecma_value_t *);
/**
* @}
* @}
*/
#endif /* !OPCODES_H */

View file

@ -0,0 +1,64 @@
/* Copyright 2015-2016 Samsung Electronics Co., Ltd.
* Copyright 2015-2016 University of Szeged.
*
* 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.
*/
#ifndef VM_DEFINES_H
#define VM_DEFINES_H
#include "byte-code.h"
#include "ecma-globals.h"
/** \addtogroup vm Virtual machine
* @{
*
* \addtogroup vm_executor Executor
* @{
*/
/**
* Helpers for updating uint16_t values.
*/
#define VM_PLUS_EQUAL_U16(base, value) (base) = (uint16_t) ((base) + (value))
#define VM_MINUS_EQUAL_U16(base, value) (base) = (uint16_t) ((base) - (value))
/**
* Instruction counter / position
*/
typedef const uint8_t *vm_instr_counter_t;
/**
* Context of interpreter, related to a JS stack frame
*/
typedef struct
{
const ecma_compiled_code_t *bytecode_header_p; /**< currently executed byte-code data */
uint8_t *byte_code_p; /**< current byte code pointer */
uint8_t *byte_code_start_p; /**< byte code start pointer */
ecma_value_t *registers_p; /**< register start pointer */
ecma_value_t *stack_top_p; /**< stack top pointer */
jmem_cpointer_t *literal_start_p; /**< literal list start pointer */
ecma_object_t *lex_env_p; /**< current lexical environment */
ecma_value_t this_binding; /**< this binding */
ecma_value_t call_block_result; /**< preserve block result during a call */
uint16_t context_depth; /**< current context depth */
uint8_t is_eval_code; /**< eval mode flag */
uint8_t call_operation; /**< perform a call or construct operation */
} vm_frame_ctx_t;
/**
* @}
* @}
*/
#endif /* !VM_DEFINES_H */

View file

@ -0,0 +1,256 @@
/* Copyright 2014-2016 Samsung Electronics Co., Ltd.
* Copyright 2015-2016 University of Szeged.
*
* 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 "ecma-alloc.h"
#include "ecma-gc.h"
#include "ecma-helpers.h"
#include "vm-defines.h"
#include "vm-stack.h"
/** \addtogroup vm Virtual machine
* @{
*
* \addtogroup stack VM stack
* @{
*/
/**
* Abort (finalize) the current stack context, and remove it.
*
* @return new stack top
*/
ecma_value_t *
vm_stack_context_abort (vm_frame_ctx_t *frame_ctx_p, /**< frame context */
ecma_value_t *vm_stack_top_p) /**< current stack top */
{
switch (VM_GET_CONTEXT_TYPE (vm_stack_top_p[-1]))
{
case VM_CONTEXT_FINALLY_THROW:
case VM_CONTEXT_FINALLY_RETURN:
{
ecma_free_value (vm_stack_top_p[-2]);
VM_MINUS_EQUAL_U16 (frame_ctx_p->context_depth, PARSER_TRY_CONTEXT_STACK_ALLOCATION);
vm_stack_top_p -= PARSER_TRY_CONTEXT_STACK_ALLOCATION;
break;
}
case VM_CONTEXT_FINALLY_JUMP:
case VM_CONTEXT_TRY:
{
VM_MINUS_EQUAL_U16 (frame_ctx_p->context_depth, PARSER_TRY_CONTEXT_STACK_ALLOCATION);
vm_stack_top_p -= PARSER_TRY_CONTEXT_STACK_ALLOCATION;
break;
}
case VM_CONTEXT_CATCH:
case VM_CONTEXT_WITH:
{
ecma_deref_object (frame_ctx_p->lex_env_p);
frame_ctx_p->lex_env_p = ecma_get_object_from_value (vm_stack_top_p[-2]);
JERRY_ASSERT (PARSER_TRY_CONTEXT_STACK_ALLOCATION == PARSER_WITH_CONTEXT_STACK_ALLOCATION);
VM_MINUS_EQUAL_U16 (frame_ctx_p->context_depth, PARSER_TRY_CONTEXT_STACK_ALLOCATION);
vm_stack_top_p -= PARSER_TRY_CONTEXT_STACK_ALLOCATION;
break;
}
case VM_CONTEXT_FOR_IN:
{
jmem_cpointer_t current = (jmem_cpointer_t) vm_stack_top_p[-2];
while (current != JMEM_CP_NULL)
{
ecma_collection_chunk_t *chunk_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_collection_chunk_t,
current);
lit_utf8_byte_t *data_ptr = chunk_p->data;
ecma_free_value (*(ecma_value_t *) data_ptr);
current = chunk_p->next_chunk_cp;
ecma_dealloc_collection_chunk (chunk_p);
}
ecma_free_value (vm_stack_top_p[-3]);
VM_MINUS_EQUAL_U16 (frame_ctx_p->context_depth, PARSER_FOR_IN_CONTEXT_STACK_ALLOCATION);
vm_stack_top_p -= PARSER_FOR_IN_CONTEXT_STACK_ALLOCATION;
break;
}
default:
{
JERRY_UNREACHABLE ();
break;
}
}
return vm_stack_top_p;
} /* vm_stack_context_abort */
/**
* Decode branch offset.
*
* @return branch offset
*/
static uint32_t
vm_decode_branch_offset (uint8_t *branch_offset_p, /**< start offset of byte code */
uint32_t length) /**< length of the branch */
{
uint32_t branch_offset = *branch_offset_p;
JERRY_ASSERT (length >= 1 && length <= 3);
switch (length)
{
case 3:
{
branch_offset <<= 8;
branch_offset |= *(branch_offset_p++);
/* FALLTHRU */
}
case 2:
{
branch_offset <<= 8;
branch_offset |= *(branch_offset_p++);
break;
}
}
return branch_offset;
} /* vm_decode_branch_offset */
/**
* Find a finally up to the end position.
*
* @return true if 'finally' found,
* false otherwise
*/
bool
vm_stack_find_finally (vm_frame_ctx_t *frame_ctx_p, /**< frame context */
ecma_value_t **vm_stack_top_ref_p, /**< current stack top */
vm_stack_context_type_t finally_type, /**< searching this finally */
uint32_t search_limit) /**< search up-to this byte code */
{
ecma_value_t *vm_stack_top_p = *vm_stack_top_ref_p;
JERRY_ASSERT (finally_type <= VM_CONTEXT_FINALLY_RETURN);
if (finally_type != VM_CONTEXT_FINALLY_JUMP)
{
search_limit = 0xffffffffu;
}
while (frame_ctx_p->context_depth > 0)
{
vm_stack_context_type_t context_type;
uint32_t context_end = VM_GET_CONTEXT_END (vm_stack_top_p[-1]);
if (search_limit < context_end)
{
*vm_stack_top_ref_p = vm_stack_top_p;
return false;
}
context_type = VM_GET_CONTEXT_TYPE (vm_stack_top_p[-1]);
if (context_type == VM_CONTEXT_TRY || context_type == VM_CONTEXT_CATCH)
{
uint8_t *byte_code_p;
uint32_t branch_offset_length;
uint32_t branch_offset;
if (search_limit == context_end)
{
*vm_stack_top_ref_p = vm_stack_top_p;
return false;
}
byte_code_p = frame_ctx_p->byte_code_start_p + VM_GET_CONTEXT_END (vm_stack_top_p[-1]);
if (context_type == VM_CONTEXT_TRY)
{
JERRY_ASSERT (byte_code_p[0] == CBC_EXT_OPCODE);
if (byte_code_p[1] >= CBC_EXT_CATCH
&& byte_code_p[1] <= CBC_EXT_CATCH_3)
{
branch_offset_length = CBC_BRANCH_OFFSET_LENGTH (byte_code_p[1]);
branch_offset = vm_decode_branch_offset (byte_code_p + 2,
branch_offset_length);
if (finally_type == VM_CONTEXT_FINALLY_THROW)
{
branch_offset += (uint32_t) (byte_code_p - frame_ctx_p->byte_code_start_p);
vm_stack_top_p[-1] = VM_CREATE_CONTEXT (VM_CONTEXT_CATCH, branch_offset);
byte_code_p += 2 + branch_offset_length;
frame_ctx_p->byte_code_p = byte_code_p;
*vm_stack_top_ref_p = vm_stack_top_p;
return true;
}
byte_code_p += branch_offset;
if (*byte_code_p == CBC_CONTEXT_END)
{
VM_MINUS_EQUAL_U16 (frame_ctx_p->context_depth, PARSER_TRY_CONTEXT_STACK_ALLOCATION);
vm_stack_top_p -= PARSER_TRY_CONTEXT_STACK_ALLOCATION;
continue;
}
}
}
else
{
ecma_deref_object (frame_ctx_p->lex_env_p);
frame_ctx_p->lex_env_p = ecma_get_object_from_value (vm_stack_top_p[-2]);
if (byte_code_p[0] == CBC_CONTEXT_END)
{
VM_MINUS_EQUAL_U16 (frame_ctx_p->context_depth, PARSER_TRY_CONTEXT_STACK_ALLOCATION);
vm_stack_top_p -= PARSER_TRY_CONTEXT_STACK_ALLOCATION;
continue;
}
}
JERRY_ASSERT (byte_code_p[0] == CBC_EXT_OPCODE);
JERRY_ASSERT (byte_code_p[1] >= CBC_EXT_FINALLY
&& byte_code_p[1] <= CBC_EXT_FINALLY_3);
branch_offset_length = CBC_BRANCH_OFFSET_LENGTH (byte_code_p[1]);
branch_offset = vm_decode_branch_offset (byte_code_p + 2,
branch_offset_length);
branch_offset += (uint32_t) (byte_code_p - frame_ctx_p->byte_code_start_p);
vm_stack_top_p[-1] = VM_CREATE_CONTEXT ((uint32_t) finally_type, branch_offset);
byte_code_p += 2 + branch_offset_length;
frame_ctx_p->byte_code_p = byte_code_p;
*vm_stack_top_ref_p = vm_stack_top_p;
return true;
}
vm_stack_top_p = vm_stack_context_abort (frame_ctx_p, vm_stack_top_p);
}
*vm_stack_top_ref_p = vm_stack_top_p;
return false;
} /* vm_stack_find_finally */
/**
* @}
* @}
*/

View file

@ -0,0 +1,79 @@
/* Copyright 2015-2016 Samsung Electronics Co., Ltd.
* Copyright 2015-2016 University of Szeged.
*
* 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.
*/
#ifndef VM_STACK_H
#define VM_STACK_H
#include "config.h"
#include "ecma-globals.h"
/** \addtogroup vm Virtual machine
* @{
*
* \addtogroup stack VM stack
* @{
*/
/**
* Number of ecma values inlined into stack frame
*/
#define VM_STACK_FRAME_INLINED_VALUES_NUMBER CONFIG_VM_STACK_FRAME_INLINED_VALUES_NUMBER
/**
* Header of a ECMA stack frame's chunk
*/
typedef struct
{
uint16_t prev_chunk_p; /**< previous chunk of same frame */
} vm_stack_chunk_header_t;
/**
* ECMA stack frame
*/
typedef struct vm_stack_frame_t
{
struct vm_stack_frame_t *prev_frame_p; /**< previous frame */
uint32_t regs_number; /**< number of register variables */
} vm_stack_frame_t;
#define VM_CREATE_CONTEXT(type, end_offset) ((ecma_value_t) ((type) | (end_offset) << 4))
#define VM_GET_CONTEXT_TYPE(value) ((vm_stack_context_type_t) ((value) & 0xf))
#define VM_GET_CONTEXT_END(value) ((value) >> 4)
/**
* Context types for the vm stack.
*/
typedef enum
{
VM_CONTEXT_FINALLY_JUMP, /**< finally context with a jump */
VM_CONTEXT_FINALLY_THROW, /**< finally context with a throw */
VM_CONTEXT_FINALLY_RETURN, /**< finally context with a return */
VM_CONTEXT_TRY, /**< try context */
VM_CONTEXT_CATCH, /**< catch context */
VM_CONTEXT_WITH, /**< with context */
VM_CONTEXT_FOR_IN, /**< for-in context */
} vm_stack_context_type_t;
extern ecma_value_t *vm_stack_context_abort (vm_frame_ctx_t *, ecma_value_t *);
extern bool vm_stack_find_finally (vm_frame_ctx_t *, ecma_value_t **,
vm_stack_context_type_t, uint32_t);
/**
* @}
* @}
*/
#endif /* !VM_STACK_H */

2755
third_party/jerryscript/jerry-core/vm/vm.c vendored Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,293 @@
/* Copyright 2014-2016 Samsung Electronics Co., Ltd.
* Copyright 2015-2016 University of Szeged.
*
* 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.
*/
#ifndef VM_H
#define VM_H
#include "ecma-globals.h"
#include "jrt.h"
#include "vm-defines.h"
/** \addtogroup vm Virtual machine
* @{
*
* \addtogroup vm_executor Executor
* @{
*/
/**
* Each CBC opcode is transformed to three vm opcodes:
*
* - first opcode is a "get arguments" opcode which specifies
* the type (register, literal, stack, etc.) and number
* (from 0 to 2) of input arguments
* - second opcode is a "group" opcode which specifies
* the actual operation (add, increment, call, etc.)
* - third opcode is a "put result" opcode which specifies
* the destination where the result is stored (register,
* stack, etc.)
*/
/**
* Branch argument is a backward branch
*/
#define VM_OC_BACKWARD_BRANCH 0x4000
/**
* Position of "get arguments" opcode.
*/
#define VM_OC_GET_ARGS_SHIFT 7
/**
* Mask of "get arguments" opcode.
*/
#define VM_OC_GET_ARGS_MASK 0x7
/**
* Generate the binary representation of a "get arguments" opcode.
*/
#define VM_OC_GET_ARGS_CREATE_INDEX(V) (((V) & VM_OC_GET_ARGS_MASK) << VM_OC_GET_ARGS_SHIFT)
/**
* Extract the "get arguments" opcode.
*/
#define VM_OC_GET_ARGS_INDEX(O) ((O) & (VM_OC_GET_ARGS_MASK << VM_OC_GET_ARGS_SHIFT))
/**
* Checks whether the result is stored somewhere.
*/
#define VM_OC_HAS_GET_ARGS(V) ((V) & (VM_OC_GET_ARGS_MASK << VM_OC_GET_ARGS_SHIFT))
/**
* Argument getters that are part of the opcodes.
*/
typedef enum
{
VM_OC_GET_NONE = VM_OC_GET_ARGS_CREATE_INDEX (0), /**< do nothing */
VM_OC_GET_BRANCH = VM_OC_GET_ARGS_CREATE_INDEX (1), /**< branch argument */
VM_OC_GET_STACK = VM_OC_GET_ARGS_CREATE_INDEX (2), /**< pop one element from the stack */
VM_OC_GET_STACK_STACK = VM_OC_GET_ARGS_CREATE_INDEX (3), /**< pop two elements from the stack */
VM_OC_GET_LITERAL = VM_OC_GET_ARGS_CREATE_INDEX (4), /**< resolve literal */
VM_OC_GET_LITERAL_LITERAL = VM_OC_GET_ARGS_CREATE_INDEX (5), /**< resolve two literals */
VM_OC_GET_STACK_LITERAL = VM_OC_GET_ARGS_CREATE_INDEX (6), /**< pop one element from the stack
* and resolve a literal */
VM_OC_GET_THIS_LITERAL = VM_OC_GET_ARGS_CREATE_INDEX (7), /**< get this and resolve a literal */
} vm_oc_get_types;
/**
* Mask of "group" opcode.
*/
#define VM_OC_GROUP_MASK 0x7f
/**
* Extract the "group" opcode.
*/
#define VM_OC_GROUP_GET_INDEX(O) ((O) & VM_OC_GROUP_MASK)
/**
* Opcodes.
*/
typedef enum
{
VM_OC_NONE, /**< do nothing */
VM_OC_POP, /**< pop from stack */
VM_OC_POP_BLOCK, /**< pop block */
VM_OC_PUSH, /**< push one element */
VM_OC_PUSH_TWO, /**< push two elements onto the stack */
VM_OC_PUSH_THREE, /**< push three elements onto the stack */
VM_OC_PUSH_UNDEFINED, /**< push undefined value */
VM_OC_PUSH_TRUE, /**< push true value */
VM_OC_PUSH_FALSE, /**< push false value */
VM_OC_PUSH_NULL, /**< push null value */
VM_OC_PUSH_THIS, /**< push this */
VM_OC_PUSH_NUMBER_0, /**< push number zero */
VM_OC_PUSH_NUMBER_POS_BYTE, /**< push number between 1 and 256 */
VM_OC_PUSH_NUMBER_NEG_BYTE, /**< push number between -1 and -256 */
VM_OC_PUSH_OBJECT, /**< push object */
VM_OC_SET_PROPERTY, /**< set property */
VM_OC_SET_GETTER, /**< set getter */
VM_OC_SET_SETTER, /**< set setter */
VM_OC_PUSH_UNDEFINED_BASE, /**< push undefined base */
VM_OC_PUSH_ARRAY, /**< push array */
VM_OC_PUSH_ELISON, /**< push elison */
VM_OC_APPEND_ARRAY, /**< append array */
VM_OC_IDENT_REFERENCE, /**< ident reference */
VM_OC_PROP_REFERENCE, /**< prop reference */
VM_OC_PROP_GET, /**< prop get */
/* These eight opcodes must be in this order. */
VM_OC_PROP_PRE_INCR, /**< prefix increment of a property */
VM_OC_PROP_PRE_DECR, /**< prop prefix decrement of a property */
VM_OC_PROP_POST_INCR, /**< prop postfix increment of a property */
VM_OC_PROP_POST_DECR, /**< prop postfix decrement of a property */
VM_OC_PRE_INCR, /**< prefix increment */
VM_OC_PRE_DECR, /**< prefix decrement */
VM_OC_POST_INCR, /**< postfix increment */
VM_OC_POST_DECR, /**< postfix decrement */
VM_OC_PROP_DELETE, /**< delete property */
VM_OC_DELETE, /**< delete */
VM_OC_ASSIGN, /**< assign */
VM_OC_ASSIGN_PROP, /**< assign property */
VM_OC_ASSIGN_PROP_THIS, /**< assign prop this */
VM_OC_RET, /**< return */
VM_OC_THROW, /**< throw */
VM_OC_THROW_REFERENCE_ERROR, /**< throw reference error */
VM_OC_EVAL, /**< eval */
VM_OC_CALL, /**< call */
VM_OC_NEW, /**< new */
VM_OC_JUMP, /**< jump */
VM_OC_BRANCH_IF_STRICT_EQUAL, /**< branch if stric equal */
/* These four opcodes must be in this order. */
VM_OC_BRANCH_IF_TRUE, /**< branch if true */
VM_OC_BRANCH_IF_FALSE, /**< branch if false */
VM_OC_BRANCH_IF_LOGICAL_TRUE, /**< branch if logical true */
VM_OC_BRANCH_IF_LOGICAL_FALSE, /**< branch if logical false */
VM_OC_PLUS, /**< unary plus */
VM_OC_MINUS, /**< unary minus */
VM_OC_NOT, /**< not */
VM_OC_BIT_NOT, /**< bitwise not */
VM_OC_VOID, /**< void */
VM_OC_TYPEOF_IDENT, /**< typeof identifier */
VM_OC_TYPEOF, /**< typeof */
VM_OC_ADD, /**< binary add */
VM_OC_SUB, /**< binary sub */
VM_OC_MUL, /**< mul */
VM_OC_DIV, /**< div */
VM_OC_MOD, /**< mod */
VM_OC_EQUAL, /**< equal */
VM_OC_NOT_EQUAL, /**< not equal */
VM_OC_STRICT_EQUAL, /**< strict equal */
VM_OC_STRICT_NOT_EQUAL, /**< strict not equal */
VM_OC_LESS, /**< less */
VM_OC_GREATER, /**< greater */
VM_OC_LESS_EQUAL, /**< less equal */
VM_OC_GREATER_EQUAL, /**< greater equal */
VM_OC_IN, /**< in */
VM_OC_INSTANCEOF, /**< instanceof */
VM_OC_BIT_OR, /**< bitwise or */
VM_OC_BIT_XOR, /**< bitwise xor */
VM_OC_BIT_AND, /**< bitwise and */
VM_OC_LEFT_SHIFT, /**< left shift */
VM_OC_RIGHT_SHIFT, /**< right shift */
VM_OC_UNS_RIGHT_SHIFT, /**< unsigned right shift */
VM_OC_WITH, /**< with */
VM_OC_FOR_IN_CREATE_CONTEXT, /**< for in create context */
VM_OC_FOR_IN_GET_NEXT, /**< get next */
VM_OC_FOR_IN_HAS_NEXT, /**< has next */
VM_OC_TRY, /**< try */
VM_OC_CATCH, /**< catch */
VM_OC_FINALLY, /**< finally */
VM_OC_CONTEXT_END, /**< context end */
VM_OC_JUMP_AND_EXIT_CONTEXT, /**< jump and exit context */
} vm_oc_types;
/**
* Decrement operator.
*/
#define VM_OC_DECREMENT_OPERATOR_FLAG 0x1
/**
* Postfix increment/decrement operator.
*/
#define VM_OC_POST_INCR_DECR_OPERATOR_FLAG 0x2
/**
* An named variable is updated by the increment/decrement operator.
*/
#define VM_OC_IDENT_INCR_DECR_OPERATOR_FLAG 0x4
/**
* Jump to target offset if input value is logical false.
*/
#define VM_OC_BRANCH_IF_FALSE_FLAG 0x1
/**
* Branch optimized for logical and/or opcodes.
*/
#define VM_OC_LOGICAL_BRANCH_FLAG 0x2
/**
* Position of "put result" opcode.
*/
#define VM_OC_PUT_RESULT_SHIFT 10
/**
* Mask of "put result" opcode.
*/
#define VM_OC_PUT_RESULT_MASK 0xf
/**
* Generate a "put result" opcode flag bit.
*/
#define VM_OC_PUT_RESULT_CREATE_FLAG(V) (((V) & VM_OC_PUT_RESULT_MASK) << VM_OC_PUT_RESULT_SHIFT)
/**
* Checks whether the result is stored somewhere.
*/
#define VM_OC_HAS_PUT_RESULT(V) ((V) & (VM_OC_PUT_RESULT_MASK << VM_OC_PUT_RESULT_SHIFT))
/**
* Specify where the result is stored
*/
typedef enum
{
VM_OC_PUT_IDENT = VM_OC_PUT_RESULT_CREATE_FLAG (0x1),
VM_OC_PUT_REFERENCE = VM_OC_PUT_RESULT_CREATE_FLAG (0x2),
VM_OC_PUT_STACK = VM_OC_PUT_RESULT_CREATE_FLAG (0x4),
VM_OC_PUT_BLOCK = VM_OC_PUT_RESULT_CREATE_FLAG (0x8),
} vm_oc_put_types;
/**
* Non-recursive vm_loop: the vm_loop can be suspended
* to execute a call /construct operation. These return
* types of the vm_loop tells whether a call operation
* is in progress or the vm_loop is finished.
*/
typedef enum
{
VM_NO_EXEC_OP, /**< do nothing */
VM_EXEC_CALL, /**< invoke a function */
VM_EXEC_CONSTRUCT, /**< construct a new object */
} vm_call_operation;
extern ecma_value_t vm_run_global (const ecma_compiled_code_t *);
extern ecma_value_t vm_run_eval (ecma_compiled_code_t *, bool);
extern ecma_value_t vm_run (const ecma_compiled_code_t *, ecma_value_t,
ecma_object_t *, bool, const ecma_value_t *,
ecma_length_t);
extern bool vm_is_strict_mode (void);
extern bool vm_is_direct_eval_form_call (void);
/**
* @}
* @}
*/
#endif /* !VM_H */