Renaming core -> jerry-core.

This commit is contained in:
Ruben Ayrapetyan
2015-02-17 19:00:34 +03:00
parent b6d018d019
commit 88353e93cf
183 changed files with 14 additions and 14 deletions
+200
View File
@@ -0,0 +1,200 @@
/* Copyright 2014-2015 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"
/**
* 'Jump down if true' opcode handler.
*
* Note:
* current opcode's position changes by adding specified offset
* if argument evaluates to true.
*/
ecma_completion_value_t
opfunc_is_true_jmp_down (opcode_t opdata, /**< operation data */
int_data_t *int_data) /**< interpreter context */
{
const idx_t cond_var_idx = opdata.data.is_true_jmp_down.value;
const opcode_counter_t offset = calc_opcode_counter_from_idx_idx (opdata.data.is_true_jmp_down.opcode_1,
opdata.data.is_true_jmp_down.opcode_2);
ecma_completion_value_t ret_value;
ECMA_TRY_CATCH (cond_value, get_variable_value (int_data, cond_var_idx, false), ret_value);
ecma_completion_value_t to_bool_completion = ecma_op_to_boolean (cond_value);
JERRY_ASSERT (ecma_is_completion_value_normal (to_bool_completion));
if (ecma_is_completion_value_normal_true (to_bool_completion))
{
JERRY_ASSERT (offset != 0 && ((uint32_t) int_data->pos + offset < MAX_OPCODES));
int_data->pos = (opcode_counter_t) (int_data->pos + offset);
}
else
{
int_data->pos++;
}
ret_value = ecma_make_empty_completion_value ();
ECMA_FINALIZE (cond_value);
return ret_value;
}
/* Likewise to opfunc_is_true_jmp_down, but jumps up. */
ecma_completion_value_t
opfunc_is_true_jmp_up (opcode_t opdata, /**< operation data */
int_data_t *int_data) /**< interpreter context */
{
const idx_t cond_var_idx = opdata.data.is_true_jmp_up.value;
const opcode_counter_t offset = calc_opcode_counter_from_idx_idx (opdata.data.is_true_jmp_up.opcode_1,
opdata.data.is_true_jmp_up.opcode_2);
ecma_completion_value_t ret_value;
ECMA_TRY_CATCH (cond_value, get_variable_value (int_data, cond_var_idx, false), ret_value);
ecma_completion_value_t to_bool_completion = ecma_op_to_boolean (cond_value);
JERRY_ASSERT (ecma_is_completion_value_normal (to_bool_completion));
if (ecma_is_completion_value_normal_true (to_bool_completion))
{
JERRY_ASSERT (offset != 0 && (uint32_t) int_data->pos >= offset);
int_data->pos = (opcode_counter_t) (int_data->pos - offset);
}
else
{
int_data->pos++;
}
ret_value = ecma_make_empty_completion_value ();
ECMA_FINALIZE (cond_value);
return ret_value;
}
/**
* 'Jump down if false' opcode handler.
*
* Note:
* current opcode's position changes by adding specified offset
* if argument evaluates to false.
*/
ecma_completion_value_t
opfunc_is_false_jmp_down (opcode_t opdata, /**< operation data */
int_data_t *int_data) /**< interpreter context */
{
const idx_t cond_var_idx = opdata.data.is_false_jmp_down.value;
const opcode_counter_t offset = calc_opcode_counter_from_idx_idx (opdata.data.is_false_jmp_down.opcode_1,
opdata.data.is_false_jmp_down.opcode_2);
ecma_completion_value_t ret_value;
ECMA_TRY_CATCH (cond_value, get_variable_value (int_data, cond_var_idx, false), ret_value);
ecma_completion_value_t to_bool_completion = ecma_op_to_boolean (cond_value);
JERRY_ASSERT (ecma_is_completion_value_normal (to_bool_completion));
if (!ecma_is_completion_value_normal_true (to_bool_completion))
{
JERRY_ASSERT (offset != 0 && ((uint32_t) int_data->pos + offset < MAX_OPCODES));
int_data->pos = (opcode_counter_t) (int_data->pos + offset);
}
else
{
int_data->pos++;
}
ret_value = ecma_make_empty_completion_value ();
ECMA_FINALIZE (cond_value);
return ret_value;
}
/* Likewise to opfunc_is_false_jmp_down, but jumps up. */
ecma_completion_value_t
opfunc_is_false_jmp_up (opcode_t opdata, /**< operation data */
int_data_t *int_data) /**< interpreter context */
{
const idx_t cond_var_idx = opdata.data.is_false_jmp_up.value;
const opcode_counter_t offset = calc_opcode_counter_from_idx_idx (opdata.data.is_false_jmp_up.opcode_1,
opdata.data.is_false_jmp_up.opcode_2);
ecma_completion_value_t ret_value;
ECMA_TRY_CATCH (cond_value, get_variable_value (int_data, cond_var_idx, false), ret_value);
ecma_completion_value_t to_bool_completion = ecma_op_to_boolean (cond_value);
JERRY_ASSERT (ecma_is_completion_value_normal (to_bool_completion));
if (!ecma_is_completion_value_normal_true (to_bool_completion))
{
JERRY_ASSERT (offset != 0 && (uint32_t) int_data->pos >= offset);
int_data->pos = (opcode_counter_t) (int_data->pos - offset);
}
else
{
int_data->pos++;
}
ret_value = ecma_make_empty_completion_value ();
ECMA_FINALIZE (cond_value);
return ret_value;
}
/**
* 'Jump down' opcode handler.
*
* Note:
* the opcode changes adds specified value to current opcode position
*/
ecma_completion_value_t
opfunc_jmp_down (opcode_t opdata, /**< operation data */
int_data_t *int_data) /**< interpreter context */
{
const opcode_counter_t offset = calc_opcode_counter_from_idx_idx (opdata.data.jmp_down.opcode_1,
opdata.data.jmp_down.opcode_2);
JERRY_ASSERT (offset != 0 && ((uint32_t) int_data->pos + offset < MAX_OPCODES));
int_data->pos = (opcode_counter_t) (int_data->pos + offset);
return ecma_make_empty_completion_value ();
}
/**
* 'Jump up' opcode handler.
*
* Note:
* the opcode changes substracts specified value from current opcode position
*/
ecma_completion_value_t
opfunc_jmp_up (opcode_t opdata, /**< operation data */
int_data_t *int_data) /**< interpreter context */
{
const opcode_counter_t offset = calc_opcode_counter_from_idx_idx (opdata.data.jmp_up.opcode_1,
opdata.data.jmp_up.opcode_2);
JERRY_ASSERT (offset != 0 && (uint32_t) int_data->pos >= offset);
int_data->pos = (opcode_counter_t) (int_data->pos - offset);
return ecma_make_empty_completion_value ();
}
+375
View File
@@ -0,0 +1,375 @@
/* Copyright 2014-2015 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"
#include "ecma-number-arithmetic.h"
#include "jrt-libc-includes.h"
/**
* Number arithmetic operations.
*/
typedef enum
{
number_arithmetic_addition, /**< addition */
number_arithmetic_substraction, /**< substraction */
number_arithmetic_multiplication, /**< multiplication */
number_arithmetic_division, /**< division */
number_arithmetic_remainder, /**< remainder calculation */
} number_arithmetic_op;
/**
* Perform ECMA number arithmetic operation.
*
* The algorithm of the operation is following:
* leftNum = ToNumber (leftValue);
* rightNum = ToNumber (rightValue);
* result = leftNum ArithmeticOp rightNum;
*
* @return completion value
* Returned value must be freed with ecma_free_completion_value
*/
static ecma_completion_value_t
do_number_arithmetic (int_data_t *int_data, /**< interpreter context */
idx_t dst_var_idx, /**< destination variable identifier */
number_arithmetic_op op, /**< number arithmetic operation */
const ecma_value_t& left_value, /**< left value */
const ecma_value_t& right_value) /** right value */
{
ecma_completion_value_t ret_value = ecma_make_empty_completion_value ();
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 *res_p = int_data->tmp_num_p;
switch (op)
{
case number_arithmetic_addition:
{
*res_p = ecma_number_add (num_left, num_right);
break;
}
case number_arithmetic_substraction:
{
*res_p = ecma_number_substract (num_left, num_right);
break;
}
case number_arithmetic_multiplication:
{
*res_p = ecma_number_multiply (num_left, num_right);
break;
}
case number_arithmetic_division:
{
*res_p = ecma_number_divide (num_left, num_right);
break;
}
case number_arithmetic_remainder:
{
*res_p = ecma_op_number_remainder (num_left, num_right);
break;
}
}
ret_value = set_variable_value (int_data, int_data->pos,
dst_var_idx,
ecma_make_number_value (res_p));
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 completion value
* Returned value must be freed with ecma_free_completion_value
*/
ecma_completion_value_t
opfunc_addition (opcode_t opdata, /**< operation data */
int_data_t *int_data) /**< interpreter context */
{
const idx_t dst_var_idx = opdata.data.addition.dst;
const idx_t left_var_idx = opdata.data.addition.var_left;
const idx_t right_var_idx = opdata.data.addition.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 (prim_left_value,
ecma_op_to_primitive (left_value,
ECMA_PREFERRED_TYPE_NO),
ret_value);
ECMA_TRY_CATCH (prim_right_value,
ecma_op_to_primitive (right_value,
ECMA_PREFERRED_TYPE_NO),
ret_value);
if (ecma_is_value_string (prim_left_value)
|| ecma_is_value_string (prim_right_value))
{
ECMA_TRY_CATCH (str_left_value, ecma_op_to_string (prim_left_value), ret_value);
ECMA_TRY_CATCH (str_right_value, ecma_op_to_string (prim_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 = set_variable_value (int_data, int_data->pos, dst_var_idx, ecma_make_string_value (concat_str_p));
ecma_deref_ecma_string (concat_str_p);
ECMA_FINALIZE (str_right_value);
ECMA_FINALIZE (str_left_value);
}
else
{
ret_value = do_number_arithmetic (int_data,
dst_var_idx,
number_arithmetic_addition,
prim_left_value,
prim_right_value);
}
ECMA_FINALIZE (prim_right_value);
ECMA_FINALIZE (prim_left_value);
ECMA_FINALIZE (right_value);
ECMA_FINALIZE (left_value);
int_data->pos++;
return ret_value;
} /* opfunc_addition */
/**
* 'Substraction' opcode handler.
*
* See also: ECMA-262 v5, 11.6.2
*
* @return completion value
* Returned value must be freed with ecma_free_completion_value
*/
ecma_completion_value_t
opfunc_substraction (opcode_t opdata, /**< operation data */
int_data_t *int_data) /**< interpreter context */
{
const idx_t dst_var_idx = opdata.data.substraction.dst;
const idx_t left_var_idx = opdata.data.substraction.var_left;
const idx_t right_var_idx = opdata.data.substraction.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);
ret_value = do_number_arithmetic (int_data,
dst_var_idx,
number_arithmetic_substraction,
left_value,
right_value);
ECMA_FINALIZE (right_value);
ECMA_FINALIZE (left_value);
int_data->pos++;
return ret_value;
} /* opfunc_substraction */
/**
* 'Multiplication' opcode handler.
*
* See also: ECMA-262 v5, 11.5, 11.5.1
*
* @return completion value
* Returned value must be freed with ecma_free_completion_value
*/
ecma_completion_value_t
opfunc_multiplication (opcode_t opdata, /**< operation data */
int_data_t *int_data) /**< interpreter context */
{
const idx_t dst_var_idx = opdata.data.multiplication.dst;
const idx_t left_var_idx = opdata.data.multiplication.var_left;
const idx_t right_var_idx = opdata.data.multiplication.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);
ret_value = do_number_arithmetic (int_data,
dst_var_idx,
number_arithmetic_multiplication,
left_value,
right_value);
ECMA_FINALIZE (right_value);
ECMA_FINALIZE (left_value);
int_data->pos++;
return ret_value;
} /* opfunc_multiplication */
/**
* 'Division' opcode handler.
*
* See also: ECMA-262 v5, 11.5, 11.5.2
*
* @return completion value
* Returned value must be freed with ecma_free_completion_value
*/
ecma_completion_value_t
opfunc_division (opcode_t opdata, /**< operation data */
int_data_t *int_data) /**< interpreter context */
{
const idx_t dst_var_idx = opdata.data.division.dst;
const idx_t left_var_idx = opdata.data.division.var_left;
const idx_t right_var_idx = opdata.data.division.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);
ret_value = do_number_arithmetic (int_data,
dst_var_idx,
number_arithmetic_division,
left_value,
right_value);
ECMA_FINALIZE (right_value);
ECMA_FINALIZE (left_value);
int_data->pos++;
return ret_value;
} /* opfunc_division */
/**
* 'Remainder calculation' opcode handler.
*
* See also: ECMA-262 v5, 11.5, 11.5.3
*
* @return completion value
* Returned value must be freed with ecma_free_completion_value
*/
ecma_completion_value_t
opfunc_remainder (opcode_t opdata, /**< operation data */
int_data_t *int_data) /**< interpreter context */
{
const idx_t dst_var_idx = opdata.data.remainder.dst;
const idx_t left_var_idx = opdata.data.remainder.var_left;
const idx_t right_var_idx = opdata.data.remainder.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);
ret_value = do_number_arithmetic (int_data,
dst_var_idx,
number_arithmetic_remainder,
left_value,
right_value);
ECMA_FINALIZE (right_value);
ECMA_FINALIZE (left_value);
int_data->pos++;
return ret_value;
} /* opfunc_remainder */
/**
* 'Unary "+"' opcode handler.
*
* See also: ECMA-262 v5, 11.4, 11.4.6
*
* @return completion value
* Returned value must be freed with ecma_free_completion_value
*/
ecma_completion_value_t
opfunc_unary_plus (opcode_t opdata, /**< operation data */
int_data_t *int_data) /**< interpreter context */
{
const idx_t dst_var_idx = opdata.data.remainder.dst;
const idx_t var_idx = opdata.data.remainder.var_left;
ecma_completion_value_t ret_value = ecma_make_empty_completion_value ();
ECMA_TRY_CATCH (var_value, get_variable_value (int_data, var_idx, false), ret_value);
ECMA_OP_TO_NUMBER_TRY_CATCH (num_var_value,
var_value,
ret_value);
ecma_number_t *tmp_p = int_data->tmp_num_p;
*tmp_p = num_var_value;
ret_value = set_variable_value (int_data, int_data->pos,
dst_var_idx,
ecma_make_number_value (tmp_p));
ECMA_OP_TO_NUMBER_FINALIZE (num_var_value);
ECMA_FINALIZE (var_value);
int_data->pos++;
return ret_value;
} /* opfunc_unary_plus */
/**
* 'Unary "-"' opcode handler.
*
* See also: ECMA-262 v5, 11.4, 11.4.7
*
* @return completion value
* Returned value must be freed with ecma_free_completion_value
*/
ecma_completion_value_t
opfunc_unary_minus (opcode_t opdata, /**< operation data */
int_data_t *int_data) /**< interpreter context */
{
const idx_t dst_var_idx = opdata.data.remainder.dst;
const idx_t var_idx = opdata.data.remainder.var_left;
ecma_completion_value_t ret_value = ecma_make_empty_completion_value ();
ECMA_TRY_CATCH (var_value, get_variable_value (int_data, var_idx, false), ret_value);
ECMA_OP_TO_NUMBER_TRY_CATCH (num_var_value,
var_value,
ret_value);
ecma_number_t *tmp_p = int_data->tmp_num_p;
*tmp_p = ecma_number_negate (num_var_value);
ret_value = set_variable_value (int_data, int_data->pos,
dst_var_idx,
ecma_make_number_value (tmp_p));
ECMA_OP_TO_NUMBER_FINALIZE (num_var_value);
ECMA_FINALIZE (var_value);
int_data->pos++;
return ret_value;
} /* opfunc_unary_minus */
+353
View File
@@ -0,0 +1,353 @@
/* Copyright 2014-2015 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"
/**
* 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;
/**
* Perform ECMA number logic operation.
*
* The algorithm of the operation is following:
* leftNum = ToNumber (leftValue);
* rightNum = ToNumber (rightValue);
* result = leftNum BitwiseLogicOp rightNum;
*
* @return completion value
* Returned value must be freed with ecma_free_completion_value
*/
static ecma_completion_value_t
do_number_bitwise_logic (int_data_t *int_data, /**< interpreter context */
idx_t dst_var_idx, /**< destination variable identifier */
number_bitwise_logic_op op, /**< number bitwise logic operation */
const ecma_value_t& left_value, /**< left value */
const ecma_value_t& right_value) /** right value */
{
ecma_completion_value_t ret_value = ecma_make_empty_completion_value ();
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* res_p = int_data->tmp_num_p;
int32_t left_int32 = ecma_number_to_int32 (num_left);
// int32_t right_int32 = ecma_number_to_int32 (num_right);
uint32_t left_uint32 = ecma_number_to_uint32 (num_left);
uint32_t right_uint32 = ecma_number_to_uint32 (num_right);
switch (op)
{
case number_bitwise_logic_and:
{
*res_p = ecma_int32_to_number ((int32_t) (left_uint32 & right_uint32));
break;
}
case number_bitwise_logic_or:
{
*res_p = ecma_int32_to_number ((int32_t) (left_uint32 | right_uint32));
break;
}
case number_bitwise_logic_xor:
{
*res_p = ecma_int32_to_number ((int32_t) (left_uint32 ^ right_uint32));
break;
}
case number_bitwise_shift_left:
{
*res_p = ecma_int32_to_number (left_int32 << (right_uint32 & 0x1F));
break;
}
case number_bitwise_shift_right:
{
*res_p = ecma_int32_to_number (left_int32 >> (right_uint32 & 0x1F));
break;
}
case number_bitwise_shift_uright:
{
*res_p = ecma_uint32_to_number (left_uint32 >> (right_uint32 & 0x1F));
break;
}
case number_bitwise_not:
{
*res_p = ecma_int32_to_number ((int32_t) ~right_uint32);
break;
}
}
ret_value = set_variable_value (int_data, int_data->pos,
dst_var_idx,
ecma_make_number_value (res_p));
ECMA_OP_TO_NUMBER_FINALIZE (num_right);
ECMA_OP_TO_NUMBER_FINALIZE (num_left);
return ret_value;
} /* do_number_bitwise_logic */
/**
* 'Bitwise AND' opcode handler.
*
* See also: ECMA-262 v5, 11.10
*
* @return completion value
* Returned value must be freed with ecma_free_completion_value
*/
ecma_completion_value_t
opfunc_b_and (opcode_t opdata, /**< operation data */
int_data_t *int_data) /**< interpreter context */
{
const idx_t dst_var_idx = opdata.data.b_and.dst;
const idx_t left_var_idx = opdata.data.b_and.var_left;
const idx_t right_var_idx = opdata.data.b_and.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);
ret_value = do_number_bitwise_logic (int_data,
dst_var_idx,
number_bitwise_logic_and,
left_value,
right_value);
ECMA_FINALIZE (right_value);
ECMA_FINALIZE (left_value);
int_data->pos++;
return ret_value;
} /* opfunc_b_and */
/**
* 'Bitwise OR' opcode handler.
*
* See also: ECMA-262 v5, 11.10
*
* @return completion value
* Returned value must be freed with ecma_free_completion_value
*/
ecma_completion_value_t
opfunc_b_or (opcode_t opdata, /**< operation data */
int_data_t *int_data) /**< interpreter context */
{
const idx_t dst_var_idx = opdata.data.b_or.dst;
const idx_t left_var_idx = opdata.data.b_or.var_left;
const idx_t right_var_idx = opdata.data.b_or.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);
ret_value = do_number_bitwise_logic (int_data,
dst_var_idx,
number_bitwise_logic_or,
left_value,
right_value);
ECMA_FINALIZE (right_value);
ECMA_FINALIZE (left_value);
int_data->pos++;
return ret_value;
} /* opfunc_b_or */
/**
* 'Bitwise XOR' opcode handler.
*
* See also: ECMA-262 v5, 11.10
*
* @return completion value
* Returned value must be freed with ecma_free_completion_value
*/
ecma_completion_value_t
opfunc_b_xor (opcode_t opdata, /**< operation data */
int_data_t *int_data) /**< interpreter context */
{
const idx_t dst_var_idx = opdata.data.b_xor.dst;
const idx_t left_var_idx = opdata.data.b_xor.var_left;
const idx_t right_var_idx = opdata.data.b_xor.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);
ret_value = do_number_bitwise_logic (int_data,
dst_var_idx,
number_bitwise_logic_xor,
left_value,
right_value);
ECMA_FINALIZE (right_value);
ECMA_FINALIZE (left_value);
int_data->pos++;
return ret_value;
} /* opfunc_b_xor */
/**
* 'Left Shift Operator' opcode handler.
*
* See also: ECMA-262 v5, 11.7.1
*
* @return completion value
* Returned value must be freed with ecma_free_completion_value
*/
ecma_completion_value_t
opfunc_b_shift_left (opcode_t opdata, /**< operation data */
int_data_t *int_data) /**< interpreter context */
{
const idx_t dst_var_idx = opdata.data.b_shift_left.dst;
const idx_t left_var_idx = opdata.data.b_shift_left.var_left;
const idx_t right_var_idx = opdata.data.b_shift_left.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);
ret_value = do_number_bitwise_logic (int_data,
dst_var_idx,
number_bitwise_shift_left,
left_value,
right_value);
ECMA_FINALIZE (right_value);
ECMA_FINALIZE (left_value);
int_data->pos++;
return ret_value;
} /* opfunc_b_shift_left */
/**
* 'Right Shift Operator' opcode handler.
*
* See also: ECMA-262 v5, 11.7.2
*
* @return completion value
* Returned value must be freed with ecma_free_completion_value
*/
ecma_completion_value_t
opfunc_b_shift_right (opcode_t opdata, /**< operation data */
int_data_t *int_data) /**< interpreter context */
{
const idx_t dst_var_idx = opdata.data.b_shift_right.dst;
const idx_t left_var_idx = opdata.data.b_shift_right.var_left;
const idx_t right_var_idx = opdata.data.b_shift_right.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);
ret_value = do_number_bitwise_logic (int_data,
dst_var_idx,
number_bitwise_shift_right,
left_value,
right_value);
ECMA_FINALIZE (right_value);
ECMA_FINALIZE (left_value);
int_data->pos++;
return ret_value;
} /* opfunc_b_shift_right */
/**
* 'Unsigned Right Shift Operator' opcode handler.
*
* See also: ECMA-262 v5, 11.7.3
*
* @return completion value
* Returned value must be freed with ecma_free_completion_value
*/
ecma_completion_value_t
opfunc_b_shift_uright (opcode_t opdata, /**< operation data */
int_data_t *int_data) /**< interpreter context */
{
const idx_t dst_var_idx = opdata.data.b_shift_uright.dst;
const idx_t left_var_idx = opdata.data.b_shift_uright.var_left;
const idx_t right_var_idx = opdata.data.b_shift_uright.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);
ret_value = do_number_bitwise_logic (int_data,
dst_var_idx,
number_bitwise_shift_uright,
left_value,
right_value);
ECMA_FINALIZE (right_value);
ECMA_FINALIZE (left_value);
int_data->pos++;
return ret_value;
} /* opfunc_b_shift_uright */
/**
* 'Bitwise NOT Operator' opcode handler.
*
* See also: ECMA-262 v5, 10.4
*
* @return completion value
* Returned value must be freed with ecma_free_completion_value
*/
ecma_completion_value_t
opfunc_b_not (opcode_t opdata, /**< operation data */
int_data_t *int_data) /**< interpreter context */
{
const idx_t dst_var_idx = opdata.data.b_not.dst;
const idx_t right_var_idx = opdata.data.b_not.var_right;
ecma_completion_value_t ret_value;
ECMA_TRY_CATCH (right_value, get_variable_value (int_data, right_var_idx, false), ret_value);
ret_value = do_number_bitwise_logic (int_data,
dst_var_idx,
number_bitwise_not,
right_value,
right_value);
ECMA_FINALIZE (right_value);
int_data->pos++;
return ret_value;
} /* opfunc_b_not */
+168
View File
@@ -0,0 +1,168 @@
/* Copyright 2014-2015 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"
/**
* 'Equals' opcode handler.
*
* See also: ECMA-262 v5, 11.9.1
*
* @return completion value
* Returned value must be freed with ecma_free_completion_value
*/
ecma_completion_value_t
opfunc_equal_value (opcode_t opdata, /**< operation data */
int_data_t *int_data) /**< interpreter context */
{
const idx_t dst_var_idx = opdata.data.equal_value.dst;
const idx_t left_var_idx = opdata.data.equal_value.var_left;
const idx_t right_var_idx = opdata.data.equal_value.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_equality_compare (left_value,
right_value),
ret_value);
JERRY_ASSERT (ecma_is_value_boolean (compare_result));
ret_value = set_variable_value (int_data, int_data->pos, dst_var_idx,
compare_result);
ECMA_FINALIZE (compare_result);
ECMA_FINALIZE (right_value);
ECMA_FINALIZE (left_value);
int_data->pos++;
return ret_value;
} /* opfunc_equal_value */
/**
* 'Does-not-equals' opcode handler.
*
* See also: ECMA-262 v5, 11.9.2
*
* @return completion value
* Returned value must be freed with ecma_free_completion_value
*/
ecma_completion_value_t
opfunc_not_equal_value (opcode_t opdata, /**< operation data */
int_data_t *int_data) /**< interpreter context */
{
const idx_t dst_var_idx = opdata.data.not_equal_value.dst;
const idx_t left_var_idx = opdata.data.not_equal_value.var_left;
const idx_t right_var_idx = opdata.data.not_equal_value.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_equality_compare (left_value, right_value),
ret_value);
JERRY_ASSERT (ecma_is_value_boolean (compare_result));
bool is_equal = ecma_is_value_true (compare_result);
ret_value = set_variable_value (int_data, int_data->pos, dst_var_idx,
ecma_make_simple_value (is_equal ? ECMA_SIMPLE_VALUE_FALSE
: ECMA_SIMPLE_VALUE_TRUE));
ECMA_FINALIZE (compare_result);
ECMA_FINALIZE (right_value);
ECMA_FINALIZE (left_value);
int_data->pos++;
return ret_value;
} /* opfunc_not_equal_value */
/**
* 'Strict Equals' opcode handler.
*
* See also: ECMA-262 v5, 11.9.4
*
* @return completion value
* Returned value must be freed with ecma_free_completion_value
*/
ecma_completion_value_t
opfunc_equal_value_type (opcode_t opdata, /**< operation data */
int_data_t *int_data) /**< interpreter context */
{
const idx_t dst_var_idx = opdata.data.equal_value_type.dst;
const idx_t left_var_idx = opdata.data.equal_value_type.var_left;
const idx_t right_var_idx = opdata.data.equal_value_type.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);
bool is_equal = ecma_op_strict_equality_compare (left_value, right_value);
ret_value = set_variable_value (int_data, int_data->pos, dst_var_idx,
ecma_make_simple_value (is_equal ? ECMA_SIMPLE_VALUE_TRUE
: ECMA_SIMPLE_VALUE_FALSE));
ECMA_FINALIZE (right_value);
ECMA_FINALIZE (left_value);
int_data->pos++;
return ret_value;
} /* opfunc_equal_value_type */
/**
* 'Strict Does-not-equals' opcode handler.
*
* See also: ECMA-262 v5, 11.9.5
*
* @return completion value
* Returned value must be freed with ecma_free_completion_value
*/
ecma_completion_value_t
opfunc_not_equal_value_type (opcode_t opdata, /**< operation data */
int_data_t *int_data) /**< interpreter context */
{
const idx_t dst_var_idx = opdata.data.not_equal_value_type.dst;
const idx_t left_var_idx = opdata.data.not_equal_value_type.var_left;
const idx_t right_var_idx = opdata.data.not_equal_value_type.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);
bool is_equal = ecma_op_strict_equality_compare (left_value, right_value);
ret_value = set_variable_value (int_data, int_data->pos, dst_var_idx,
ecma_make_simple_value (is_equal ? ECMA_SIMPLE_VALUE_FALSE
: ECMA_SIMPLE_VALUE_TRUE));
ECMA_FINALIZE (right_value);
ECMA_FINALIZE (left_value);
int_data->pos++;
return ret_value;
} /* opfunc_not_equal_value_type */
+326
View File
@@ -0,0 +1,326 @@
/* Copyright 2014-2015 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 (left_value, right_value, true),
ret_value);
ecma_simple_value_t res;
if (ecma_is_value_undefined (compare_result))
{
res = ECMA_SIMPLE_VALUE_FALSE;
}
else
{
JERRY_ASSERT (ecma_is_value_boolean (compare_result));
res = (ecma_is_value_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 (right_value, left_value, false),
ret_value);
ecma_simple_value_t res;
if (ecma_is_value_undefined (compare_result))
{
res = ECMA_SIMPLE_VALUE_FALSE;
}
else
{
JERRY_ASSERT (ecma_is_value_boolean (compare_result));
res = (ecma_is_value_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 (right_value, left_value, false),
ret_value);
ecma_simple_value_t res;
if (ecma_is_value_undefined (compare_result))
{
res = ECMA_SIMPLE_VALUE_FALSE;
}
else
{
JERRY_ASSERT (ecma_is_value_boolean (compare_result));
if (ecma_is_value_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 (left_value, right_value, true),
ret_value);
ecma_simple_value_t res;
if (ecma_is_value_undefined (compare_result))
{
res = ECMA_SIMPLE_VALUE_FALSE;
}
else
{
JERRY_ASSERT (ecma_is_value_boolean (compare_result));
if (ecma_is_value_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 __attr_unused___, /**< operation data */
int_data_t *int_data __attr_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 (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_value (right_value);
ECMA_TRY_CATCH (is_instance_of,
ecma_op_object_has_instance (right_value_obj_p, left_value),
ret_value);
ret_value = set_variable_value (int_data, int_data->pos, dst_idx, 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 __attr_unused___, /**< operation data */
int_data_t *int_data __attr_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 (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 (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_value (str_left_value);
ecma_object_t *right_value_obj_p = ecma_get_object_from_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 */
+46
View File
@@ -0,0 +1,46 @@
/* Copyright 2014-2015 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.
*/
#ifndef OPCODES_ECMA_SUPPORT_H
#define OPCODES_ECMA_SUPPORT_H
#include "ecma-alloc.h"
#include "ecma-array-object.h"
#include "ecma-comparison.h"
#include "ecma-conversion.h"
#include "ecma-exceptions.h"
#include "ecma-function-object.h"
#include "ecma-gc.h"
#include "ecma-helpers.h"
#include "ecma-lex-env.h"
#include "ecma-number-arithmetic.h"
#include "ecma-objects.h"
#include "ecma-objects-general.h"
#include "ecma-operations.h"
#include "ecma-reference.h"
#include "ecma-try-catch-macro.h"
#include "deserializer.h"
bool is_reg_variable (int_data_t *int_data, idx_t var_idx);
ecma_completion_value_t get_variable_value (int_data_t *, idx_t, bool);
ecma_completion_value_t set_variable_value (int_data_t *, opcode_counter_t, idx_t, const ecma_value_t&);
ecma_completion_value_t fill_varg_list (int_data_t *int_data,
ecma_length_t args_number,
ecma_value_t args_values[],
ecma_length_t *out_arg_number_p);
void fill_params_list (int_data_t *int_data,
ecma_length_t params_number,
ecma_string_t* params_names[]);
#endif /* OPCODES_ECMA_SUPPORT_H */
@@ -0,0 +1,133 @@
/* Copyright 2014-2015 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 "jrt.h"
#include "vm.h"
#include "opcodes.h"
#include "opcodes-ecma-support.h"
/**
* 'Try' opcode handler.
*
* See also: ECMA-262 v5, 12.14
*
* @return completion value
* Returned value must be freed with ecma_free_completion_value
*/
ecma_completion_value_t
opfunc_try_block (opcode_t opdata, /**< operation data */
int_data_t *int_data) /**< interpreter context */
{
const idx_t block_end_oc_idx_1 = opdata.data.try_block.oc_idx_1;
const idx_t block_end_oc_idx_2 = opdata.data.try_block.oc_idx_2;
const opcode_counter_t try_end_oc = (opcode_counter_t) (
calc_opcode_counter_from_idx_idx (block_end_oc_idx_1, block_end_oc_idx_2) + int_data->pos);
int_data->pos++;
ecma_completion_value_t try_completion = run_int_loop (int_data);
JERRY_ASSERT ((!ecma_is_completion_value_empty (try_completion) && int_data->pos <= try_end_oc)
|| (ecma_is_completion_value_empty (try_completion) && int_data->pos == try_end_oc));
int_data->pos = try_end_oc;
opcode_t next_opcode = read_opcode (int_data->pos);
JERRY_ASSERT (next_opcode.op_idx == __op__idx_meta);
if (ecma_is_completion_value_exit (try_completion))
{
return try_completion;
}
if (next_opcode.data.meta.type == OPCODE_META_TYPE_CATCH)
{
const opcode_counter_t catch_end_oc = (opcode_counter_t) (
read_meta_opcode_counter (OPCODE_META_TYPE_CATCH, int_data) + int_data->pos);
int_data->pos++;
if (ecma_is_completion_value_throw (try_completion))
{
next_opcode = read_opcode (int_data->pos);
JERRY_ASSERT (next_opcode.op_idx == __op__idx_meta);
JERRY_ASSERT (next_opcode.data.meta.type == OPCODE_META_TYPE_CATCH_EXCEPTION_IDENTIFIER);
const literal_index_t catch_exc_val_var_name_lit_idx = deserialize_lit_id_by_uid (next_opcode.data.meta.data_1,
int_data->pos);
int_data->pos++;
ecma_string_t *catch_exc_var_name_str_p = ecma_new_ecma_string_from_lit_index (catch_exc_val_var_name_lit_idx);
ecma_object_t *old_env_p = int_data->lex_env_p;
ecma_object_t *catch_env_p = ecma_create_decl_lex_env (old_env_p);
ecma_completion_value_t completion = ecma_op_create_mutable_binding (catch_env_p,
catch_exc_var_name_str_p,
false);
JERRY_ASSERT (ecma_is_completion_value_empty (completion));
completion = ecma_op_set_mutable_binding (catch_env_p,
catch_exc_var_name_str_p,
ecma_get_completion_value_value (try_completion),
false);
JERRY_ASSERT (ecma_is_completion_value_empty (completion));
ecma_deref_ecma_string (catch_exc_var_name_str_p);
int_data->lex_env_p = catch_env_p;
ecma_free_completion_value (try_completion);
try_completion = run_int_loop (int_data);
int_data->lex_env_p = old_env_p;
ecma_deref_object (catch_env_p);
JERRY_ASSERT ((!ecma_is_completion_value_empty (try_completion) && int_data->pos <= catch_end_oc)
|| (ecma_is_completion_value_empty (try_completion) && int_data->pos == catch_end_oc));
}
int_data->pos = catch_end_oc;
}
next_opcode = read_opcode (int_data->pos);
JERRY_ASSERT (next_opcode.op_idx == __op__idx_meta);
if (ecma_is_completion_value_exit (try_completion))
{
return try_completion;
}
if (next_opcode.data.meta.type == OPCODE_META_TYPE_FINALLY)
{
const opcode_counter_t finally_end_oc = (opcode_counter_t) (
read_meta_opcode_counter (OPCODE_META_TYPE_FINALLY, int_data) + int_data->pos);
int_data->pos++;
ecma_completion_value_t finally_completion = run_int_loop (int_data);
JERRY_ASSERT ((!ecma_is_completion_value_empty (finally_completion) && int_data->pos <= finally_end_oc)
|| (ecma_is_completion_value_empty (finally_completion) && int_data->pos == finally_end_oc));
int_data->pos = finally_end_oc;
if (!ecma_is_completion_value_empty (finally_completion))
{
ecma_free_completion_value (try_completion);
try_completion = finally_completion;
}
}
next_opcode = read_opcode (int_data->pos++);
JERRY_ASSERT (next_opcode.op_idx == __op__idx_meta);
JERRY_ASSERT (next_opcode.data.meta.type == OPCODE_META_TYPE_END_TRY_CATCH_FINALLY);
return try_completion;
} /* opfunc_try_block */
+183
View File
@@ -0,0 +1,183 @@
/* Copyright 2014-2015 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-ecma-support.h"
#ifndef JERRY_NDEBUG
/**
* Perform so-called 'strict eval or arguments reference' check
* that is used in definition of several statement handling algorithms,
* but has no ECMA-defined name.
*/
static void
do_strict_eval_arguments_check (ecma_object_t *ref_base_lex_env_p, /**< base of ECMA-reference
(lexical environment) */
ecma_string_t *var_name_string_p, /**< variable name */
bool is_strict) /**< flag indicating strict mode */
{
bool is_check_failed = false;
if (is_strict)
{
if (ref_base_lex_env_p != NULL)
{
JERRY_ASSERT (ecma_is_lexical_environment (ref_base_lex_env_p));
ecma_string_t* magic_string_eval = ecma_get_magic_string (ECMA_MAGIC_STRING_EVAL);
ecma_string_t* magic_string_arguments = ecma_get_magic_string (ECMA_MAGIC_STRING_ARGUMENTS);
is_check_failed = (ecma_compare_ecma_strings (var_name_string_p,
magic_string_eval)
|| ecma_compare_ecma_strings (var_name_string_p,
magic_string_arguments));
ecma_deref_ecma_string (magic_string_eval);
ecma_deref_ecma_string (magic_string_arguments);
}
}
JERRY_ASSERT (!is_check_failed);
} /* do_strict_eval_arguments_check */
#endif /* !JERRY_NDEBUG */
/**
* Check if the variable is register variable.
*
* @return true - if var_idx is register variable in current interpreter context,
* false - otherwise.
*/
bool
is_reg_variable (int_data_t *int_data, /**< interpreter context */
idx_t var_idx) /**< variable identifier */
{
return (var_idx >= int_data->min_reg_num && var_idx <= int_data->max_reg_num);
} /* is_reg_variable */
/**
* Get variable's value.
*
* @return completion value
* Returned value must be freed with ecma_free_completion_value
*/
ecma_completion_value_t
get_variable_value (int_data_t *int_data, /**< interpreter context */
idx_t var_idx, /**< variable identifier */
bool do_eval_or_arguments_check) /** run 'strict eval or arguments reference' check
See also: do_strict_eval_arguments_check */
{
ecma_completion_value_t ret_value;
if (is_reg_variable (int_data, var_idx))
{
ecma_value_t reg_value = ecma_stack_frame_get_reg_value (&int_data->stack_frame,
var_idx - int_data->min_reg_num);
JERRY_ASSERT (!ecma_is_value_empty (reg_value));
ret_value = ecma_make_normal_completion_value (ecma_copy_value (reg_value, true));
}
else
{
ecma_string_t var_name_string;
const literal_index_t lit_id = deserialize_lit_id_by_uid (var_idx, int_data->pos);
JERRY_ASSERT (lit_id != INVALID_LITERAL);
ecma_new_ecma_string_on_stack_from_lit_index (&var_name_string, lit_id);
ecma_object_t *ref_base_lex_env_p = ecma_op_resolve_reference_base (int_data->lex_env_p,
&var_name_string);
if (do_eval_or_arguments_check)
{
#ifndef JERRY_NDEBUG
do_strict_eval_arguments_check (ref_base_lex_env_p,
&var_name_string,
int_data->is_strict);
#endif /* !JERRY_NDEBUG */
}
ret_value = ecma_op_get_value_lex_env_base (ref_base_lex_env_p,
&var_name_string,
int_data->is_strict);
ecma_check_that_ecma_string_need_not_be_freed (&var_name_string);
}
return ret_value;
} /* get_variable_value */
/**
* Set variable's value.
*
* @return completion value
* Returned value must be freed with ecma_free_completion_value
*/
ecma_completion_value_t
set_variable_value (int_data_t *int_data, /**< interpreter context */
opcode_counter_t lit_oc, /**< opcode counter for literal */
idx_t var_idx, /**< variable identifier */
const ecma_value_t& value) /**< value to set */
{
ecma_completion_value_t ret_value;
if (is_reg_variable (int_data, var_idx))
{
ret_value = ecma_make_empty_completion_value ();
ecma_value_t reg_value = ecma_stack_frame_get_reg_value (&int_data->stack_frame,
var_idx - int_data->min_reg_num);
if (ecma_is_value_number (reg_value)
&& ecma_is_value_number (value))
{
*ecma_get_number_from_value (reg_value) = *ecma_get_number_from_value (value);
}
else
{
if (!ecma_is_value_empty (reg_value))
{
ecma_free_value (reg_value, false);
}
ecma_stack_frame_set_reg_value (&int_data->stack_frame,
var_idx - int_data->min_reg_num,
ecma_copy_value (value, false));
}
}
else
{
ecma_string_t var_name_string;
const literal_index_t lit_id = deserialize_lit_id_by_uid (var_idx, lit_oc);
JERRY_ASSERT (lit_id != INVALID_LITERAL);
ecma_new_ecma_string_on_stack_from_lit_index (&var_name_string, lit_id);
ecma_object_t *ref_base_lex_env_p = ecma_op_resolve_reference_base (int_data->lex_env_p,
&var_name_string);
#ifndef JERRY_NDEBUG
do_strict_eval_arguments_check (ref_base_lex_env_p,
&var_name_string,
int_data->is_strict);
#endif /* !JERRY_NDEBUG */
ret_value = ecma_op_put_value_lex_env_base (ref_base_lex_env_p,
&var_name_string,
int_data->is_strict,
value);
ecma_check_that_ecma_string_need_not_be_freed (&var_name_string);
}
return ret_value;
} /* set_variable_value */
+129
View File
@@ -0,0 +1,129 @@
/* Copyright 2014-2015 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-ecma-support.h"
#include "jrt.h"
#include "vm.h"
#include "opcodes.h"
#include "opcodes-native-call.h"
#include "jrt-libc-includes.h"
/**
* 'Native call' opcode handler.
*/
ecma_completion_value_t
opfunc_native_call (opcode_t opdata, /**< operation data */
int_data_t *int_data) /**< interpreter context */
{
// const idx_t dst_var_idx = opdata.data.native_call.lhs;
const idx_t native_call_id_idx = opdata.data.native_call.name;
const idx_t args_number = opdata.data.native_call.arg_list;
JERRY_ASSERT (native_call_id_idx < OPCODE_NATIVE_CALL__COUNT);
int_data->pos++;
JERRY_STATIC_ASSERT (OPCODE_NATIVE_CALL__COUNT < (1u << (sizeof (native_call_id_idx) * JERRY_BITSINBYTE)));
ecma_completion_value_t ret_value = 0;
MEM_DEFINE_LOCAL_ARRAY (arg_values, args_number, ecma_value_t);
ecma_length_t args_read;
ecma_completion_value_t get_arg_completion = fill_varg_list (int_data,
args_number,
arg_values,
&args_read);
if (ecma_is_completion_value_empty (get_arg_completion))
{
JERRY_ASSERT (args_read == args_number);
switch ((opcode_native_call_t)native_call_id_idx)
{
case OPCODE_NATIVE_CALL_LED_TOGGLE:
case OPCODE_NATIVE_CALL_LED_ON:
case OPCODE_NATIVE_CALL_LED_OFF:
case OPCODE_NATIVE_CALL_LED_ONCE:
case OPCODE_NATIVE_CALL_WAIT:
{
JERRY_UNIMPLEMENTED ("Device operations are not implemented.");
}
case OPCODE_NATIVE_CALL_PRINT:
{
JERRY_ASSERT (args_number == 1);
ECMA_TRY_CATCH (str_value,
ecma_op_to_string (arg_values[0]),
ret_value);
ecma_string_t *str_p = ecma_get_string_from_value (str_value);
int32_t chars = ecma_string_get_length (str_p);
JERRY_ASSERT (chars >= 0);
ssize_t zt_str_size = (ssize_t) sizeof (ecma_char_t) * (chars + 1);
ecma_char_t *zt_str_p = (ecma_char_t*) mem_heap_alloc_block ((size_t) zt_str_size,
MEM_HEAP_ALLOC_SHORT_TERM);
if (zt_str_p == NULL)
{
jerry_fatal (ERR_OUT_OF_MEMORY);
}
ecma_string_to_zt_string (str_p, zt_str_p, zt_str_size);
#if CONFIG_ECMA_CHAR_ENCODING == CONFIG_ECMA_CHAR_ASCII
printf ("%s\n", (char*) zt_str_p);
#elif CONFIG_ECMA_CHAR_ENCODING == CONFIG_ECMA_CHAR_UTF16
JERRY_UNIMPLEMENTED ("UTF-16 support is not implemented.");
#endif /* CONFIG_ECMA_CHAR_ENCODING == CONFIG_ECMA_CHAR_UTF16 */
mem_heap_free_block (zt_str_p);
ret_value = ecma_make_empty_completion_value ();
ECMA_FINALIZE (str_value);
break;
}
case OPCODE_NATIVE_CALL__COUNT:
{
JERRY_UNREACHABLE ();
}
}
}
else
{
JERRY_ASSERT (!ecma_is_completion_value_normal (get_arg_completion));
ret_value = get_arg_completion;
}
for (ecma_length_t arg_index = 0;
arg_index < args_read;
arg_index++)
{
ecma_free_value (arg_values[arg_index], true);
}
MEM_FINALIZE_LOCAL_ARRAY (arg_values);
return ret_value;
} /* opfunc_native_call */
+33
View File
@@ -0,0 +1,33 @@
/* 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.
*/
#ifndef OPCODES_NATIVE_CALL_H
#define OPCODES_NATIVE_CALL_H
/**
* Identifier of a native call
*/
typedef enum
{
OPCODE_NATIVE_CALL_LED_TOGGLE,
OPCODE_NATIVE_CALL_LED_ON,
OPCODE_NATIVE_CALL_LED_OFF,
OPCODE_NATIVE_CALL_LED_ONCE,
OPCODE_NATIVE_CALL_WAIT,
OPCODE_NATIVE_CALL_PRINT,
OPCODE_NATIVE_CALL__COUNT
} opcode_native_call_t;
#endif /* !OPCODES_NATIVE_CALL_H */
+107
View File
@@ -0,0 +1,107 @@
/* Copyright 2014-2015 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-ecma-support.h"
#include "jrt.h"
#include "vm.h"
#include "opcodes.h"
/**
* Fill arguments' list
*
* @return empty completion value if argument list was filled successfully,
* otherwise - not normal completion value indicating completion type
* of last expression evaluated
*/
ecma_completion_value_t
fill_varg_list (int_data_t *int_data, /**< interpreter context */
ecma_length_t args_number, /**< number of arguments */
ecma_value_t arg_values[], /**< out: arguments' values */
ecma_length_t *out_arg_number_p) /**< out: number of arguments
successfully read */
{
ecma_completion_value_t ret_value = ecma_make_empty_completion_value ();
ecma_length_t arg_index;
for (arg_index = 0;
arg_index < args_number;
arg_index++)
{
ecma_completion_value_t evaluate_arg_completion = run_int_loop (int_data);
if (ecma_is_completion_value_normal (evaluate_arg_completion))
{
opcode_t next_opcode = read_opcode (int_data->pos);
JERRY_ASSERT (next_opcode.op_idx == __op__idx_meta);
JERRY_ASSERT (next_opcode.data.meta.type == OPCODE_META_TYPE_VARG);
const idx_t varg_var_idx = next_opcode.data.meta.data_1;
ecma_completion_value_t get_arg_completion = get_variable_value (int_data, varg_var_idx, false);
if (ecma_is_completion_value_normal (get_arg_completion))
{
arg_values[arg_index] = ecma_get_completion_value_value (get_arg_completion);
}
else
{
ret_value = get_arg_completion;
}
}
else
{
ret_value = evaluate_arg_completion;
}
if (!ecma_is_completion_value_empty (ret_value))
{
break;
}
int_data->pos++;
}
*out_arg_number_p = arg_index;
return ret_value;
} /* fill_varg_list */
/**
* Fill parameters' list
*/
void
fill_params_list (int_data_t *int_data, /**< interpreter context */
ecma_length_t params_number, /**< number of parameters */
ecma_string_t* params_names[]) /**< out: parameters' names */
{
uint32_t param_index;
for (param_index = 0;
param_index < params_number;
param_index++)
{
opcode_t next_opcode = read_opcode (int_data->pos);
JERRY_ASSERT (next_opcode.op_idx == __op__idx_meta);
JERRY_ASSERT (next_opcode.data.meta.type == OPCODE_META_TYPE_VARG);
const literal_index_t param_name_lit_idx = deserialize_lit_id_by_uid (next_opcode.data.meta.data_1, int_data->pos);
params_names [param_index] = ecma_new_ecma_string_from_lit_index (param_name_lit_idx);
int_data->pos++;
}
JERRY_ASSERT (param_index == params_number);
} /* fill_params_list */
File diff suppressed because it is too large Load Diff
+282
View File
@@ -0,0 +1,282 @@
/* Copyright 2014-2015 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.
*/
#ifndef OPCODES_H
#define OPCODES_H
#include "ecma-globals.h"
#include "ecma-stack.h"
#include "jrt.h"
/* Maximum opcodes number in bytecode. */
#define MAX_OPCODES (256*256 - 1)
#define OP_0(action, name) \
__##action (name, void, void, void)
#define OP_1(action, name, field1) \
__##action (name, field1, void, void)
#define OP_2(action, name, field1, field2) \
__##action (name, field1, field2, void)
#define OP_3(action, name, field1, field2, field3) \
__##action (name, field1, field2, field3)
typedef uint16_t opcode_counter_t; /** opcode counters */
typedef uint8_t idx_t; /** index values */
/**
* Descriptor of assignment's second argument
* that specifies type of third argument.
*/
typedef enum
{
OPCODE_ARG_TYPE_SIMPLE, /**< ecma_simple_value_t */
OPCODE_ARG_TYPE_SMALLINT, /**< small integer: from 0 to 255 */
OPCODE_ARG_TYPE_SMALLINT_NEGATE, /**< small integer: from -255 to -0 */
OPCODE_ARG_TYPE_NUMBER, /**< index of number literal */
OPCODE_ARG_TYPE_NUMBER_NEGATE, /**< index of number literal with negation */
OPCODE_ARG_TYPE_STRING, /**< index of string literal */
OPCODE_ARG_TYPE_VARIABLE /**< index of variable name */
} opcode_arg_type_operand;
/**
* Types of data in 'meta' opcode.
*/
typedef enum
{
OPCODE_META_TYPE_UNDEFINED, /**< undefined meta (should be rewritten) */
OPCODE_META_TYPE_THIS_ARG, /**< value (var_idx) of this used during call */
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_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_END_WITH, /**< end of with statement */
OPCODE_META_TYPE_FUNCTION_END, /**< offset to function end */
OPCODE_META_TYPE_CATCH, /**< mark of beginning of catch block containing pointer to end of catch block */
OPCODE_META_TYPE_CATCH_EXCEPTION_IDENTIFIER, /**< literal index containing name of variable with exception object */
OPCODE_META_TYPE_FINALLY, /**< mark of beginning of finally block containing pointer to end of finally block */
OPCODE_META_TYPE_END_TRY_CATCH_FINALLY, /**< mark of end of try-catch, try-finally, try-catch-finally blocks */
OPCODE_META_TYPE_STRICT_CODE /**< mark of beginning of strict code */
} opcode_meta_type;
typedef struct
{
opcode_counter_t pos; /**< current opcode to execute */
ecma_value_t this_binding; /**< this binding for current context */
ecma_object_t *lex_env_p; /**< current lexical environment */
bool is_strict; /**< is current code execution mode strict? */
bool is_eval_code; /**< is current code executed with eval */
idx_t min_reg_num; /**< minimum idx used for register identification */
idx_t max_reg_num; /**< maximum idx used for register identification */
ecma_number_t* tmp_num_p; /**< an allocated number (to reduce temporary allocations) */
ecma_stack_frame_t stack_frame; /**< ecma-stack frame associated with the context */
#ifdef MEM_STATS
size_t context_peak_allocated_heap_bytes;
size_t context_peak_waste_heap_bytes;
size_t context_peak_pools_count;
size_t context_peak_allocated_pool_chunks;
mem_heap_stats_t heap_stats_context_enter;
mem_pools_stats_t pools_stats_context_enter;
#endif /* MEM_STATS */
} int_data_t;
opcode_counter_t calc_opcode_counter_from_idx_idx (const idx_t oc_idx_1, const idx_t oc_idx_2);
opcode_counter_t read_meta_opcode_counter (opcode_meta_type expected_type, int_data_t *int_data);
#define OP_CALLS_AND_ARGS(p, a) \
p##_3 (a, call_n, lhs, name_lit_idx, arg_list) \
p##_3 (a, native_call, lhs, name, arg_list) \
p##_3 (a, construct_n, lhs, name_lit_idx, arg_list) \
p##_2 (a, func_decl_n, name_lit_idx, arg_list) \
p##_3 (a, func_expr_n, lhs, name_lit_idx, arg_list) \
p##_1 (a, exitval, status_code) \
p##_1 (a, retval, ret_value) \
p##_0 (a, ret)
#define OP_INITS(p, a) \
p##_2 (a, array_decl, lhs, list) \
p##_3 (a, prop_getter, lhs, obj, prop) \
p##_3 (a, prop_setter, obj, prop, rhs) \
p##_2 (a, obj_decl, lhs, list) \
p##_1 (a, this_binding, lhs) \
p##_2 (a, delete_var, lhs, name) \
p##_3 (a, delete_prop, lhs, base, name) \
p##_2 (a, typeof, lhs, obj) \
p##_1 (a, with, expr) \
p##_2 (a, try_block, oc_idx_1, oc_idx_2) \
p##_1 (a, throw_value, var)
#define OP_ASSIGNMENTS(p, a) \
p##_3 (a, assignment, var_left, type_value_right, value_right)
#define OP_B_SHIFTS(p, a) \
p##_3 (a, b_shift_left, dst, var_left, var_right) \
p##_3 (a, b_shift_right, dst, var_left, var_right) \
p##_3 (a, b_shift_uright, dst, var_left, var_right)
#define OP_B_BITWISE(p, a) \
p##_3 (a, b_and, dst, var_left, var_right) \
p##_3 (a, b_or, dst, var_left, var_right) \
p##_3 (a, b_xor, dst, var_left, var_right) \
p##_2 (a, b_not, dst, var_right)
#define OP_B_LOGICAL(p, a) \
p##_2 (a, logical_not, dst, var_right)
#define OP_EQUALITY(p, a) \
p##_3 (a, equal_value, dst, var_left, var_right) \
p##_3 (a, not_equal_value, dst, var_left, var_right) \
p##_3 (a, equal_value_type, dst, var_left, var_right) \
p##_3 (a, not_equal_value_type, dst, var_left, var_right)
#define OP_RELATIONAL(p, a) \
p##_3 (a, less_than, dst, var_left, var_right) \
p##_3 (a, greater_than, dst, var_left, var_right) \
p##_3 (a, less_or_equal_than, dst, var_left, var_right) \
p##_3 (a, greater_or_equal_than, dst, var_left, var_right) \
p##_3 (a, instanceof, dst, var_left, var_right) \
p##_3 (a, in, dst, var_left, var_right)
#define OP_ARITHMETIC(p, a) \
p##_2 (a, post_incr, dst, var_right) \
p##_2 (a, post_decr, dst, var_right) \
p##_2 (a, pre_incr, dst, var_right) \
p##_2 (a, pre_decr, dst, var_right) \
p##_3 (a, addition, dst, var_left, var_right) \
p##_3 (a, substraction, dst, var_left, var_right) \
p##_3 (a, division, dst, var_left, var_right) \
p##_3 (a, multiplication, dst, var_left, var_right) \
p##_3 (a, remainder, dst, var_left, var_right) \
p##_2 (a, unary_minus, dst, var) \
p##_2 (a, unary_plus, dst, var)
#define OP_JUMPS(p, a) \
p##_2 (a, jmp_up, opcode_1, opcode_2) \
p##_2 (a, jmp_down, opcode_1, opcode_2) \
p##_0 (a, nop) \
p##_3 (a, is_true_jmp_up, value, opcode_1, opcode_2) \
p##_3 (a, is_true_jmp_down, value, opcode_1, opcode_2) \
p##_3 (a, is_false_jmp_up, value, opcode_1, opcode_2) \
p##_3 (a, is_false_jmp_down, value, opcode_1, opcode_2)
#define OP_LIST_FULL(p, a) \
OP_CALLS_AND_ARGS (p, a) \
OP_INITS (p, a) \
OP_ASSIGNMENTS (p, a) \
OP_B_LOGICAL (p, a) \
OP_B_BITWISE (p, a) \
OP_B_SHIFTS (p, a) \
OP_EQUALITY (p, a) \
OP_RELATIONAL (p, a) \
OP_ARITHMETIC (p, a) \
OP_JUMPS (p, a) \
p##_1 (a, var_decl, variable_name) \
p##_2 (a, reg_var_decl, min, max) \
p##_3 (a, meta, type, data_1, data_2)
#define OP_LIST(a) OP_LIST_FULL (OP, a)
#define OP_ARGS_LIST(a) OP_LIST_FULL (a, void)
#define OP_DATA_0(action, name) \
typedef struct \
{ \
idx_t __do_not_use; \
} __op_##name;
#define OP_DATA_1(action, name, arg1) \
typedef struct \
{ \
idx_t arg1; \
} __op_##name;
#define OP_DATA_2(action, name, arg1, arg2) \
typedef struct \
{ \
idx_t arg1; \
idx_t arg2; \
} __op_##name;
#define OP_DATA_3(action, name, arg1, arg2, arg3) \
typedef struct \
{ \
idx_t arg1; \
idx_t arg2; \
idx_t arg3; \
} __op_##name;
OP_ARGS_LIST (OP_DATA)
#define __OP_STRUCT_FIELD(name, arg1, arg2, arg3) __op_##name name;
typedef struct
{
idx_t op_idx;
union
{
OP_LIST (OP_STRUCT_FIELD)
} data;
} opcode_t;
#undef __OP_STRUCT_FIELD
#define __OP_ENUM_FIELD(name, arg1, arg2, arg3) __op__idx_##name ,
enum __opcode_idx
{
OP_LIST (OP_ENUM_FIELD)
LAST_OP
};
#undef __OP_ENUM_FIELD
#define __OP_FUNC_DECL(name, arg1, arg2, arg3) ecma_completion_value_t opfunc_##name (opcode_t, int_data_t*);
OP_LIST (OP_FUNC_DECL)
#undef __OP_FUNC_DECL
typedef ecma_completion_value_t (*opfunc) (opcode_t, int_data_t *);
#define GETOP_DECL_0(a, name) \
opcode_t getop_##name (void);
#define GETOP_DECL_1(a, name, arg1) \
opcode_t getop_##name (idx_t);
#define GETOP_DECL_2(a, name, arg1, arg2) \
opcode_t getop_##name (idx_t, idx_t);
#define GETOP_DECL_3(a, name, arg1, arg2, arg3) \
opcode_t getop_##name (idx_t, idx_t, idx_t);
#define GETOP_DEF_0(a, name) \
opcode_t getop_##name (void) \
{ \
opcode_t opdata; \
opdata.op_idx = __op__idx_##name; \
return opdata; \
}
OP_ARGS_LIST (GETOP_DECL)
#undef GETOP_DECL_0
#undef GETOP_DECL_1
#undef GETOP_DECL_2
#undef GETOP_DECL_3
typedef struct
{
uint8_t uids[4];
}
raw_opcode;
#endif /* OPCODES_H */
+653
View File
@@ -0,0 +1,653 @@
/* Copyright 2014-2015 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 "jrt.h"
#ifdef JERRY_ENABLE_PRETTY_PRINTER
#include "pretty-printer.h"
#include "jrt-libc-includes.h"
#include "lexer.h"
#include "deserializer.h"
#include "opcodes-native-call.h"
#include "ecma-helpers.h"
#include "ecma-globals.h"
#include <stdarg.h>
#define NAME_TO_ID(op) (__op__idx_##op)
#define __OPCODE_STR(name, arg1, arg2, arg3) \
#name,
#define __OPCODE_SIZE(name, arg1, arg2, arg3) \
(uint8_t) (sizeof (__op_##name) + 1),
static const char* opcode_names[] =
{
OP_LIST (OPCODE_STR)
""
};
static uint8_t opcode_sizes[] =
{
OP_LIST (OPCODE_SIZE)
0
};
static void
dump_literal (literal lit)
{
switch (lit.type)
{
case LIT_NUMBER:
{
if (ecma_number_is_nan (lit.data.num))
{
printf ("%s : NUMBER", "NaN");
}
else
{
printf ("%d : Truncated NUMBER", (int) lit.data.num);
}
break;
}
case LIT_MAGIC_STR:
{
printf ("%s : MAGIC STRING", (const char *) ecma_get_magic_string_zt (lit.data.magic_str_id));
break;
}
case LIT_STR:
{
printf ("%s : STRING", (const char *) (lit.data.lp.str));
break;
}
default:
{
JERRY_UNREACHABLE ();
}
}
}
void
pp_literals (const literal lits[], literal_index_t size)
{
printf ("LITERALS %lu:\n", (unsigned long) size);
for (literal_index_t i = 0; i < size; i++)
{
printf ("%3lu ", (unsigned long) i);
dump_literal (lits[i]);
putchar ('\n');
}
}
static char buff[ECMA_MAX_CHARS_IN_STRINGIFIED_NUMBER];
static void
clear_temp_buffer (void)
{
memset (buff, 0, ECMA_MAX_CHARS_IN_STRINGIFIED_NUMBER);
}
static const char *
lit_id_to_str (literal_index_t id)
{
literal lit = lexer_get_literal_by_id (id);
if (lit.type == LIT_STR || lit.type == LIT_MAGIC_STR)
{
return (char *) literal_to_zt (lit);
}
else
{
JERRY_ASSERT (lit.type == LIT_NUMBER);
clear_temp_buffer ();
ecma_number_to_zt_string (lit.data.num, (ecma_char_t *) buff, ECMA_MAX_CHARS_IN_STRINGIFIED_NUMBER);
return buff;
}
}
static const char *
tmp_id_to_str (idx_t id)
{
JERRY_ASSERT (id != LITERAL_TO_REWRITE);
JERRY_ASSERT (id >= 128);
clear_temp_buffer ();
strncpy (buff, "tmp", 3);
if (id / 100 != 0)
{
buff[3] = (char) (id / 100 + '0');
buff[4] = (char) ((id % 100) / 10 + '0');
buff[5] = (char) (id % 10 + '0');
}
else if (id / 10 != 0)
{
buff[3] = (char) (id / 10 + '0');
buff[4] = (char) (id % 10 + '0');
}
else
{
buff[3] = (char) (id + '0');
}
return buff;
}
static const char *
var_to_str (opcode_t opcode, literal_index_t lit_ids[], opcode_counter_t oc, uint8_t current_arg)
{
raw_opcode raw = *(raw_opcode*) &opcode;
if (raw.uids[current_arg] == LITERAL_TO_REWRITE)
{
if (lit_ids == NULL)
{
return "hz";
}
JERRY_ASSERT (lit_ids[current_arg - 1] != NOT_A_LITERAL
&& lit_ids[current_arg - 1] != INVALID_LITERAL);
return lit_id_to_str (lit_ids[current_arg - 1]);
}
else if (raw.uids[current_arg] >= 128)
{
return tmp_id_to_str (raw.uids[current_arg]);
}
else
{
return lit_id_to_str (deserialize_lit_id_by_uid (raw.uids[current_arg], oc));
}
}
static void
pp_printf (const char *format, opcode_t opcode, literal_index_t lit_ids[], opcode_counter_t oc)
{
uint8_t current_arg = 1;
while (*format)
{
if (*format != '%')
{
putchar (*format);
format++;
continue;
}
format++;
switch (*format)
{
case 'd':
{
raw_opcode raw = *(raw_opcode*) &opcode;
printf ("%d", raw.uids[current_arg]);
break;
}
case 's':
{
printf ("%s", var_to_str (opcode, lit_ids, oc, current_arg));
break;
}
default:
{
putchar ('%');
continue;
}
}
current_arg++;
format++;
}
}
#define PP_OP(op_name, format) \
case NAME_TO_ID(op_name): pp_printf (format, opm.op, opm.lit_id, oc); break;
#define VAR(i) var_to_str (opm.op, opm.lit_id, oc, i)
#define OC(i, j) __extension__({ raw_opcode* raw = (raw_opcode *) &opm.op; \
calc_opcode_counter_from_idx_idx (raw->uids[i], raw->uids[j]); })
static int vargs_num = 0;
static int seen_vargs = 0;
static void
dump_asm (opcode_counter_t oc, opcode_t opcode)
{
uint8_t i = 0;
uint8_t opcode_id = opcode.op_idx;
printf ("%3d: %20s ", oc, opcode_names[opcode_id]);
if (opcode_id != NAME_TO_ID (nop) && opcode_id != NAME_TO_ID (ret))
{
for (i = 1; i < opcode_sizes[opcode_id]; i++)
{
printf ("%4d ", ((raw_opcode *) &opcode)->uids[i]);
}
}
for (; i < 4; i++)
{
printf (" ");
}
}
void
pp_op_meta (opcode_counter_t oc, op_meta opm, bool rewrite)
{
dump_asm (oc, opm.op);
printf (" // ");
switch (opm.op.op_idx)
{
PP_OP (addition, "%s = %s + %s;");
PP_OP (substraction, "%s = %s - %s;");
PP_OP (division, "%s = %s - %s;");
PP_OP (multiplication, "%s = %s * %s;");
PP_OP (remainder, "%s = %s %% %s;");
PP_OP (unary_minus, "%s = -%s;");
PP_OP (unary_plus, "%s = +%s;");
PP_OP (b_shift_left, "%s = %s << %s;");
PP_OP (b_shift_right, "%s = %s >> %s;");
PP_OP (b_shift_uright, "%s = %s >>> %s;");
PP_OP (b_and, "%s = %s & %s;");
PP_OP (b_or, "%s = %s | %s;");
PP_OP (b_xor, "%s = %s ^ %s;");
PP_OP (b_not, "%s = ~ %s;");
PP_OP (logical_not, "%s = ! %s;");
PP_OP (equal_value, "%s = %s == %s;");
PP_OP (not_equal_value, "%s = %s != %s;");
PP_OP (equal_value_type, "%s = %s === %s;");
PP_OP (not_equal_value_type, "%s = %s !== %s;");
PP_OP (less_than, "%s = %s < %s;");
PP_OP (greater_than, "%s = %s > %s;");
PP_OP (less_or_equal_than, "%s = %s <= %s;");
PP_OP (greater_or_equal_than, "%s = %s >= %s;");
PP_OP (instanceof, "%s = %s instanceof %s;");
PP_OP (in, "%s = %s in %s;");
PP_OP (post_incr, "%s = %s++;");
PP_OP (post_decr, "%s = %s--;");
PP_OP (pre_incr, "%s = ++%s;");
PP_OP (pre_decr, "%s = --%s;");
PP_OP (throw_value, "throw %s;");
PP_OP (reg_var_decl, "var %s .. %s;");
PP_OP (var_decl, "var %s;");
PP_OP (nop, ";");
PP_OP (exitval, "exit %d;");
PP_OP (retval, "return %s;");
PP_OP (ret, "ret;");
PP_OP (prop_getter, "%s = %s[%s];");
PP_OP (prop_setter, "%s[%s] = %s;");
PP_OP (this_binding, "%s = this;");
PP_OP (delete_var, "%s = delete %s;");
PP_OP (delete_prop, "%s = delete %s.%s;");
PP_OP (typeof, "%s = typeof %s;");
PP_OP (with, "with (%s);");
case NAME_TO_ID (is_true_jmp_up): printf ("if (%s) goto %d;", VAR (1), oc - OC (2, 3)); break;
case NAME_TO_ID (is_false_jmp_up): printf ("if (%s == false) goto %d;", VAR (1), oc - OC (2, 3)); break;
case NAME_TO_ID (is_true_jmp_down): printf ("if (%s) goto %d;", VAR (1), oc + OC (2, 3)); break;
case NAME_TO_ID (is_false_jmp_down): printf ("if (%s == false) goto %d;", VAR (1), oc + OC (2, 3)); break;
case NAME_TO_ID (jmp_up): printf ("goto %d;", oc - OC (1, 2)); break;
case NAME_TO_ID (jmp_down): printf ("goto %d;", oc + OC (1, 2)); break;
case NAME_TO_ID (try_block): printf ("try (end: %d);", oc + OC (1, 2)); break;
case NAME_TO_ID (assignment):
{
printf ("%s = ", VAR (1));
switch (opm.op.data.assignment.type_value_right)
{
case OPCODE_ARG_TYPE_STRING: printf ("'%s': STRING;", VAR (3)); break;
case OPCODE_ARG_TYPE_NUMBER: printf ("%s: NUMBER;", VAR (3)); break;
case OPCODE_ARG_TYPE_NUMBER_NEGATE: printf ("-%s: NUMBER;", VAR (3)); break;
case OPCODE_ARG_TYPE_SMALLINT: printf ("%d: SMALLINT;", opm.op.data.assignment.value_right); break;
case OPCODE_ARG_TYPE_SMALLINT_NEGATE: printf ("-%d: SMALLINT;", opm.op.data.assignment.value_right); break;
case OPCODE_ARG_TYPE_VARIABLE: printf ("%s : TYPEOF(%s);", VAR (3), VAR (3)); break;
case OPCODE_ARG_TYPE_SIMPLE:
{
switch (opm.op.data.assignment.value_right)
{
case ECMA_SIMPLE_VALUE_NULL: printf ("null"); break;
case ECMA_SIMPLE_VALUE_FALSE: printf ("false"); break;
case ECMA_SIMPLE_VALUE_TRUE: printf ("true"); break;
case ECMA_SIMPLE_VALUE_UNDEFINED: printf ("undefined"); break;
default: JERRY_UNREACHABLE ();
}
printf (": SIMPLE;");
break;
}
}
break;
}
case NAME_TO_ID (call_n):
{
if (opm.op.data.call_n.arg_list == 0)
{
printf ("%s = %s ();", VAR (1), VAR (2));
}
else
{
vargs_num = opm.op.data.call_n.arg_list;
seen_vargs = 0;
}
break;
}
case NAME_TO_ID (native_call):
{
if (opm.op.data.native_call.arg_list == 0)
{
printf ("%s = ", VAR (1));
switch (opm.op.data.native_call.name)
{
case OPCODE_NATIVE_CALL_LED_TOGGLE: printf ("LEDToggle ();"); break;
case OPCODE_NATIVE_CALL_LED_ON: printf ("LEDOn ();"); break;
case OPCODE_NATIVE_CALL_LED_OFF: printf ("LEDOff ();"); break;
case OPCODE_NATIVE_CALL_LED_ONCE: printf ("LEDOnce ();"); break;
case OPCODE_NATIVE_CALL_WAIT: printf ("wait ();"); break;
case OPCODE_NATIVE_CALL_PRINT: printf ("print ();"); break;
default: JERRY_UNREACHABLE ();
}
}
else
{
vargs_num = opm.op.data.native_call.arg_list;
seen_vargs = 0;
}
break;
}
case NAME_TO_ID (construct_n):
{
if (opm.op.data.construct_n.arg_list == 0)
{
printf ("%s = new %s;", VAR (1), VAR (2));
}
else
{
vargs_num = opm.op.data.construct_n.arg_list;
seen_vargs = 0;
}
break;
}
case NAME_TO_ID (func_decl_n):
{
if (opm.op.data.func_decl_n.arg_list == 0)
{
printf ("function %s ();", VAR (1));
}
else
{
vargs_num = opm.op.data.func_decl_n.arg_list;
seen_vargs = 0;
}
break;
}
case NAME_TO_ID (func_expr_n):
{
if (opm.op.data.func_expr_n.arg_list == 0)
{
if (opm.op.data.func_expr_n.name_lit_idx == INVALID_VALUE)
{
printf ("%s = function ();", VAR (1));
}
else
{
printf ("%s = function %s ();", VAR (1), VAR (2));
}
}
else
{
vargs_num = opm.op.data.func_expr_n.arg_list;
seen_vargs = 0;
}
break;
}
case NAME_TO_ID (array_decl):
{
if (opm.op.data.array_decl.list == 0)
{
printf ("%s = [];", VAR (1));
}
else
{
vargs_num = opm.op.data.array_decl.list;
seen_vargs = 0;
}
break;
}
case NAME_TO_ID (obj_decl):
{
if (opm.op.data.obj_decl.list == 0)
{
printf ("%s = {};", VAR (1));
}
else
{
vargs_num = opm.op.data.obj_decl.list;
seen_vargs = 0;
}
break;
}
case NAME_TO_ID (meta):
{
switch (opm.op.data.meta.type)
{
case OPCODE_META_TYPE_UNDEFINED:
{
printf ("unknown meta;");
break;
}
case OPCODE_META_TYPE_THIS_ARG:
case OPCODE_META_TYPE_VARG:
case OPCODE_META_TYPE_VARG_PROP_DATA:
case OPCODE_META_TYPE_VARG_PROP_GETTER:
case OPCODE_META_TYPE_VARG_PROP_SETTER:
{
seen_vargs++;
if (seen_vargs == vargs_num)
{
bool found = false;
opcode_counter_t start = oc;
while ((int16_t) start >= 0 && !found)
{
start--;
switch (deserialize_opcode (start).op_idx)
{
case NAME_TO_ID (call_n):
case NAME_TO_ID (native_call):
case NAME_TO_ID (construct_n):
case NAME_TO_ID (func_decl_n):
case NAME_TO_ID (func_expr_n):
case NAME_TO_ID (array_decl):
case NAME_TO_ID (obj_decl):
{
found = true;
break;
}
}
}
opcode_t start_op = deserialize_opcode (start);
switch (start_op.op_idx)
{
case NAME_TO_ID (call_n):
{
printf ("%s = %s (", var_to_str (start_op, NULL, start, 1),
var_to_str (start_op, NULL, start, 2));
break;
}
case NAME_TO_ID (native_call):
{
printf ("%s = ", var_to_str (start_op, NULL, start, 1));
switch (start_op.data.native_call.name)
{
case OPCODE_NATIVE_CALL_LED_TOGGLE: printf ("LEDToggle ("); break;
case OPCODE_NATIVE_CALL_LED_ON: printf ("LEDOn ("); break;
case OPCODE_NATIVE_CALL_LED_OFF: printf ("LEDOff ("); break;
case OPCODE_NATIVE_CALL_LED_ONCE: printf ("LEDOnce ("); break;
case OPCODE_NATIVE_CALL_WAIT: printf ("wait ("); break;
case OPCODE_NATIVE_CALL_PRINT: printf ("print ("); break;
default: JERRY_UNREACHABLE ();
}
break;
}
case NAME_TO_ID (construct_n):
{
printf ("%s = new %s (", var_to_str (start_op, NULL, start, 1),
var_to_str (start_op, NULL, start, 2));
break;
}
case NAME_TO_ID (func_decl_n):
{
printf ("function %s (", var_to_str (start_op, NULL, start, 1));
break;
}
case NAME_TO_ID (func_expr_n):
{
if (start_op.data.func_expr_n.name_lit_idx == INVALID_VALUE)
{
printf ("%s = function (", var_to_str (start_op, NULL, start, 1));
}
else
{
printf ("%s = function %s (", var_to_str (start_op, NULL, start, 1),
var_to_str (start_op, NULL, start, 2));
}
break;
}
case NAME_TO_ID (array_decl):
{
printf ("%s = [", var_to_str (start_op, NULL, start, 1));
break;
}
case NAME_TO_ID (obj_decl):
{
printf ("%s = {", var_to_str (start_op, NULL, start, 1));
break;
}
default:
{
JERRY_UNREACHABLE ();
}
}
for (opcode_counter_t counter = start; counter <= oc; counter++)
{
opcode_t meta_op = deserialize_opcode (counter);
switch (meta_op.op_idx)
{
case NAME_TO_ID (meta):
{
switch (meta_op.data.meta.type)
{
case OPCODE_META_TYPE_THIS_ARG:
{
printf ("this_arg = %s", var_to_str (meta_op, NULL, counter, 2));
break;
}
case OPCODE_META_TYPE_VARG:
{
printf ("%s", var_to_str (meta_op, NULL, counter, 2));
break;
}
case OPCODE_META_TYPE_VARG_PROP_DATA:
{
printf ("%s:%s", var_to_str (meta_op, NULL, counter, 2),
var_to_str (meta_op, NULL, counter, 3));
break;
}
case OPCODE_META_TYPE_VARG_PROP_GETTER:
{
printf ("%s = get %s ();", var_to_str (meta_op, NULL, counter, 2),
var_to_str (meta_op, NULL, counter, 3));
break;
}
case OPCODE_META_TYPE_VARG_PROP_SETTER:
{
printf ("%s = set (%s);", var_to_str (meta_op, NULL, counter, 2),
var_to_str (meta_op, NULL, counter, 3));
break;
}
default:
{
continue;
}
}
if (counter != oc)
{
printf (", ");
}
break;
}
}
}
switch (start_op.op_idx)
{
case NAME_TO_ID (array_decl):
{
printf ("];");
break;
}
case NAME_TO_ID (obj_decl):
{
printf ("};");
break;
}
default:
{
printf (");");
}
}
}
break;
}
case OPCODE_META_TYPE_END_WITH:
{
printf ("end with;");
break;
}
case OPCODE_META_TYPE_FUNCTION_END:
{
printf ("function end: %d;", oc + OC (2, 3));
break;
}
case OPCODE_META_TYPE_CATCH:
{
printf ("catch end: %d;", oc + OC (2, 3));
break;
}
case OPCODE_META_TYPE_CATCH_EXCEPTION_IDENTIFIER:
{
printf ("catch (%s);", VAR (2));
break;
}
case OPCODE_META_TYPE_FINALLY:
{
printf ("finally end: %d;", oc + OC (2, 3));
break;
}
case OPCODE_META_TYPE_END_TRY_CATCH_FINALLY:
{
printf ("end try");
break;
}
case OPCODE_META_TYPE_STRICT_CODE:
{
printf ("use strict;");
break;
}
default:
{
JERRY_UNREACHABLE ();
}
}
break;
}
default:
{
JERRY_UNREACHABLE ();
}
}
if (rewrite)
{
printf (" // REWRITE");
}
printf ("\n");
}
#endif /* JERRY_ENABLE_PRETTY_PRINTER */
+30
View File
@@ -0,0 +1,30 @@
/* Copyright 2014-2015 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.
*/
#ifndef PRETTY_PRINTER
#define PRETTY_PRINTER
#include "jrt.h"
#ifdef JERRY_ENABLE_PRETTY_PRINTER
#include "vm.h"
#include "literal.h"
#include "scopes-tree.h"
void pp_opcode (opcode_counter_t, opcode_t, bool);
void pp_op_meta (opcode_counter_t, op_meta, bool);
void pp_literals (const literal *, literal_index_t);
#endif // JERRY_ENABLE_PRETTY_PRINTER
#endif // PRETTY_PRINTER
+529
View File
@@ -0,0 +1,529 @@
/* Copyright 2014-2015 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 "ecma-alloc.h"
#include "ecma-builtins.h"
#include "ecma-gc.h"
#include "ecma-globals.h"
#include "ecma-helpers.h"
#include "ecma-lex-env.h"
#include "ecma-operations.h"
#include "ecma-stack.h"
#include "jrt.h"
#include "vm.h"
#include "jrt-libc-includes.h"
#include "mem-allocator.h"
#define __INIT_OP_FUNC(name, arg1, arg2, arg3) [ __op__idx_##name ] = opfunc_##name,
static const opfunc __opfuncs[LAST_OP] =
{
OP_LIST (INIT_OP_FUNC)
};
#undef __INIT_OP_FUNC
JERRY_STATIC_ASSERT (sizeof (opcode_t) <= 4);
const opcode_t *__program = NULL;
#ifdef MEM_STATS
#define __OP_FUNC_NAME(name, arg1, arg2, arg3) #name,
static const char *__op_names[LAST_OP] =
{
OP_LIST (OP_FUNC_NAME)
};
#undef __OP_FUNC_NAME
#define INTERP_MEM_PRINT_INDENTATION_STEP (5)
#define INTERP_MEM_PRINT_INDENTATION_MAX (125)
static uint32_t interp_mem_stats_print_indentation = 0;
static bool interp_mem_stats_enabled = false;
static void
interp_mem_stats_print_legend (void)
{
if (likely (!interp_mem_stats_enabled))
{
return;
}
printf ("----- Legend of memory usage trace during interpretation -----\n\n"
"\tEntering block = beginning execution of initial (global) scope or function.\n\n"
"\tInformation on each value is formatted as following: (p -> n ( [+-]c, local l, peak g), where:\n"
"\t p - value just before starting of item's execution;\n"
"\t n - value just after end of item's execution;\n"
"\t [+-c] - difference between n and p;\n"
"\t l - temporary usage of memory during item's execution;\n"
"\t g - global peak of the value during program's execution.\n\n"
"\tChunks are items allocated in a pool."
" If there is no pool with a free chunk upon chunk allocation request,\n"
"\tthen new pool is allocated on the heap (that causes increase of number of allocated heap bytes).\n\n");
}
static void
interp_mem_get_stats (mem_heap_stats_t *out_heap_stats_p,
mem_pools_stats_t *out_pool_stats_p,
bool reset_peak_before,
bool reset_peak_after)
{
if (likely (!interp_mem_stats_enabled))
{
return;
}
/* Requesting to free as much memory as we currently can */
ecma_try_to_give_back_some_memory (MEM_TRY_GIVE_MEMORY_BACK_SEVERITY_CRITICAL);
if (reset_peak_before)
{
mem_heap_stats_reset_peak ();
mem_pools_stats_reset_peak ();
}
mem_heap_get_stats (out_heap_stats_p);
mem_pools_get_stats (out_pool_stats_p);
if (reset_peak_after)
{
mem_heap_stats_reset_peak ();
mem_pools_stats_reset_peak ();
}
}
static void
interp_mem_stats_context_enter (int_data_t *int_data_p,
opcode_counter_t block_position)
{
if (likely (!interp_mem_stats_enabled))
{
return;
}
const uint32_t indentation = JERRY_MIN (interp_mem_stats_print_indentation,
INTERP_MEM_PRINT_INDENTATION_MAX);
char indent_prefix[INTERP_MEM_PRINT_INDENTATION_MAX + 2];
memset (indent_prefix, ' ', sizeof (indent_prefix));
indent_prefix [indentation] = '|';
indent_prefix [indentation + 1] = '\0';
int_data_p->context_peak_allocated_heap_bytes = 0;
int_data_p->context_peak_waste_heap_bytes = 0;
int_data_p->context_peak_pools_count = 0;
int_data_p->context_peak_allocated_pool_chunks = 0;
interp_mem_get_stats (&int_data_p->heap_stats_context_enter,
&int_data_p->pools_stats_context_enter,
false, false);
printf ("\n%s--- Beginning interpretation of a block at position %u ---\n"
"%s Allocated heap bytes: %5u\n"
"%s Waste heap bytes: %5u\n"
"%s Pools: %5u\n"
"%s Allocated pool chunks: %5u\n\n",
indent_prefix, (uint32_t) block_position,
indent_prefix, (uint32_t) int_data_p->heap_stats_context_enter.allocated_bytes,
indent_prefix, (uint32_t) int_data_p->heap_stats_context_enter.waste_bytes,
indent_prefix, (uint32_t) int_data_p->pools_stats_context_enter.pools_count,
indent_prefix, (uint32_t) int_data_p->pools_stats_context_enter.allocated_chunks);
}
static void
interp_mem_stats_context_exit (int_data_t *int_data_p,
opcode_counter_t block_position)
{
if (likely (!interp_mem_stats_enabled))
{
return;
}
const uint32_t indentation = JERRY_MIN (interp_mem_stats_print_indentation,
INTERP_MEM_PRINT_INDENTATION_MAX);
char indent_prefix[INTERP_MEM_PRINT_INDENTATION_MAX + 2];
memset (indent_prefix, ' ', sizeof (indent_prefix));
indent_prefix [indentation] = '|';
indent_prefix [indentation + 1] = '\0';
mem_heap_stats_t heap_stats_context_exit;
mem_pools_stats_t pools_stats_context_exit;
interp_mem_get_stats (&heap_stats_context_exit,
&pools_stats_context_exit,
false, true);
int_data_p->context_peak_allocated_heap_bytes -= JERRY_MAX (int_data_p->heap_stats_context_enter.allocated_bytes,
heap_stats_context_exit.allocated_bytes);
int_data_p->context_peak_waste_heap_bytes -= JERRY_MAX (int_data_p->heap_stats_context_enter.waste_bytes,
heap_stats_context_exit.waste_bytes);
int_data_p->context_peak_pools_count -= JERRY_MAX (int_data_p->pools_stats_context_enter.pools_count,
pools_stats_context_exit.pools_count);
int_data_p->context_peak_allocated_pool_chunks -= JERRY_MAX (int_data_p->pools_stats_context_enter.allocated_chunks,
pools_stats_context_exit.allocated_chunks);
printf ("%sAllocated heap bytes in the context: %5u -> %5u (%+5d, local %5u, peak %5u)\n",
indent_prefix,
(uint32_t) int_data_p->heap_stats_context_enter.allocated_bytes,
(uint32_t) heap_stats_context_exit.allocated_bytes,
(uint32_t) (heap_stats_context_exit.allocated_bytes - int_data_p->heap_stats_context_enter.allocated_bytes),
(uint32_t) int_data_p->context_peak_allocated_heap_bytes,
(uint32_t) heap_stats_context_exit.global_peak_allocated_bytes);
printf ("%sWaste heap bytes in the context: %5u -> %5u (%+5d, local %5u, peak %5u)\n",
indent_prefix,
(uint32_t) int_data_p->heap_stats_context_enter.waste_bytes,
(uint32_t) heap_stats_context_exit.waste_bytes,
(uint32_t) (heap_stats_context_exit.waste_bytes - int_data_p->heap_stats_context_enter.waste_bytes),
(uint32_t) int_data_p->context_peak_waste_heap_bytes,
(uint32_t) heap_stats_context_exit.global_peak_waste_bytes);
printf ("%sPools count in the context: %5u -> %5u (%+5d, local %5u, peak %5u)\n",
indent_prefix,
(uint32_t) int_data_p->pools_stats_context_enter.pools_count,
(uint32_t) pools_stats_context_exit.pools_count,
(uint32_t) (pools_stats_context_exit.pools_count - int_data_p->pools_stats_context_enter.pools_count),
(uint32_t) int_data_p->context_peak_pools_count,
(uint32_t) pools_stats_context_exit.global_peak_pools_count);
printf ("%sAllocated pool chunks in the context: %5u -> %5u (%+5d, local %5u, peak %5u)\n",
indent_prefix,
(uint32_t) int_data_p->pools_stats_context_enter.allocated_chunks,
(uint32_t) pools_stats_context_exit.allocated_chunks,
(uint32_t) (pools_stats_context_exit.allocated_chunks -
int_data_p->pools_stats_context_enter.allocated_chunks),
(uint32_t) int_data_p->context_peak_allocated_pool_chunks,
(uint32_t) pools_stats_context_exit.global_peak_allocated_chunks);
printf ("\n%s--- End of interpretation of a block at position %u ---\n\n",
indent_prefix, (uint32_t) block_position);
}
static void
interp_mem_stats_opcode_enter (opcode_counter_t opcode_position,
mem_heap_stats_t *out_heap_stats_p,
mem_pools_stats_t *out_pools_stats_p)
{
if (likely (!interp_mem_stats_enabled))
{
return;
}
const uint32_t indentation = JERRY_MIN (interp_mem_stats_print_indentation,
INTERP_MEM_PRINT_INDENTATION_MAX);
char indent_prefix[INTERP_MEM_PRINT_INDENTATION_MAX + 2];
memset (indent_prefix, ' ', sizeof (indent_prefix));
indent_prefix [indentation] = '|';
indent_prefix [indentation + 1] = '\0';
interp_mem_get_stats (out_heap_stats_p,
out_pools_stats_p,
true, false);
opcode_t opcode = read_opcode (opcode_position);
printf ("%s-- Opcode: %s (position %u) --\n",
indent_prefix, __op_names [opcode.op_idx], (uint32_t) opcode_position);
interp_mem_stats_print_indentation += INTERP_MEM_PRINT_INDENTATION_STEP;
}
static void
interp_mem_stats_opcode_exit (int_data_t *int_data_p,
opcode_counter_t opcode_position,
mem_heap_stats_t *heap_stats_before_p,
mem_pools_stats_t *pools_stats_before_p)
{
if (likely (!interp_mem_stats_enabled))
{
return;
}
interp_mem_stats_print_indentation -= INTERP_MEM_PRINT_INDENTATION_STEP;
const uint32_t indentation = JERRY_MIN (interp_mem_stats_print_indentation,
INTERP_MEM_PRINT_INDENTATION_MAX);
char indent_prefix[INTERP_MEM_PRINT_INDENTATION_MAX + 2];
memset (indent_prefix, ' ', sizeof (indent_prefix));
indent_prefix [indentation] = '|';
indent_prefix [indentation + 1] = '\0';
mem_heap_stats_t heap_stats_after;
mem_pools_stats_t pools_stats_after;
interp_mem_get_stats (&heap_stats_after,
&pools_stats_after,
false, true);
int_data_p->context_peak_allocated_heap_bytes = JERRY_MAX (int_data_p->context_peak_allocated_heap_bytes,
heap_stats_after.allocated_bytes);
int_data_p->context_peak_waste_heap_bytes = JERRY_MAX (int_data_p->context_peak_waste_heap_bytes,
heap_stats_after.waste_bytes);
int_data_p->context_peak_pools_count = JERRY_MAX (int_data_p->context_peak_pools_count,
pools_stats_after.pools_count);
int_data_p->context_peak_allocated_pool_chunks = JERRY_MAX (int_data_p->context_peak_allocated_pool_chunks,
pools_stats_after.allocated_chunks);
opcode_t opcode = read_opcode (opcode_position);
printf ("%s Allocated heap bytes: %5u -> %5u (%+5d, local %5u, peak %5u)\n",
indent_prefix,
(uint32_t) heap_stats_before_p->allocated_bytes,
(uint32_t) heap_stats_after.allocated_bytes,
(uint32_t) (heap_stats_after.allocated_bytes - heap_stats_before_p->allocated_bytes),
(uint32_t) (heap_stats_after.peak_allocated_bytes - JERRY_MAX (heap_stats_before_p->allocated_bytes,
heap_stats_after.allocated_bytes)),
(uint32_t) heap_stats_after.global_peak_allocated_bytes);
if (heap_stats_before_p->waste_bytes != heap_stats_after.waste_bytes)
{
printf ("%s Waste heap bytes: %5u -> %5u (%+5d, local %5u, peak %5u)\n",
indent_prefix,
(uint32_t) heap_stats_before_p->waste_bytes,
(uint32_t) heap_stats_after.waste_bytes,
(uint32_t) (heap_stats_after.waste_bytes - heap_stats_before_p->waste_bytes),
(uint32_t) (heap_stats_after.peak_waste_bytes - JERRY_MAX (heap_stats_before_p->waste_bytes,
heap_stats_after.waste_bytes)),
(uint32_t) heap_stats_after.global_peak_waste_bytes);
}
if (pools_stats_before_p->pools_count != pools_stats_after.pools_count)
{
printf ("%s Pools: %5u -> %5u (%+5d, local %5u, peak %5u)\n",
indent_prefix,
(uint32_t) pools_stats_before_p->pools_count,
(uint32_t) pools_stats_after.pools_count,
(uint32_t) (pools_stats_after.pools_count - pools_stats_before_p->pools_count),
(uint32_t) (pools_stats_after.peak_pools_count - JERRY_MAX (pools_stats_before_p->pools_count,
pools_stats_after.pools_count)),
(uint32_t) pools_stats_after.global_peak_pools_count);
}
if (pools_stats_before_p->allocated_chunks != pools_stats_after.allocated_chunks)
{
printf ("%s Allocated pool chunks: %5u -> %5u (%+5d, local %5u, peak %5u)\n",
indent_prefix,
(uint32_t) pools_stats_before_p->allocated_chunks,
(uint32_t) pools_stats_after.allocated_chunks,
(uint32_t) (pools_stats_after.allocated_chunks - pools_stats_before_p->allocated_chunks),
(uint32_t) (pools_stats_after.peak_allocated_chunks - JERRY_MAX (pools_stats_before_p->allocated_chunks,
pools_stats_after.allocated_chunks)),
(uint32_t) pools_stats_after.global_peak_allocated_chunks);
}
printf ("%s-- End of execution of opcode %s (position %u) --\n\n",
indent_prefix, __op_names [opcode.op_idx], opcode_position);
}
#endif /* MEM_STATS */
/**
* Initialize interpreter.
*/
void
init_int (const opcode_t *program_p, /**< pointer to byte-code program */
bool dump_mem_stats) /** dump per-opcode memory usage change statistics */
{
#ifdef MEM_STATS
interp_mem_stats_enabled = dump_mem_stats;
#else /* MEM_STATS */
JERRY_ASSERT (!dump_mem_stats);
#endif /* !MEM_STATS */
JERRY_ASSERT (__program == NULL);
__program = program_p;
} /* init_int */
jerry_completion_code_t
run_int (void)
{
JERRY_ASSERT (__program != NULL);
#ifdef MEM_STATS
interp_mem_stats_print_legend ();
#endif /* MEM_STATS */
bool is_strict = false;
opcode_counter_t start_pos = 0;
opcode_t first_opcode = read_opcode (start_pos);
if (first_opcode.op_idx == __op__idx_meta
&& first_opcode.data.meta.type == OPCODE_META_TYPE_STRICT_CODE)
{
is_strict = true;
start_pos++;
}
ecma_init ();
ecma_object_t *glob_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_GLOBAL);
ecma_object_t *lex_env_p = ecma_op_create_global_environment (glob_obj_p);
ecma_value_t this_binding_value = ecma_make_object_value (glob_obj_p);
ecma_completion_value_t completion = run_int_from_pos (start_pos,
this_binding_value,
lex_env_p,
is_strict,
false);
jerry_completion_code_t ret_code;
if (ecma_is_completion_value_exit (completion))
{
if (ecma_is_value_true (ecma_get_completion_value_value (completion)))
{
ret_code = JERRY_COMPLETION_CODE_OK;
}
else
{
ret_code = JERRY_COMPLETION_CODE_FAILED_ASSERTION_IN_SCRIPT;
}
}
else
{
JERRY_ASSERT (ecma_is_completion_value_throw (completion));
ret_code = JERRY_COMPLETION_CODE_UNHANDLED_EXCEPTION;
}
ecma_deref_object (glob_obj_p);
ecma_deref_object (lex_env_p);
ecma_finalize ();
return ret_code;
}
ecma_completion_value_t
run_int_loop (int_data_t *int_data)
{
ecma_completion_value_t completion;
#ifdef MEM_STATS
mem_heap_stats_t heap_stats_before;
mem_pools_stats_t pools_stats_before;
memset (&heap_stats_before, 0, sizeof (heap_stats_before));
memset (&pools_stats_before, 0, sizeof (pools_stats_before));
#endif /* MEM_STATS */
while (true)
{
do
{
const opcode_t *curr = &__program[int_data->pos];
#ifdef MEM_STATS
const opcode_counter_t opcode_pos = int_data->pos;
interp_mem_stats_opcode_enter (opcode_pos,
&heap_stats_before,
&pools_stats_before);
#endif /* MEM_STATS */
completion = __opfuncs[curr->op_idx] (*curr, int_data);
#ifdef MEM_STATS
interp_mem_stats_opcode_exit (int_data,
opcode_pos,
&heap_stats_before,
&pools_stats_before);
#endif /* MEM_STATS */
JERRY_ASSERT (!ecma_is_completion_value_normal (completion)
|| ecma_is_completion_value_empty (completion));
}
while (ecma_is_completion_value_normal (completion));
if (ecma_is_completion_value_break (completion)
|| ecma_is_completion_value_continue (completion))
{
JERRY_UNIMPLEMENTED ("break and continue on labels are not supported.");
continue;
}
if (ecma_is_completion_value_meta (completion))
{
completion = ecma_make_empty_completion_value ();
}
return completion;
}
}
ecma_completion_value_t
run_int_from_pos (opcode_counter_t start_pos,
const ecma_value_t& this_binding_value,
ecma_object_t *lex_env_p,
bool is_strict,
bool is_eval_code)
{
ecma_completion_value_t completion;
const opcode_t *curr = &__program[start_pos];
JERRY_ASSERT (curr->op_idx == __op__idx_reg_var_decl);
const idx_t min_reg_num = curr->data.reg_var_decl.min;
const idx_t max_reg_num = curr->data.reg_var_decl.max;
JERRY_ASSERT (max_reg_num >= min_reg_num);
const int32_t regs_num = max_reg_num - min_reg_num + 1;
MEM_DEFINE_LOCAL_ARRAY (regs, regs_num, ecma_value_t);
int_data_t int_data;
int_data.pos = (opcode_counter_t) (start_pos + 1);
int_data.this_binding = this_binding_value;
int_data.lex_env_p = lex_env_p;
int_data.is_strict = is_strict;
int_data.is_eval_code = is_eval_code;
int_data.min_reg_num = min_reg_num;
int_data.max_reg_num = max_reg_num;
int_data.tmp_num_p = ecma_alloc_number ();
ecma_stack_add_frame (&int_data.stack_frame, regs, regs_num);
#ifdef MEM_STATS
interp_mem_stats_context_enter (&int_data, start_pos);
#endif /* MEM_STATS */
completion = run_int_loop (&int_data);
JERRY_ASSERT (ecma_is_completion_value_normal (completion)
|| ecma_is_completion_value_throw (completion)
|| ecma_is_completion_value_return (completion)
|| ecma_is_completion_value_exit (completion));
ecma_stack_free_frame (&int_data.stack_frame);
ecma_dealloc_number (int_data.tmp_num_p);
#ifdef MEM_STATS
interp_mem_stats_context_exit (&int_data, start_pos);
#endif /* MEM_STATS */
MEM_FINALIZE_LOCAL_ARRAY (regs);
return completion;
}
/**
* Get specified opcode from the program.
*/
opcode_t
read_opcode (opcode_counter_t counter) /**< opcode counter */
{
return __program[ counter ];
} /* read_opcode */
+35
View File
@@ -0,0 +1,35 @@
/* Copyright 2014-2015 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.
*/
#ifndef VM_H
#define VM_H
#include "ecma-globals.h"
#include "jrt.h"
#include "opcodes.h"
void init_int (const opcode_t* program_p, bool dump_mem_stats);
jerry_completion_code_t run_int (void);
ecma_completion_value_t run_int_loop (int_data_t *int_data);
ecma_completion_value_t run_int_from_pos (opcode_counter_t start_pos,
const ecma_value_t& this_binding_value,
ecma_object_t *lex_env_p,
bool is_strict,
bool is_eval_code);
opcode_t read_opcode (opcode_counter_t counter);
#endif /* VM_H */