Compact Byte Code parser and executor for Jerry.

JerryScript-DCO-1.0-Signed-off-by: László Langó llango.u-szeged@partner.samsung.com
JerryScript-DCO-1.0-Signed-off-by: Tamas Gergely tgergely.u-szeged@partner.samsung.com
JerryScript-DCO-1.0-Signed-off-by: Zsolt Borbély zsborbely.u-szeged@partner.samsung.com
JerryScript-DCO-1.0-Signed-off-by: Roland Takacs rtakacs.u-szeged@partner.samsung.com
JerryScript-DCO-1.0-Signed-off-by: István Kádár ikadar@inf.u-szeged.hu
JerryScript-DCO-1.0-Signed-off-by: Zoltan Herczeg zherczeg.u-szeged@partner.samsung.com
This commit is contained in:
Zoltan Herczeg
2016-02-05 00:10:10 -08:00
parent db6caf3c48
commit 4d2dd22ced
92 changed files with 17184 additions and 20276 deletions
-217
View File
@@ -1,217 +0,0 @@
/* 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 instruction's position changes by adding specified offset
* if argument evaluates to true.
*/
ecma_completion_value_t
opfunc_is_true_jmp_down (vm_instr_t instr, /**< instruction */
vm_frame_ctx_t *frame_ctx_p) /**< interpreter context */
{
const vm_idx_t cond_var_idx = instr.data.is_true_jmp_down.value;
const vm_instr_counter_t offset = vm_calc_instr_counter_from_idx_idx (instr.data.is_true_jmp_down.oc_idx_1,
instr.data.is_true_jmp_down.oc_idx_2);
ecma_completion_value_t ret_value = ecma_make_empty_completion_value ();
ECMA_TRY_CATCH (cond_value, get_variable_value (frame_ctx_p, 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 ((uint32_t) frame_ctx_p->pos + offset < MAX_OPCODES);
frame_ctx_p->pos = (vm_instr_counter_t) (frame_ctx_p->pos + offset);
}
else
{
frame_ctx_p->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 (vm_instr_t instr, /**< instruction */
vm_frame_ctx_t *frame_ctx_p) /**< interpreter context */
{
const vm_idx_t cond_var_idx = instr.data.is_true_jmp_up.value;
const vm_instr_counter_t offset = vm_calc_instr_counter_from_idx_idx (instr.data.is_true_jmp_up.oc_idx_1,
instr.data.is_true_jmp_up.oc_idx_2);
ecma_completion_value_t ret_value = ecma_make_empty_completion_value ();
ECMA_TRY_CATCH (cond_value, get_variable_value (frame_ctx_p, 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 ((uint32_t) frame_ctx_p->pos >= offset);
frame_ctx_p->pos = (vm_instr_counter_t) (frame_ctx_p->pos - offset);
}
else
{
frame_ctx_p->pos++;
}
ret_value = ecma_make_empty_completion_value ();
ECMA_FINALIZE (cond_value);
return ret_value;
}
/**
* 'Jump down if false' opcode handler.
*
* Note:
* current instruction's position changes by adding specified offset
* if argument evaluates to false.
*/
ecma_completion_value_t
opfunc_is_false_jmp_down (vm_instr_t instr, /**< instruction */
vm_frame_ctx_t *frame_ctx_p) /**< interpreter context */
{
const vm_idx_t cond_var_idx = instr.data.is_false_jmp_down.value;
const vm_instr_counter_t offset = vm_calc_instr_counter_from_idx_idx (instr.data.is_false_jmp_down.oc_idx_1,
instr.data.is_false_jmp_down.oc_idx_2);
ecma_completion_value_t ret_value = ecma_make_empty_completion_value ();
ECMA_TRY_CATCH (cond_value, get_variable_value (frame_ctx_p, 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 ((uint32_t) frame_ctx_p->pos + offset < MAX_OPCODES);
frame_ctx_p->pos = (vm_instr_counter_t) (frame_ctx_p->pos + offset);
}
else
{
frame_ctx_p->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 (vm_instr_t instr, /**< instruction */
vm_frame_ctx_t *frame_ctx_p) /**< interpreter context */
{
const vm_idx_t cond_var_idx = instr.data.is_false_jmp_up.value;
const vm_instr_counter_t offset = vm_calc_instr_counter_from_idx_idx (instr.data.is_false_jmp_up.oc_idx_1,
instr.data.is_false_jmp_up.oc_idx_2);
ecma_completion_value_t ret_value = ecma_make_empty_completion_value ();
ECMA_TRY_CATCH (cond_value, get_variable_value (frame_ctx_p, 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 ((uint32_t) frame_ctx_p->pos >= offset);
frame_ctx_p->pos = (vm_instr_counter_t) (frame_ctx_p->pos - offset);
}
else
{
frame_ctx_p->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 instruction position
*/
ecma_completion_value_t
opfunc_jmp_down (vm_instr_t instr, /**< instruction */
vm_frame_ctx_t *frame_ctx_p) /**< interpreter context */
{
const vm_instr_counter_t offset = vm_calc_instr_counter_from_idx_idx (instr.data.jmp_down.oc_idx_1,
instr.data.jmp_down.oc_idx_2);
JERRY_ASSERT (((uint32_t) frame_ctx_p->pos + offset < MAX_OPCODES));
frame_ctx_p->pos = (vm_instr_counter_t) (frame_ctx_p->pos + offset);
return ecma_make_empty_completion_value ();
}
/**
* 'Jump up' opcode handler.
*
* Note:
* the opcode changes substracts specified value from current instruction position
*/
ecma_completion_value_t
opfunc_jmp_up (vm_instr_t instr, /**< instruction */
vm_frame_ctx_t *frame_ctx_p) /**< interpreter context */
{
const vm_instr_counter_t offset = vm_calc_instr_counter_from_idx_idx (instr.data.jmp_up.oc_idx_1,
instr.data.jmp_up.oc_idx_2);
JERRY_ASSERT ((uint32_t) frame_ctx_p->pos >= offset);
frame_ctx_p->pos = (vm_instr_counter_t) (frame_ctx_p->pos - offset);
return ecma_make_empty_completion_value ();
}
/**
* 'Break or continue jump' opcode handler.
*
* Note:
* the opcode returns break-continue completion value with jump target
*/
ecma_completion_value_t
opfunc_jmp_break_continue (vm_instr_t instr, /**< instruction */
vm_frame_ctx_t *frame_ctx_p) /**< interpreter context */
{
vm_instr_counter_t target = frame_ctx_p->pos;
target = (vm_instr_counter_t) (target + vm_calc_instr_counter_from_idx_idx (instr.data.jmp_down.oc_idx_1,
instr.data.jmp_down.oc_idx_2));
return ecma_make_jump_completion_value (target);
} /* opfunc_jmp_break_continue */
+41 -215
View File
@@ -1,4 +1,5 @@
/* Copyright 2014-2015 Samsung Electronics Co., Ltd.
/* Copyright 2014-2016 Samsung Electronics Co., Ltd.
* Copyright 2015-2016 University of Szeged.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -13,22 +14,20 @@
* limitations under the License.
*/
#include "opcodes.h"
#include "opcodes-ecma-support.h"
#include "ecma-alloc.h"
#include "ecma-conversion.h"
#include "ecma-helpers.h"
#include "ecma-number-arithmetic.h"
#include "ecma-try-catch-macro.h"
#include "opcodes.h"
#include "jrt-libc-includes.h"
/**
* Number arithmetic operations.
/** \addtogroup vm Virtual machine
* @{
*
* \addtogroup vm_opcodes Opcodes
* @{
*/
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.
@@ -41,52 +40,48 @@ typedef enum
* @return completion value
* Returned value must be freed with ecma_free_completion_value
*/
static ecma_completion_value_t
do_number_arithmetic (vm_frame_ctx_t *frame_ctx_p, /**< interpreter context */
vm_idx_t dst_var_idx, /**< destination variable identifier */
number_arithmetic_op op, /**< number arithmetic operation */
ecma_completion_value_t
do_number_arithmetic (number_arithmetic_op op, /**< number arithmetic operation */
ecma_value_t left_value, /**< left value */
ecma_value_t right_value) /** right value */
ecma_value_t 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 = frame_ctx_p->tmp_num_p;
ecma_number_t *res_p = ecma_alloc_number ();
switch (op)
{
case number_arithmetic_addition:
case NUMBER_ARITHMETIC_ADDITION:
{
*res_p = ecma_number_add (num_left, num_right);
break;
}
case number_arithmetic_substraction:
case NUMBER_ARITHMETIC_SUBSTRACTION:
{
*res_p = ecma_number_substract (num_left, num_right);
break;
}
case number_arithmetic_multiplication:
case NUMBER_ARITHMETIC_MULTIPLICATION:
{
*res_p = ecma_number_multiply (num_left, num_right);
break;
}
case number_arithmetic_division:
case NUMBER_ARITHMETIC_DIVISION:
{
*res_p = ecma_number_divide (num_left, num_right);
break;
}
case number_arithmetic_remainder:
case NUMBER_ARITHMETIC_REMAINDER:
{
*res_p = ecma_op_number_remainder (num_left, num_right);
break;
}
}
ret_value = set_variable_value (frame_ctx_p, frame_ctx_p->pos,
dst_var_idx,
ecma_make_number_value (res_p));
ret_value = ecma_make_completion_value (ECMA_COMPLETION_TYPE_NORMAL, ecma_make_number_value (res_p));
ECMA_OP_TO_NUMBER_FINALIZE (num_right);
ECMA_OP_TO_NUMBER_FINALIZE (num_left);
@@ -103,17 +98,11 @@ do_number_arithmetic (vm_frame_ctx_t *frame_ctx_p, /**< interpreter context */
* Returned value must be freed with ecma_free_completion_value
*/
ecma_completion_value_t
opfunc_addition (vm_instr_t instr, /**< instruction */
vm_frame_ctx_t *frame_ctx_p) /**< interpreter context */
opfunc_addition (ecma_value_t left_value, /**< left value */
ecma_value_t right_value) /**< right value */
{
const vm_idx_t dst_var_idx = instr.data.addition.dst;
const vm_idx_t left_var_idx = instr.data.addition.var_left;
const vm_idx_t right_var_idx = instr.data.addition.var_right;
ecma_completion_value_t ret_value = ecma_make_empty_completion_value ();
ECMA_TRY_CATCH (left_value, get_variable_value (frame_ctx_p, left_var_idx, false), ret_value);
ECMA_TRY_CATCH (right_value, get_variable_value (frame_ctx_p, right_var_idx, false), ret_value);
ECMA_TRY_CATCH (prim_left_value,
ecma_op_to_primitive (left_value,
ECMA_PREFERRED_TYPE_NO),
@@ -134,172 +123,24 @@ opfunc_addition (vm_instr_t instr, /**< instruction */
ecma_string_t *concat_str_p = ecma_concat_ecma_strings (string1_p, string2_p);
ret_value = set_variable_value (frame_ctx_p, frame_ctx_p->pos, dst_var_idx, ecma_make_string_value (concat_str_p));
ecma_deref_ecma_string (concat_str_p);
ret_value = ecma_make_completion_value (ECMA_COMPLETION_TYPE_NORMAL, ecma_make_string_value (concat_str_p));
ECMA_FINALIZE (str_right_value);
ECMA_FINALIZE (str_left_value);
}
else
{
ret_value = do_number_arithmetic (frame_ctx_p,
dst_var_idx,
number_arithmetic_addition,
prim_left_value,
prim_right_value);
ret_value = do_number_arithmetic (NUMBER_ARITHMETIC_ADDITION,
left_value,
right_value);
}
ECMA_FINALIZE (prim_right_value);
ECMA_FINALIZE (prim_left_value);
ECMA_FINALIZE (right_value);
ECMA_FINALIZE (left_value);
frame_ctx_p->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 (vm_instr_t instr, /**< instruction */
vm_frame_ctx_t *frame_ctx_p) /**< interpreter context */
{
const vm_idx_t dst_var_idx = instr.data.substraction.dst;
const vm_idx_t left_var_idx = instr.data.substraction.var_left;
const vm_idx_t right_var_idx = instr.data.substraction.var_right;
ecma_completion_value_t ret_value = ecma_make_empty_completion_value ();
ECMA_TRY_CATCH (left_value, get_variable_value (frame_ctx_p, left_var_idx, false), ret_value);
ECMA_TRY_CATCH (right_value, get_variable_value (frame_ctx_p, right_var_idx, false), ret_value);
ret_value = do_number_arithmetic (frame_ctx_p,
dst_var_idx,
number_arithmetic_substraction,
left_value,
right_value);
ECMA_FINALIZE (right_value);
ECMA_FINALIZE (left_value);
frame_ctx_p->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 (vm_instr_t instr, /**< instruction */
vm_frame_ctx_t *frame_ctx_p) /**< interpreter context */
{
const vm_idx_t dst_var_idx = instr.data.multiplication.dst;
const vm_idx_t left_var_idx = instr.data.multiplication.var_left;
const vm_idx_t right_var_idx = instr.data.multiplication.var_right;
ecma_completion_value_t ret_value = ecma_make_empty_completion_value ();
ECMA_TRY_CATCH (left_value, get_variable_value (frame_ctx_p, left_var_idx, false), ret_value);
ECMA_TRY_CATCH (right_value, get_variable_value (frame_ctx_p, right_var_idx, false), ret_value);
ret_value = do_number_arithmetic (frame_ctx_p,
dst_var_idx,
number_arithmetic_multiplication,
left_value,
right_value);
ECMA_FINALIZE (right_value);
ECMA_FINALIZE (left_value);
frame_ctx_p->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 (vm_instr_t instr, /**< instruction */
vm_frame_ctx_t *frame_ctx_p) /**< interpreter context */
{
const vm_idx_t dst_var_idx = instr.data.division.dst;
const vm_idx_t left_var_idx = instr.data.division.var_left;
const vm_idx_t right_var_idx = instr.data.division.var_right;
ecma_completion_value_t ret_value = ecma_make_empty_completion_value ();
ECMA_TRY_CATCH (left_value, get_variable_value (frame_ctx_p, left_var_idx, false), ret_value);
ECMA_TRY_CATCH (right_value, get_variable_value (frame_ctx_p, right_var_idx, false), ret_value);
ret_value = do_number_arithmetic (frame_ctx_p,
dst_var_idx,
number_arithmetic_division,
left_value,
right_value);
ECMA_FINALIZE (right_value);
ECMA_FINALIZE (left_value);
frame_ctx_p->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 (vm_instr_t instr, /**< instruction */
vm_frame_ctx_t *frame_ctx_p) /**< interpreter context */
{
const vm_idx_t dst_var_idx = instr.data.remainder.dst;
const vm_idx_t left_var_idx = instr.data.remainder.var_left;
const vm_idx_t right_var_idx = instr.data.remainder.var_right;
ecma_completion_value_t ret_value = ecma_make_empty_completion_value ();
ECMA_TRY_CATCH (left_value, get_variable_value (frame_ctx_p, left_var_idx, false), ret_value);
ECMA_TRY_CATCH (right_value, get_variable_value (frame_ctx_p, right_var_idx, false), ret_value);
ret_value = do_number_arithmetic (frame_ctx_p,
dst_var_idx,
number_arithmetic_remainder,
left_value,
right_value);
ECMA_FINALIZE (right_value);
ECMA_FINALIZE (left_value);
frame_ctx_p->pos++;
return ret_value;
} /* opfunc_remainder */
/**
* 'Unary "+"' opcode handler.
*
@@ -309,30 +150,20 @@ opfunc_remainder (vm_instr_t instr, /**< instruction */
* Returned value must be freed with ecma_free_completion_value
*/
ecma_completion_value_t
opfunc_unary_plus (vm_instr_t instr, /**< instruction */
vm_frame_ctx_t *frame_ctx_p) /**< interpreter context */
opfunc_unary_plus (ecma_value_t left_value) /**< left value */
{
const vm_idx_t dst_var_idx = instr.data.remainder.dst;
const vm_idx_t var_idx = instr.data.remainder.var_left;
ecma_completion_value_t ret_value = ecma_make_empty_completion_value ();
ECMA_TRY_CATCH (var_value, get_variable_value (frame_ctx_p, var_idx, false), ret_value);
ECMA_OP_TO_NUMBER_TRY_CATCH (num_var_value,
var_value,
left_value,
ret_value);
ecma_number_t *tmp_p = frame_ctx_p->tmp_num_p;
ecma_number_t *tmp_p = ecma_alloc_number ();
*tmp_p = num_var_value;
ret_value = set_variable_value (frame_ctx_p, frame_ctx_p->pos,
dst_var_idx,
ecma_make_number_value (tmp_p));
ret_value = ecma_make_completion_value (ECMA_COMPLETION_TYPE_NORMAL, ecma_make_number_value (tmp_p));
ECMA_OP_TO_NUMBER_FINALIZE (num_var_value);
ECMA_FINALIZE (var_value);
frame_ctx_p->pos++;
return ret_value;
} /* opfunc_unary_plus */
@@ -346,30 +177,25 @@ opfunc_unary_plus (vm_instr_t instr, /**< instruction */
* Returned value must be freed with ecma_free_completion_value
*/
ecma_completion_value_t
opfunc_unary_minus (vm_instr_t instr, /**< instruction */
vm_frame_ctx_t *frame_ctx_p) /**< interpreter context */
opfunc_unary_minus (ecma_value_t left_value) /**< left value */
{
const vm_idx_t dst_var_idx = instr.data.remainder.dst;
const vm_idx_t var_idx = instr.data.remainder.var_left;
ecma_completion_value_t ret_value = ecma_make_empty_completion_value ();
ECMA_TRY_CATCH (var_value, get_variable_value (frame_ctx_p, var_idx, false), ret_value);
ECMA_OP_TO_NUMBER_TRY_CATCH (num_var_value,
var_value,
left_value,
ret_value);
ecma_number_t *tmp_p = frame_ctx_p->tmp_num_p;
ecma_number_t *tmp_p = ecma_alloc_number ();
*tmp_p = ecma_number_negate (num_var_value);
ret_value = set_variable_value (frame_ctx_p, frame_ctx_p->pos,
dst_var_idx,
ecma_make_number_value (tmp_p));
ret_value = ecma_make_completion_value (ECMA_COMPLETION_TYPE_NORMAL, ecma_make_number_value (tmp_p));
ECMA_OP_TO_NUMBER_FINALIZE (num_var_value);
ECMA_FINALIZE (var_value);
frame_ctx_p->pos++;
return ret_value;
} /* opfunc_unary_minus */
/**
* @}
* @}
*/
+24 -269
View File
@@ -1,4 +1,5 @@
/* Copyright 2014-2015 Samsung Electronics Co., Ltd.
/* Copyright 2014-2016 Samsung Electronics Co., Ltd.
* Copyright 2015-2016 University of Szeged.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -13,22 +14,18 @@
* limitations under the License.
*/
#include "ecma-alloc.h"
#include "ecma-conversion.h"
#include "ecma-helpers.h"
#include "ecma-try-catch-macro.h"
#include "opcodes.h"
#include "opcodes-ecma-support.h"
/**
* Number bitwise logic operations.
/** \addtogroup vm Virtual machine
* @{
*
* \addtogroup vm_opcodes Opcodes
* @{
*/
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.
@@ -41,10 +38,8 @@ typedef enum
* @return completion value
* Returned value must be freed with ecma_free_completion_value
*/
static ecma_completion_value_t
do_number_bitwise_logic (vm_frame_ctx_t *frame_ctx_p, /**< interpreter context */
vm_idx_t dst_var_idx, /**< destination variable identifier */
number_bitwise_logic_op op, /**< number bitwise logic operation */
ecma_completion_value_t
do_number_bitwise_logic (number_bitwise_logic_op op, /**< number bitwise logic operation */
ecma_value_t left_value, /**< left value */
ecma_value_t right_value) /** right value */
{
@@ -53,56 +48,53 @@ do_number_bitwise_logic (vm_frame_ctx_t *frame_ctx_p, /**< interpreter context *
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 = frame_ctx_p->tmp_num_p;
ecma_number_t* res_p = ecma_alloc_number ();
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:
case NUMBER_BITWISE_LOGIC_AND:
{
*res_p = ecma_int32_to_number ((int32_t) (left_uint32 & right_uint32));
break;
}
case number_bitwise_logic_or:
case NUMBER_BITWISE_LOGIC_OR:
{
*res_p = ecma_int32_to_number ((int32_t) (left_uint32 | right_uint32));
break;
}
case number_bitwise_logic_xor:
case NUMBER_BITWISE_LOGIC_XOR:
{
*res_p = ecma_int32_to_number ((int32_t) (left_uint32 ^ right_uint32));
break;
}
case number_bitwise_shift_left:
case NUMBER_BITWISE_SHIFT_LEFT:
{
*res_p = ecma_int32_to_number (left_int32 << (right_uint32 & 0x1F));
break;
}
case number_bitwise_shift_right:
case NUMBER_BITWISE_SHIFT_RIGHT:
{
*res_p = ecma_int32_to_number (left_int32 >> (right_uint32 & 0x1F));
break;
}
case number_bitwise_shift_uright:
case NUMBER_BITWISE_SHIFT_URIGHT:
{
*res_p = ecma_uint32_to_number (left_uint32 >> (right_uint32 & 0x1F));
break;
}
case number_bitwise_not:
case NUMBER_BITWISE_NOT:
{
*res_p = ecma_int32_to_number ((int32_t) ~right_uint32);
break;
}
}
ret_value = set_variable_value (frame_ctx_p, frame_ctx_p->pos,
dst_var_idx,
ecma_make_number_value (res_p));
ret_value = ecma_make_normal_completion_value (ecma_make_number_value (res_p));
ECMA_OP_TO_NUMBER_FINALIZE (num_right);
ECMA_OP_TO_NUMBER_FINALIZE (num_left);
@@ -111,243 +103,6 @@ do_number_bitwise_logic (vm_frame_ctx_t *frame_ctx_p, /**< interpreter context *
} /* 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 (vm_instr_t instr, /**< instruction */
vm_frame_ctx_t *frame_ctx_p) /**< interpreter context */
{
const vm_idx_t dst_var_idx = instr.data.b_and.dst;
const vm_idx_t left_var_idx = instr.data.b_and.var_left;
const vm_idx_t right_var_idx = instr.data.b_and.var_right;
ecma_completion_value_t ret_value = ecma_make_empty_completion_value ();
ECMA_TRY_CATCH (left_value, get_variable_value (frame_ctx_p, left_var_idx, false), ret_value);
ECMA_TRY_CATCH (right_value, get_variable_value (frame_ctx_p, right_var_idx, false), ret_value);
ret_value = do_number_bitwise_logic (frame_ctx_p,
dst_var_idx,
number_bitwise_logic_and,
left_value,
right_value);
ECMA_FINALIZE (right_value);
ECMA_FINALIZE (left_value);
frame_ctx_p->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 (vm_instr_t instr, /**< instruction */
vm_frame_ctx_t *frame_ctx_p) /**< interpreter context */
{
const vm_idx_t dst_var_idx = instr.data.b_or.dst;
const vm_idx_t left_var_idx = instr.data.b_or.var_left;
const vm_idx_t right_var_idx = instr.data.b_or.var_right;
ecma_completion_value_t ret_value = ecma_make_empty_completion_value ();
ECMA_TRY_CATCH (left_value, get_variable_value (frame_ctx_p, left_var_idx, false), ret_value);
ECMA_TRY_CATCH (right_value, get_variable_value (frame_ctx_p, right_var_idx, false), ret_value);
ret_value = do_number_bitwise_logic (frame_ctx_p,
dst_var_idx,
number_bitwise_logic_or,
left_value,
right_value);
ECMA_FINALIZE (right_value);
ECMA_FINALIZE (left_value);
frame_ctx_p->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 (vm_instr_t instr, /**< instruction */
vm_frame_ctx_t *frame_ctx_p) /**< interpreter context */
{
const vm_idx_t dst_var_idx = instr.data.b_xor.dst;
const vm_idx_t left_var_idx = instr.data.b_xor.var_left;
const vm_idx_t right_var_idx = instr.data.b_xor.var_right;
ecma_completion_value_t ret_value = ecma_make_empty_completion_value ();
ECMA_TRY_CATCH (left_value, get_variable_value (frame_ctx_p, left_var_idx, false), ret_value);
ECMA_TRY_CATCH (right_value, get_variable_value (frame_ctx_p, right_var_idx, false), ret_value);
ret_value = do_number_bitwise_logic (frame_ctx_p,
dst_var_idx,
number_bitwise_logic_xor,
left_value,
right_value);
ECMA_FINALIZE (right_value);
ECMA_FINALIZE (left_value);
frame_ctx_p->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 (vm_instr_t instr, /**< instruction */
vm_frame_ctx_t *frame_ctx_p) /**< interpreter context */
{
const vm_idx_t dst_var_idx = instr.data.b_shift_left.dst;
const vm_idx_t left_var_idx = instr.data.b_shift_left.var_left;
const vm_idx_t right_var_idx = instr.data.b_shift_left.var_right;
ecma_completion_value_t ret_value = ecma_make_empty_completion_value ();
ECMA_TRY_CATCH (left_value, get_variable_value (frame_ctx_p, left_var_idx, false), ret_value);
ECMA_TRY_CATCH (right_value, get_variable_value (frame_ctx_p, right_var_idx, false), ret_value);
ret_value = do_number_bitwise_logic (frame_ctx_p,
dst_var_idx,
number_bitwise_shift_left,
left_value,
right_value);
ECMA_FINALIZE (right_value);
ECMA_FINALIZE (left_value);
frame_ctx_p->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 (vm_instr_t instr, /**< instruction */
vm_frame_ctx_t *frame_ctx_p) /**< interpreter context */
{
const vm_idx_t dst_var_idx = instr.data.b_shift_right.dst;
const vm_idx_t left_var_idx = instr.data.b_shift_right.var_left;
const vm_idx_t right_var_idx = instr.data.b_shift_right.var_right;
ecma_completion_value_t ret_value = ecma_make_empty_completion_value ();
ECMA_TRY_CATCH (left_value, get_variable_value (frame_ctx_p, left_var_idx, false), ret_value);
ECMA_TRY_CATCH (right_value, get_variable_value (frame_ctx_p, right_var_idx, false), ret_value);
ret_value = do_number_bitwise_logic (frame_ctx_p,
dst_var_idx,
number_bitwise_shift_right,
left_value,
right_value);
ECMA_FINALIZE (right_value);
ECMA_FINALIZE (left_value);
frame_ctx_p->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 (vm_instr_t instr, /**< instruction */
vm_frame_ctx_t *frame_ctx_p) /**< interpreter context */
{
const vm_idx_t dst_var_idx = instr.data.b_shift_uright.dst;
const vm_idx_t left_var_idx = instr.data.b_shift_uright.var_left;
const vm_idx_t right_var_idx = instr.data.b_shift_uright.var_right;
ecma_completion_value_t ret_value = ecma_make_empty_completion_value ();
ECMA_TRY_CATCH (left_value, get_variable_value (frame_ctx_p, left_var_idx, false), ret_value);
ECMA_TRY_CATCH (right_value, get_variable_value (frame_ctx_p, right_var_idx, false), ret_value);
ret_value = do_number_bitwise_logic (frame_ctx_p,
dst_var_idx,
number_bitwise_shift_uright,
left_value,
right_value);
ECMA_FINALIZE (right_value);
ECMA_FINALIZE (left_value);
frame_ctx_p->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 (vm_instr_t instr, /**< instruction */
vm_frame_ctx_t *frame_ctx_p) /**< interpreter context */
{
const vm_idx_t dst_var_idx = instr.data.b_not.dst;
const vm_idx_t right_var_idx = instr.data.b_not.var_right;
ecma_completion_value_t ret_value = ecma_make_empty_completion_value ();
ECMA_TRY_CATCH (right_value, get_variable_value (frame_ctx_p, right_var_idx, false), ret_value);
ret_value = do_number_bitwise_logic (frame_ctx_p,
dst_var_idx,
number_bitwise_not,
right_value,
right_value);
ECMA_FINALIZE (right_value);
frame_ctx_p->pos++;
return ret_value;
} /* opfunc_b_not */
+38 -74
View File
@@ -1,4 +1,5 @@
/* Copyright 2014-2015 Samsung Electronics Co., Ltd.
/* Copyright 2014-2016 Samsung Electronics Co., Ltd.
* Copyright 2015-2016 University of Szeged.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -13,8 +14,23 @@
* limitations under the License.
*/
#include "ecma-builtins.h"
#include "ecma-comparison.h"
#include "ecma-exceptions.h"
#include "ecma-function-object.h"
#include "ecma-globals.h"
#include "ecma-helpers.h"
#include "ecma-lex-env.h"
#include "ecma-try-catch-macro.h"
#include "opcodes.h"
#include "opcodes-ecma-support.h"
#include "vm-defines.h"
/** \addtogroup vm Virtual machine
* @{
*
* \addtogroup vm_opcodes Opcodes
* @{
*/
/**
* 'Equals' opcode handler.
@@ -25,17 +41,11 @@
* Returned value must be freed with ecma_free_completion_value
*/
ecma_completion_value_t
opfunc_equal_value (vm_instr_t instr, /**< instruction */
vm_frame_ctx_t *frame_ctx_p) /**< interpreter context */
opfunc_equal_value (ecma_value_t left_value, /**< left value */
ecma_value_t right_value) /**< right value */
{
const vm_idx_t dst_var_idx = instr.data.equal_value.dst;
const vm_idx_t left_var_idx = instr.data.equal_value.var_left;
const vm_idx_t right_var_idx = instr.data.equal_value.var_right;
ecma_completion_value_t ret_value = ecma_make_empty_completion_value ();
ECMA_TRY_CATCH (left_value, get_variable_value (frame_ctx_p, left_var_idx, false), ret_value);
ECMA_TRY_CATCH (right_value, get_variable_value (frame_ctx_p, right_var_idx, false), ret_value);
ECMA_TRY_CATCH (compare_result,
ecma_op_abstract_equality_compare (left_value,
right_value),
@@ -43,14 +53,9 @@ opfunc_equal_value (vm_instr_t instr, /**< instruction */
JERRY_ASSERT (ecma_is_value_boolean (compare_result));
ret_value = set_variable_value (frame_ctx_p, frame_ctx_p->pos, dst_var_idx,
compare_result);
ret_value = ecma_make_normal_completion_value (compare_result);
ECMA_FINALIZE (compare_result);
ECMA_FINALIZE (right_value);
ECMA_FINALIZE (left_value);
frame_ctx_p->pos++;
return ret_value;
} /* opfunc_equal_value */
@@ -64,17 +69,11 @@ opfunc_equal_value (vm_instr_t instr, /**< instruction */
* Returned value must be freed with ecma_free_completion_value
*/
ecma_completion_value_t
opfunc_not_equal_value (vm_instr_t instr, /**< instruction */
vm_frame_ctx_t *frame_ctx_p) /**< interpreter context */
opfunc_not_equal_value (ecma_value_t left_value, /**< left value */
ecma_value_t right_value) /**< right value */
{
const vm_idx_t dst_var_idx = instr.data.not_equal_value.dst;
const vm_idx_t left_var_idx = instr.data.not_equal_value.var_left;
const vm_idx_t right_var_idx = instr.data.not_equal_value.var_right;
ecma_completion_value_t ret_value = ecma_make_empty_completion_value ();
ECMA_TRY_CATCH (left_value, get_variable_value (frame_ctx_p, left_var_idx, false), ret_value);
ECMA_TRY_CATCH (right_value, get_variable_value (frame_ctx_p, right_var_idx, false), ret_value);
ECMA_TRY_CATCH (compare_result,
ecma_op_abstract_equality_compare (left_value, right_value),
ret_value);
@@ -83,15 +82,10 @@ opfunc_not_equal_value (vm_instr_t instr, /**< instruction */
bool is_equal = ecma_is_value_true (compare_result);
ret_value = set_variable_value (frame_ctx_p, frame_ctx_p->pos, dst_var_idx,
ecma_make_simple_value (is_equal ? ECMA_SIMPLE_VALUE_FALSE
: ECMA_SIMPLE_VALUE_TRUE));
ret_value = ecma_make_normal_completion_value (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);
frame_ctx_p->pos++;
return ret_value;
} /* opfunc_not_equal_value */
@@ -105,30 +99,13 @@ opfunc_not_equal_value (vm_instr_t instr, /**< instruction */
* Returned value must be freed with ecma_free_completion_value
*/
ecma_completion_value_t
opfunc_equal_value_type (vm_instr_t instr, /**< instruction */
vm_frame_ctx_t *frame_ctx_p) /**< interpreter context */
opfunc_equal_value_type (ecma_value_t left_value, /**< left value */
ecma_value_t right_value) /**< right value */
{
const vm_idx_t dst_var_idx = instr.data.equal_value_type.dst;
const vm_idx_t left_var_idx = instr.data.equal_value_type.var_left;
const vm_idx_t right_var_idx = instr.data.equal_value_type.var_right;
ecma_completion_value_t ret_value = ecma_make_empty_completion_value ();
ECMA_TRY_CATCH (left_value, get_variable_value (frame_ctx_p, left_var_idx, false), ret_value);
ECMA_TRY_CATCH (right_value, get_variable_value (frame_ctx_p, right_var_idx, false), ret_value);
bool is_equal = ecma_op_strict_equality_compare (left_value, right_value);
ret_value = set_variable_value (frame_ctx_p, frame_ctx_p->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);
frame_ctx_p->pos++;
return ret_value;
return ecma_make_normal_completion_value (ecma_make_simple_value (is_equal ? ECMA_SIMPLE_VALUE_TRUE
: ECMA_SIMPLE_VALUE_FALSE));
} /* opfunc_equal_value_type */
/**
@@ -140,29 +117,16 @@ opfunc_equal_value_type (vm_instr_t instr, /**< instruction */
* Returned value must be freed with ecma_free_completion_value
*/
ecma_completion_value_t
opfunc_not_equal_value_type (vm_instr_t instr, /**< instruction */
vm_frame_ctx_t *frame_ctx_p) /**< interpreter context */
opfunc_not_equal_value_type (ecma_value_t left_value, /**< left value */
ecma_value_t right_value) /**< right value */
{
const vm_idx_t dst_var_idx = instr.data.not_equal_value_type.dst;
const vm_idx_t left_var_idx = instr.data.not_equal_value_type.var_left;
const vm_idx_t right_var_idx = instr.data.not_equal_value_type.var_right;
ecma_completion_value_t ret_value = ecma_make_empty_completion_value ();
ECMA_TRY_CATCH (left_value, get_variable_value (frame_ctx_p, left_var_idx, false), ret_value);
ECMA_TRY_CATCH (right_value, get_variable_value (frame_ctx_p, right_var_idx, false), ret_value);
bool is_equal = ecma_op_strict_equality_compare (left_value, right_value);
ret_value = set_variable_value (frame_ctx_p, frame_ctx_p->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);
frame_ctx_p->pos++;
return ret_value;
return ecma_make_normal_completion_value (ecma_make_simple_value (is_equal ? ECMA_SIMPLE_VALUE_FALSE
: ECMA_SIMPLE_VALUE_TRUE));
} /* opfunc_not_equal_value_type */
/**
* @}
* @}
*/
+38 -86
View File
@@ -1,4 +1,5 @@
/* Copyright 2014-2015 Samsung Electronics Co., Ltd.
/* Copyright 2014-2016 Samsung Electronics Co., Ltd.
* Copyright 2015-2016 University of Szeged.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -13,8 +14,20 @@
* limitations under the License.
*/
#include "ecma-comparison.h"
#include "ecma-conversion.h"
#include "ecma-exceptions.h"
#include "ecma-helpers.h"
#include "ecma-objects.h"
#include "ecma-try-catch-macro.h"
#include "opcodes.h"
#include "opcodes-ecma-support.h"
/** \addtogroup vm Virtual machine
* @{
*
* \addtogroup vm_opcodes Opcodes
* @{
*/
/**
* 'Less-than' opcode handler.
@@ -25,17 +38,11 @@
* Returned value must be freed with ecma_free_completion_value
*/
ecma_completion_value_t
opfunc_less_than (vm_instr_t instr, /**< instruction */
vm_frame_ctx_t *frame_ctx_p) /**< interpreter context */
opfunc_less_than (ecma_value_t left_value, /**< left value */
ecma_value_t right_value) /**< right value */
{
const vm_idx_t dst_var_idx = instr.data.less_than.dst;
const vm_idx_t left_var_idx = instr.data.less_than.var_left;
const vm_idx_t right_var_idx = instr.data.less_than.var_right;
ecma_completion_value_t ret_value = ecma_make_empty_completion_value ();
ECMA_TRY_CATCH (left_value, get_variable_value (frame_ctx_p, left_var_idx, false), ret_value);
ECMA_TRY_CATCH (right_value, get_variable_value (frame_ctx_p, right_var_idx, false), ret_value);
ECMA_TRY_CATCH (compare_result,
ecma_op_abstract_relational_compare (left_value, right_value, true),
ret_value);
@@ -53,13 +60,9 @@ opfunc_less_than (vm_instr_t instr, /**< instruction */
res = (ecma_is_value_true (compare_result) ? ECMA_SIMPLE_VALUE_TRUE : ECMA_SIMPLE_VALUE_FALSE);
}
ret_value = set_variable_value (frame_ctx_p, frame_ctx_p->pos, dst_var_idx, ecma_make_simple_value (res));
ret_value = ecma_make_simple_completion_value (res);
ECMA_FINALIZE (compare_result);
ECMA_FINALIZE (right_value);
ECMA_FINALIZE (left_value);
frame_ctx_p->pos++;
return ret_value;
} /* opfunc_less_than */
@@ -73,17 +76,11 @@ opfunc_less_than (vm_instr_t instr, /**< instruction */
* Returned value must be freed with ecma_free_completion_value
*/
ecma_completion_value_t
opfunc_greater_than (vm_instr_t instr, /**< instruction */
vm_frame_ctx_t *frame_ctx_p) /**< interpreter context */
opfunc_greater_than (ecma_value_t left_value, /**< left value */
ecma_value_t right_value) /**< right value */
{
const vm_idx_t dst_var_idx = instr.data.greater_than.dst;
const vm_idx_t left_var_idx = instr.data.greater_than.var_left;
const vm_idx_t right_var_idx = instr.data.greater_than.var_right;
ecma_completion_value_t ret_value = ecma_make_empty_completion_value ();
ECMA_TRY_CATCH (left_value, get_variable_value (frame_ctx_p, left_var_idx, false), ret_value);
ECMA_TRY_CATCH (right_value, get_variable_value (frame_ctx_p, right_var_idx, false), ret_value);
ECMA_TRY_CATCH (compare_result,
ecma_op_abstract_relational_compare (right_value, left_value, false),
ret_value);
@@ -101,13 +98,9 @@ opfunc_greater_than (vm_instr_t instr, /**< instruction */
res = (ecma_is_value_true (compare_result) ? ECMA_SIMPLE_VALUE_TRUE : ECMA_SIMPLE_VALUE_FALSE);
}
ret_value = set_variable_value (frame_ctx_p, frame_ctx_p->pos, dst_var_idx, ecma_make_simple_value (res));
ret_value = ecma_make_simple_completion_value (res);
ECMA_FINALIZE (compare_result);
ECMA_FINALIZE (right_value);
ECMA_FINALIZE (left_value);
frame_ctx_p->pos++;
return ret_value;
} /* opfunc_greater_than */
@@ -121,17 +114,11 @@ opfunc_greater_than (vm_instr_t instr, /**< instruction */
* Returned value must be freed with ecma_free_completion_value
*/
ecma_completion_value_t
opfunc_less_or_equal_than (vm_instr_t instr, /**< instruction */
vm_frame_ctx_t *frame_ctx_p) /**< interpreter context */
opfunc_less_or_equal_than (ecma_value_t left_value, /**< left value */
ecma_value_t right_value) /**< right value */
{
const vm_idx_t dst_var_idx = instr.data.less_or_equal_than.dst;
const vm_idx_t left_var_idx = instr.data.less_or_equal_than.var_left;
const vm_idx_t right_var_idx = instr.data.less_or_equal_than.var_right;
ecma_completion_value_t ret_value = ecma_make_empty_completion_value ();
ECMA_TRY_CATCH (left_value, get_variable_value (frame_ctx_p, left_var_idx, false), ret_value);
ECMA_TRY_CATCH (right_value, get_variable_value (frame_ctx_p, right_var_idx, false), ret_value);
ECMA_TRY_CATCH (compare_result,
ecma_op_abstract_relational_compare (right_value, left_value, false),
ret_value);
@@ -156,13 +143,9 @@ opfunc_less_or_equal_than (vm_instr_t instr, /**< instruction */
}
}
ret_value = set_variable_value (frame_ctx_p, frame_ctx_p->pos, dst_var_idx, ecma_make_simple_value (res));
ret_value = ecma_make_simple_completion_value (res);
ECMA_FINALIZE (compare_result);
ECMA_FINALIZE (right_value);
ECMA_FINALIZE (left_value);
frame_ctx_p->pos++;
return ret_value;
} /* opfunc_less_or_equal_than */
@@ -176,17 +159,11 @@ opfunc_less_or_equal_than (vm_instr_t instr, /**< instruction */
* Returned value must be freed with ecma_free_completion_value
*/
ecma_completion_value_t
opfunc_greater_or_equal_than (vm_instr_t instr, /**< instruction */
vm_frame_ctx_t *frame_ctx_p) /**< interpreter context */
opfunc_greater_or_equal_than (ecma_value_t left_value, /**< left value */
ecma_value_t right_value) /**< right value */
{
const vm_idx_t dst_var_idx = instr.data.greater_or_equal_than.dst;
const vm_idx_t left_var_idx = instr.data.greater_or_equal_than.var_left;
const vm_idx_t right_var_idx = instr.data.greater_or_equal_than.var_right;
ecma_completion_value_t ret_value = ecma_make_empty_completion_value ();
ECMA_TRY_CATCH (left_value, get_variable_value (frame_ctx_p, left_var_idx, false), ret_value);
ECMA_TRY_CATCH (right_value, get_variable_value (frame_ctx_p, right_var_idx, false), ret_value);
ECMA_TRY_CATCH (compare_result,
ecma_op_abstract_relational_compare (left_value, right_value, true),
ret_value);
@@ -211,13 +188,9 @@ opfunc_greater_or_equal_than (vm_instr_t instr, /**< instruction */
}
}
ret_value = set_variable_value (frame_ctx_p, frame_ctx_p->pos, dst_var_idx, ecma_make_simple_value (res));
ret_value = ecma_make_simple_completion_value (res);
ECMA_FINALIZE (compare_result);
ECMA_FINALIZE (right_value);
ECMA_FINALIZE (left_value);
frame_ctx_p->pos++;
return ret_value;
} /* opfunc_greater_or_equal_than */
@@ -231,18 +204,11 @@ opfunc_greater_or_equal_than (vm_instr_t instr, /**< instruction */
* returned value must be freed with ecma_free_completion_value.
*/
ecma_completion_value_t
opfunc_instanceof (vm_instr_t instr __attr_unused___, /**< instruction */
vm_frame_ctx_t *frame_ctx_p __attr_unused___) /**< interpreter context */
opfunc_instanceof (ecma_value_t left_value, /**< left value */
ecma_value_t right_value) /**< right value */
{
const vm_idx_t dst_idx = instr.data.instanceof.dst;
const vm_idx_t left_var_idx = instr.data.instanceof.var_left;
const vm_idx_t right_var_idx = instr.data.instanceof.var_right;
ecma_completion_value_t ret_value = ecma_make_empty_completion_value ();
ECMA_TRY_CATCH (left_value, get_variable_value (frame_ctx_p, left_var_idx, false), ret_value);
ECMA_TRY_CATCH (right_value, get_variable_value (frame_ctx_p, 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));
@@ -255,16 +221,11 @@ opfunc_instanceof (vm_instr_t instr __attr_unused___, /**< instruction */
ecma_op_object_has_instance (right_value_obj_p, left_value),
ret_value);
ret_value = set_variable_value (frame_ctx_p, frame_ctx_p->pos, dst_idx, is_instance_of);
ret_value = ecma_make_normal_completion_value (is_instance_of);
ECMA_FINALIZE (is_instance_of);
}
ECMA_FINALIZE (right_value);
ECMA_FINALIZE (left_value);
frame_ctx_p->pos++;
return ret_value;
} /* opfunc_instanceof */
@@ -277,18 +238,11 @@ opfunc_instanceof (vm_instr_t instr __attr_unused___, /**< instruction */
* returned value must be freed with ecma_free_completion_value.
*/
ecma_completion_value_t
opfunc_in (vm_instr_t instr __attr_unused___, /**< instruction */
vm_frame_ctx_t *frame_ctx_p __attr_unused___) /**< interpreter context */
opfunc_in (ecma_value_t left_value, /**< left value */
ecma_value_t right_value) /**< right value */
{
const vm_idx_t dst_idx = instr.data.in.dst;
const vm_idx_t left_var_idx = instr.data.in.var_left;
const vm_idx_t right_var_idx = instr.data.in.var_right;
ecma_completion_value_t ret_value = ecma_make_empty_completion_value ();
ECMA_TRY_CATCH (left_value, get_variable_value (frame_ctx_p, left_var_idx, false), ret_value);
ECMA_TRY_CATCH (right_value, get_variable_value (frame_ctx_p, 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));
@@ -310,17 +264,15 @@ opfunc_in (vm_instr_t instr __attr_unused___, /**< instruction */
is_in = ECMA_SIMPLE_VALUE_FALSE;
}
ret_value = set_variable_value (frame_ctx_p, frame_ctx_p->pos,
dst_idx,
ecma_make_simple_value (is_in));
ret_value = ecma_make_simple_completion_value (is_in);
ECMA_FINALIZE (str_left_value);
}
ECMA_FINALIZE (right_value);
ECMA_FINALIZE (left_value);
frame_ctx_p->pos++;
return ret_value;
} /* opfunc_in */
/**
* @}
* @}
*/
-48
View File
@@ -1,48 +0,0 @@
/* 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-builtins.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-reference.h"
#include "ecma-regexp-object.h"
#include "ecma-try-catch-macro.h"
bool vm_is_reg_variable (vm_idx_t);
ecma_completion_value_t get_variable_value (vm_frame_ctx_t *, vm_idx_t, bool);
ecma_completion_value_t set_variable_value (vm_frame_ctx_t *, vm_instr_counter_t, vm_idx_t, ecma_value_t);
ecma_completion_value_t vm_fill_varg_list (vm_frame_ctx_t *, ecma_length_t, ecma_collection_header_t *);
extern vm_instr_counter_t vm_fill_params_list (const bytecode_data_header_t *,
vm_instr_counter_t,
ecma_length_t,
ecma_collection_header_t *);
extern ecma_completion_value_t vm_function_declaration (const bytecode_data_header_t *bytecode_header_p,
bool is_strict,
bool is_eval_code,
ecma_object_t *lex_env_p);
#endif /* OPCODES_ECMA_SUPPORT_H */
@@ -1,134 +0,0 @@
/* 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 "bytecode-data.h"
#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 (vm_instr_t instr, /**< instruction */
vm_frame_ctx_t *frame_ctx_p) /**< interpreter context */
{
const vm_idx_t block_end_oc_idx_1 = instr.data.try_block.oc_idx_1;
const vm_idx_t block_end_oc_idx_2 = instr.data.try_block.oc_idx_2;
const vm_instr_counter_t try_end_oc = (vm_instr_counter_t) (
vm_calc_instr_counter_from_idx_idx (block_end_oc_idx_1, block_end_oc_idx_2) + frame_ctx_p->pos);
frame_ctx_p->pos++;
vm_run_scope_t run_scope_try = { frame_ctx_p->pos, try_end_oc };
ecma_completion_value_t try_completion = vm_loop (frame_ctx_p, &run_scope_try);
JERRY_ASSERT ((!ecma_is_completion_value_empty (try_completion) && frame_ctx_p->pos <= try_end_oc)
|| (ecma_is_completion_value_empty (try_completion) && frame_ctx_p->pos == try_end_oc));
frame_ctx_p->pos = try_end_oc;
vm_instr_t next_instr = vm_get_instr (frame_ctx_p->bytecode_header_p->instrs_p, frame_ctx_p->pos);
JERRY_ASSERT (next_instr.op_idx == VM_OP_META);
if (next_instr.data.meta.type == OPCODE_META_TYPE_CATCH)
{
const vm_instr_counter_t catch_end_oc = (vm_instr_counter_t) (
vm_read_instr_counter_from_meta (OPCODE_META_TYPE_CATCH,
frame_ctx_p->bytecode_header_p,
frame_ctx_p->pos) + frame_ctx_p->pos);
frame_ctx_p->pos++;
if (ecma_is_completion_value_throw (try_completion))
{
next_instr = vm_get_instr (frame_ctx_p->bytecode_header_p->instrs_p, frame_ctx_p->pos);
JERRY_ASSERT (next_instr.op_idx == VM_OP_META);
JERRY_ASSERT (next_instr.data.meta.type == OPCODE_META_TYPE_CATCH_EXCEPTION_IDENTIFIER);
lit_cpointer_t catch_exc_val_var_name_lit_cp = bc_get_literal_cp_by_uid (next_instr.data.meta.data_1,
frame_ctx_p->bytecode_header_p,
frame_ctx_p->pos);
frame_ctx_p->pos++;
ecma_string_t *catch_exc_var_name_str_p = ecma_new_ecma_string_from_lit_cp (catch_exc_val_var_name_lit_cp);
ecma_object_t *old_env_p = frame_ctx_p->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);
frame_ctx_p->lex_env_p = catch_env_p;
ecma_free_completion_value (try_completion);
vm_run_scope_t run_scope_catch = { frame_ctx_p->pos, catch_end_oc };
try_completion = vm_loop (frame_ctx_p, &run_scope_catch);
frame_ctx_p->lex_env_p = old_env_p;
ecma_deref_object (catch_env_p);
JERRY_ASSERT ((!ecma_is_completion_value_empty (try_completion) && frame_ctx_p->pos <= catch_end_oc)
|| (ecma_is_completion_value_empty (try_completion) && frame_ctx_p->pos == catch_end_oc));
}
frame_ctx_p->pos = catch_end_oc;
}
next_instr = vm_get_instr (frame_ctx_p->bytecode_header_p->instrs_p, frame_ctx_p->pos);
JERRY_ASSERT (next_instr.op_idx == VM_OP_META);
if (next_instr.data.meta.type == OPCODE_META_TYPE_FINALLY)
{
const vm_instr_counter_t finally_end_oc = (vm_instr_counter_t) (
vm_read_instr_counter_from_meta (OPCODE_META_TYPE_FINALLY,
frame_ctx_p->bytecode_header_p,
frame_ctx_p->pos) + frame_ctx_p->pos);
frame_ctx_p->pos++;
vm_run_scope_t run_scope_finally = { frame_ctx_p->pos, finally_end_oc };
ecma_completion_value_t finally_completion = vm_loop (frame_ctx_p, &run_scope_finally);
JERRY_ASSERT ((!ecma_is_completion_value_empty (finally_completion) && frame_ctx_p->pos <= finally_end_oc)
|| (ecma_is_completion_value_empty (finally_completion) && frame_ctx_p->pos == finally_end_oc));
frame_ctx_p->pos = finally_end_oc;
if (!ecma_is_completion_value_empty (finally_completion))
{
ecma_free_completion_value (try_completion);
try_completion = finally_completion;
}
}
next_instr = vm_get_instr (frame_ctx_p->bytecode_header_p->instrs_p, frame_ctx_p->pos++);
JERRY_ASSERT (next_instr.op_idx == VM_OP_META);
JERRY_ASSERT (next_instr.data.meta.type == OPCODE_META_TYPE_END_TRY_CATCH_FINALLY);
return try_completion;
} /* opfunc_try_block */
-125
View File
@@ -1,125 +0,0 @@
/* Copyright 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 "bytecode-data.h"
#include "jrt.h"
#include "opcodes.h"
#include "opcodes-ecma-support.h"
/**
* 'for-in' opcode handler
*
* See also:
* ECMA-262 v5, 12.6.4
*
* @return completion value
* Returned value must be freed with ecma_free_completion_value
*/
ecma_completion_value_t
opfunc_for_in (vm_instr_t instr, /**< instruction */
vm_frame_ctx_t *int_data_p) /**< interpreter context */
{
const vm_idx_t expr_idx = instr.data.for_in.expr;
const vm_idx_t block_end_oc_idx_1 = instr.data.for_in.oc_idx_1;
const vm_idx_t block_end_oc_idx_2 = instr.data.for_in.oc_idx_2;
const vm_instr_counter_t for_in_end_oc = (vm_instr_counter_t) (
vm_calc_instr_counter_from_idx_idx (block_end_oc_idx_1,
block_end_oc_idx_2) + int_data_p->pos);
ecma_completion_value_t ret_value = ecma_make_empty_completion_value ();
/* 1., 2. */
ECMA_TRY_CATCH (expr_value,
get_variable_value (int_data_p,
expr_idx,
false),
ret_value);
int_data_p->pos++;
vm_instr_t meta_instr = vm_get_instr (int_data_p->bytecode_header_p->instrs_p, for_in_end_oc);
JERRY_ASSERT (meta_instr.op_idx == VM_OP_META);
JERRY_ASSERT (meta_instr.data.meta.type == OPCODE_META_TYPE_END_FOR_IN);
/* 3. */
if (!ecma_is_value_undefined (expr_value)
&& !ecma_is_value_null (expr_value))
{
/* 4. */
ECMA_TRY_CATCH (obj_expr_value,
ecma_op_to_object (expr_value),
ret_value);
ecma_object_t *obj_p = ecma_get_object_from_value (obj_expr_value);
ecma_collection_iterator_t names_iterator;
ecma_collection_header_t *names_p = ecma_op_object_get_property_names (obj_p, false, true, true);
if (names_p != NULL)
{
ecma_collection_iterator_init (&names_iterator, names_p);
const vm_instr_counter_t for_in_body_begin_oc = int_data_p->pos;
const vm_instr_counter_t for_in_body_end_oc = for_in_end_oc;
while (ecma_collection_iterator_next (&names_iterator))
{
ecma_value_t name_value = *names_iterator.current_value_p;
ecma_string_t *name_p = ecma_get_string_from_value (name_value);
if (ecma_op_object_get_property (obj_p, name_p) != NULL)
{
ecma_completion_value_t completion = set_variable_value (int_data_p,
int_data_p->pos,
VM_REG_SPECIAL_FOR_IN_PROPERTY_NAME,
name_value);
JERRY_ASSERT (ecma_is_completion_value_empty (completion));
vm_run_scope_t run_scope_for_in = { for_in_body_begin_oc, for_in_body_end_oc };
ecma_completion_value_t for_in_body_completion = vm_loop (int_data_p, &run_scope_for_in);
if (ecma_is_completion_value_empty (for_in_body_completion))
{
JERRY_ASSERT (int_data_p->pos == for_in_body_end_oc);
int_data_p->pos = for_in_body_begin_oc;
}
else
{
JERRY_ASSERT (ecma_is_completion_value_throw (for_in_body_completion)
|| ecma_is_completion_value_return (for_in_body_completion)
|| ecma_is_completion_value_jump (for_in_body_completion));
JERRY_ASSERT (int_data_p->pos <= for_in_body_end_oc);
ret_value = for_in_body_completion;
break;
}
}
}
ecma_free_values_collection (names_p, true);
}
ECMA_FINALIZE (obj_expr_value);
}
int_data_p->pos = (vm_instr_counter_t) (for_in_end_oc + 1u);
ECMA_FINALIZE (expr_value);
return ret_value;
} /* opfunc_for_in */
-181
View File
@@ -1,181 +0,0 @@
/* 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 "bytecode-data.h"
#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 (LIT_MAGIC_STRING_EVAL);
ecma_string_t* magic_string_arguments = ecma_get_magic_string (LIT_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 a register variable,
* false - otherwise.
*/
bool
vm_is_reg_variable (vm_idx_t var_idx) /**< variable identifier */
{
return (var_idx >= VM_REG_FIRST && var_idx <= VM_REG_LAST);
} /* vm_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 (vm_frame_ctx_t *frame_ctx_p, /**< interpreter context */
vm_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 = ecma_make_empty_completion_value ();
if (vm_is_reg_variable (var_idx))
{
ecma_value_t reg_value = vm_stack_frame_get_reg_value (&frame_ctx_p->stack_frame, var_idx);
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;
lit_cpointer_t lit_cp = bc_get_literal_cp_by_uid (var_idx,
frame_ctx_p->bytecode_header_p,
frame_ctx_p->pos);
JERRY_ASSERT (lit_cp.packed_value != MEM_CP_NULL);
ecma_new_ecma_string_on_stack_from_lit_cp (&var_name_string, lit_cp);
ecma_object_t *ref_base_lex_env_p = ecma_op_resolve_reference_base (frame_ctx_p->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,
frame_ctx_p->is_strict);
#endif /* !JERRY_NDEBUG */
}
ret_value = ecma_op_get_value_lex_env_base (ref_base_lex_env_p,
&var_name_string,
frame_ctx_p->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 (vm_frame_ctx_t *frame_ctx_p, /**< interpreter context */
vm_instr_counter_t lit_oc, /**< instruction counter for literal */
vm_idx_t var_idx, /**< variable identifier */
ecma_value_t value) /**< value to set */
{
ecma_completion_value_t ret_value = ecma_make_empty_completion_value ();
if (vm_is_reg_variable (var_idx))
{
ret_value = ecma_make_empty_completion_value ();
ecma_value_t reg_value = vm_stack_frame_get_reg_value (&frame_ctx_p->stack_frame, var_idx);
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);
}
vm_stack_frame_set_reg_value (&frame_ctx_p->stack_frame, var_idx, ecma_copy_value (value, false));
}
}
else
{
ecma_string_t var_name_string;
lit_cpointer_t lit_cp = bc_get_literal_cp_by_uid (var_idx, frame_ctx_p->bytecode_header_p, lit_oc);
JERRY_ASSERT (lit_cp.packed_value != MEM_CP_NULL);
ecma_new_ecma_string_on_stack_from_lit_cp (&var_name_string, lit_cp);
ecma_object_t *ref_base_lex_env_p = ecma_op_resolve_reference_base (frame_ctx_p->lex_env_p,
&var_name_string);
#ifndef JERRY_NDEBUG
do_strict_eval_arguments_check (ref_base_lex_env_p,
&var_name_string,
frame_ctx_p->is_strict);
#endif /* !JERRY_NDEBUG */
ret_value = ecma_op_put_value_lex_env_base (ref_base_lex_env_p,
&var_name_string,
frame_ctx_p->is_strict,
value);
ecma_check_that_ecma_string_need_not_be_freed (&var_name_string);
}
return ret_value;
} /* set_variable_value */
-109
View File
@@ -1,109 +0,0 @@
/* 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 "bytecode-data.h"
#include "jrt.h"
#include "opcodes.h"
#include "opcodes-ecma-support.h"
#include "vm.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
vm_fill_varg_list (vm_frame_ctx_t *frame_ctx_p, /**< interpreter context */
ecma_length_t args_number, /**< number of arguments */
ecma_collection_header_t *arg_collection_p) /** collection to fill with argument values */
{
ecma_completion_value_t ret_value = ecma_make_empty_completion_value ();
ecma_length_t arg_index;
for (arg_index = 0;
arg_index < args_number && ecma_is_completion_value_empty (ret_value);
arg_index++)
{
ECMA_TRY_CATCH (evaluate_arg,
vm_loop (frame_ctx_p, NULL),
ret_value);
vm_instr_t next_instr = vm_get_instr (frame_ctx_p->bytecode_header_p->instrs_p, frame_ctx_p->pos);
JERRY_ASSERT (next_instr.op_idx == VM_OP_META);
JERRY_ASSERT (next_instr.data.meta.type == OPCODE_META_TYPE_VARG);
const vm_idx_t varg_var_idx = next_instr.data.meta.data_1;
ECMA_TRY_CATCH (get_arg,
get_variable_value (frame_ctx_p, varg_var_idx, false),
ret_value);
ecma_append_to_values_collection (arg_collection_p,
ecma_get_completion_value_value (get_arg_completion),
true);
ECMA_FINALIZE (get_arg);
frame_ctx_p->pos++;
ECMA_FINALIZE (evaluate_arg);
}
return ret_value;
} /* vm_fill_varg_list */
/**
* Fill parameters' list
*/
vm_instr_counter_t
vm_fill_params_list (const bytecode_data_header_t *bytecode_header_p, /**< header of byte-code */
vm_instr_counter_t first_instr_pos, /**< position of the first instruction
* with a formal parameter's name */
ecma_length_t params_number, /**< number of parameters */
ecma_collection_header_t *formal_params_collection_p) /**< collection to fill with
* parameters' names */
{
vm_instr_counter_t instr_pos = first_instr_pos;
uint32_t param_index;
for (param_index = 0;
param_index < params_number;
param_index++)
{
vm_instr_t next_instr = vm_get_instr (bytecode_header_p->instrs_p, instr_pos);
JERRY_ASSERT (next_instr.op_idx == VM_OP_META);
JERRY_ASSERT (next_instr.data.meta.type == OPCODE_META_TYPE_VARG);
const lit_cpointer_t param_name_lit_idx = bc_get_literal_cp_by_uid (next_instr.data.meta.data_1,
bytecode_header_p,
instr_pos);
ecma_string_t *param_name_str_p = ecma_new_ecma_string_from_lit_cp (param_name_lit_idx);
ecma_value_t param_name_value = ecma_make_string_value (param_name_str_p);
ecma_append_to_values_collection (formal_params_collection_p, param_name_value, false);
ecma_deref_ecma_string (param_name_str_p);
instr_pos++;
}
JERRY_ASSERT (param_index == params_number);
return instr_pos;
} /* vm_fill_params_list */
+229 -1578
View File
File diff suppressed because it is too large Load Diff
+102 -266
View File
@@ -1,4 +1,5 @@
/* Copyright 2014-2015 Samsung Electronics Co., Ltd.
/* Copyright 2015-2016 Samsung Electronics Co., Ltd.
* Copyright 2015-2016 University of Szeged.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,284 +18,119 @@
#define OPCODES_H
#include "ecma-globals.h"
#include "jrt.h"
#include "vm-stack.h"
#include "vm-defines.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)
/**
* Instruction counter / position
*/
typedef uint16_t vm_instr_counter_t;
/**
* Opcode / argument value in an instruction ("idx")
*/
typedef uint8_t vm_idx_t;
/**
* Description of vm_idx_t possible value ranges and special values
*/
enum : vm_idx_t
{
VM_IDX_GENERAL_VALUE_FIRST = 0, /**< first idx value that can be used for any argument value */
VM_IDX_GENERAL_VALUE_LAST = 252, /**< last idx value that can be used for any argument value */
/*
* Special values
*/
VM_IDX_REWRITE_GENERAL_CASE = 253, /**< intermediate value, used during byte-code generation,
* indicating that the idx would be rewritten with a value
* other than in-block literal identifier */
VM_IDX_REWRITE_LITERAL_UID = 254, /**< intermediate value, used during byte-code generation,
* indicating that the idx would be rewritten with in-block
* literal identifier */
VM_IDX_EMPTY = 255, /**< empty idx value, used when corresponding instruction argument is not set */
/*
* Literals (variable names / strings / numbers) ranges
*/
VM_IDX_LITERAL_FIRST = VM_IDX_GENERAL_VALUE_FIRST, /**< index of first possible literals-related idx value */
VM_IDX_LITERAL_LAST = VM_IDX_LITERAL_FIRST + 127, /**< index of last possible literals-related idx value */
/*
* Registers (temp variables) ranges
*/
VM_IDX_REG_FIRST = VM_IDX_LITERAL_LAST + 1, /** identifier of first special register */
VM_IDX_REG_LAST = VM_IDX_GENERAL_VALUE_LAST, /**< identifier of last register */
};
/**
* Ranges of registers (temporary variables)
*/
typedef enum : vm_idx_t
{
VM_REG_FIRST = VM_IDX_REG_FIRST, /** first register */
VM_REG_LAST = VM_IDX_REG_LAST, /**< last register */
VM_REG_SPECIAL_FIRST = VM_REG_FIRST, /**< first special register */
VM_REG_SPECIAL_EVAL_RET = VM_REG_SPECIAL_FIRST, /**< eval return value */
VM_REG_SPECIAL_FOR_IN_PROPERTY_NAME, /**< variable, containing property name,
* at start of for-in loop body */
VM_REG_SPECIAL_THIS_BINDING, /**< value of ThisBinding */
VM_REG_SPECIAL_LAST = VM_REG_SPECIAL_THIS_BINDING, /**< last special register */
VM_REG_GENERAL_FIRST, /** first non-special register */
VM_REG_GENERAL_LAST = VM_IDX_REG_LAST /** last non-special register */
} vm_reg_t;
/**
* Number of special VM registers
*/
#define VM_SPECIAL_REGS_NUMBER (VM_REG_SPECIAL_LAST - VM_REG_SPECIAL_FIRST + 1u)
/**
* 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 string literal with variable name */
OPCODE_ARG_TYPE_REGEXP /**< index of string literal with regular expression */
} opcode_arg_type_operand;
/**
* Types of data in 'meta' opcode.
*/
typedef enum
{
OPCODE_META_TYPE_UNDEFINED, /**< undefined meta (should be rewritten) */
OPCODE_META_TYPE_CALL_SITE_INFO, /**< optional additional information about call site
* (includes opcode_call_flags_t and can include 'this' argument) */
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_END_FOR_IN /**< end of for-in statement */
} opcode_meta_type;
typedef enum : vm_idx_t
{
OPCODE_CALL_FLAGS__EMPTY = (0u), /**< initializer for empty flag set */
OPCODE_CALL_FLAGS_HAVE_THIS_ARG = (1u << 0), /**< flag, indicating that call is performed
* with 'this' argument specified */
OPCODE_CALL_FLAGS_DIRECT_CALL_TO_EVAL_FORM = (1u << 1) /**< flag, indicating that call is performed
* in form 'eval (...)', i.e. through 'eval' string
* without object base (i.e. with lexical environment
* as base), so it can be a direct call to eval
* See also: ECMA-262 v5, 15.1.2.1.1
*/
} opcode_call_flags_t;
/**
* Types of byte-code instruction arguments, used for instruction description
/** \addtogroup vm Virtual machine
* @{
*
* See also:
* vm-opcodes.inc.h
* \addtogroup vm_opcodes Opcodes
* @{
*/
/**
* Number arithmetic operations.
*/
typedef enum
{
VM_OP_ARG_TYPE_EMPTY = (1u << 0), /**< empty argument (no value) */
VM_OP_ARG_TYPE_REGISTER = (1u << 1), /**< register variable (index) */
VM_OP_ARG_TYPE_IDENTIFIER = (1u << 2), /**< identifier - named variable (string literal) */
VM_OP_ARG_TYPE_STRING = (1u << 3), /**< string constant value (string literal) */
VM_OP_ARG_TYPE_NUMBER = (1u << 4), /**< number constant value (number literal) */
VM_OP_ARG_TYPE_INTEGER_CONST = (1u << 5), /**< a 8-bit integer constant (any vm_idx_t) */
VM_OP_ARG_TYPE_TYPE_OF_NEXT = (1u << 6), /**< opcode_arg_type_operand value,
* representing type of argument encoded in next idx */
/** variable - an identifier or a register */
VM_OP_ARG_TYPE_VARIABLE = (VM_OP_ARG_TYPE_REGISTER | VM_OP_ARG_TYPE_IDENTIFIER)
} vm_op_arg_type_t;
NUMBER_ARITHMETIC_ADDITION, /**< addition */
NUMBER_ARITHMETIC_SUBSTRACTION, /**< substraction */
NUMBER_ARITHMETIC_MULTIPLICATION, /**< multiplication */
NUMBER_ARITHMETIC_DIVISION, /**< division */
NUMBER_ARITHMETIC_REMAINDER, /**< remainder calculation */
} number_arithmetic_op;
/**
* Forward declaration of instruction structure
* Number bitwise logic operations.
*/
struct vm_instr_t;
/**
* Forward declaration of bytecode data header structure
*/
struct bytecode_data_header_t;
/**
* Context of interpreter, related to a JS stack frame
*/
typedef struct
{
const bytecode_data_header_t *bytecode_header_p; /**< currently executed byte-code data */
vm_instr_counter_t pos; /**< current position instruction to execute */
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 */
bool is_call_in_direct_eval_form; /** flag, indicating if there is call of 'Direct call to eval' form in
* process (see also: OPCODE_CALL_FLAGS_DIRECT_CALL_TO_EVAL_FORM) */
ecma_number_t *tmp_num_p; /**< an allocated number (to reduce temporary allocations) */
vm_stack_frame_t stack_frame; /**< 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 */
} vm_frame_ctx_t;
/**
* Description of a run scope
*
* Note:
* Run scope represents boundaries of byte-code block to run.
*
* Jumps within of the current run scope are performed by just changing instruction counter,
* and outside of the run scope - by returning corresponding ECMA_COMPLETION_TYPE_BREAK_CONTINUE
* completion value.
*/
typedef struct
{
const vm_instr_counter_t start_oc; /**< instruction counter of the first instruction of the scope */
const vm_instr_counter_t end_oc; /**< instruction counter of the last instruction of the scope */
} vm_run_scope_t;
vm_instr_counter_t vm_calc_instr_counter_from_idx_idx (const vm_idx_t, const vm_idx_t);
vm_instr_counter_t vm_read_instr_counter_from_meta (opcode_meta_type,
const bytecode_data_header_t *,
vm_instr_counter_t);
typedef struct vm_instr_t
{
vm_idx_t op_idx;
union
{
#define VM_OP_1(opcode_name, opcode_name_uppercase, arg1, arg1_type) \
struct \
{ \
vm_idx_t arg1; \
} opcode_name;
#define VM_OP_2(opcode_name, opcode_name_uppercase, arg1, arg1_type, arg2, arg2_type) \
struct \
{ \
vm_idx_t arg1; \
vm_idx_t arg2; \
} opcode_name;
#define VM_OP_3(opcode_name, opcode_name_uppercase, arg1, arg1_type, arg2, arg2_type, arg3, arg3_type) \
struct \
{ \
vm_idx_t arg1; \
vm_idx_t arg2; \
vm_idx_t arg3; \
} opcode_name;
#include "vm-opcodes.inc.h"
/**
* Opcode-independent arguments accessor
*
* Note:
* If opcode is statically known, opcode-specific way of accessing arguments should be used.
*/
vm_idx_t raw_args[3];
} data;
} vm_instr_t;
typedef enum
{
#define VM_OP_0(opcode_name, opcode_name_uppercase) \
VM_OP_ ## opcode_name_uppercase,
#define VM_OP_1(opcode_name, opcode_name_uppercase, arg1, arg1_type) \
VM_OP_ ## opcode_name_uppercase,
#define VM_OP_2(opcode_name, opcode_name_uppercase, arg1, arg1_type, arg2, arg2_type) \
VM_OP_ ## opcode_name_uppercase,
#define VM_OP_3(opcode_name, opcode_name_uppercase, arg1, arg1_type, arg2, arg2_type, arg3, arg3_type) \
VM_OP_ ## opcode_name_uppercase,
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;
#include "vm-opcodes.inc.h"
ecma_completion_value_t
vm_var_decl (vm_frame_ctx_t *, ecma_string_t *);
VM_OP__COUNT /**< number of opcodes */
} vm_op_t;
ecma_completion_value_t
opfunc_call_n (ecma_value_t,
ecma_value_t,
const ecma_value_t *,
ecma_length_t);
#define VM_OP_0(opcode_name, opcode_name_uppercase) \
ecma_completion_value_t opfunc_##opcode_name (vm_instr_t, vm_frame_ctx_t *);
#define VM_OP_1(opcode_name, opcode_name_uppercase, arg1, arg1_type) \
ecma_completion_value_t opfunc_##opcode_name (vm_instr_t, vm_frame_ctx_t *);
#define VM_OP_2(opcode_name, opcode_name_uppercase, arg1, arg1_type, arg2, arg2_type) \
ecma_completion_value_t opfunc_##opcode_name (vm_instr_t, vm_frame_ctx_t *);
#define VM_OP_3(opcode_name, opcode_name_uppercase, arg1, arg1_type, arg2, arg2_type, arg3, arg3_type) \
ecma_completion_value_t opfunc_##opcode_name (vm_instr_t, vm_frame_ctx_t *);
ecma_completion_value_t
opfunc_construct_n (ecma_value_t, uint8_t, ecma_value_t *);
#include "vm-opcodes.inc.h"
ecma_completion_value_t
opfunc_equal_value (ecma_value_t, ecma_value_t);
typedef ecma_completion_value_t (*opfunc) (vm_instr_t, vm_frame_ctx_t *);
ecma_completion_value_t
opfunc_not_equal_value (ecma_value_t, ecma_value_t);
#endif /* OPCODES_H */
ecma_completion_value_t
opfunc_equal_value_type (ecma_value_t, ecma_value_t);
ecma_completion_value_t
opfunc_not_equal_value_type (ecma_value_t, ecma_value_t);
ecma_completion_value_t
do_number_arithmetic (number_arithmetic_op, ecma_value_t, ecma_value_t);
ecma_completion_value_t
opfunc_unary_plus (ecma_value_t);
ecma_completion_value_t
opfunc_unary_minus (ecma_value_t);
ecma_completion_value_t
do_number_bitwise_logic (number_bitwise_logic_op, ecma_value_t, ecma_value_t);
ecma_completion_value_t
opfunc_addition (ecma_value_t, ecma_value_t);
ecma_completion_value_t
opfunc_less_than (ecma_value_t, ecma_value_t);
ecma_completion_value_t
opfunc_greater_than (ecma_value_t, ecma_value_t);
ecma_completion_value_t
opfunc_less_or_equal_than (ecma_value_t, ecma_value_t);
ecma_completion_value_t
opfunc_greater_or_equal_than (ecma_value_t, ecma_value_t);
ecma_completion_value_t
opfunc_in (ecma_value_t, ecma_value_t);
ecma_completion_value_t
opfunc_instanceof (ecma_value_t, ecma_value_t);
ecma_completion_value_t
opfunc_logical_not (ecma_value_t);
ecma_completion_value_t
opfunc_typeof (ecma_value_t);
void
opfunc_set_accessor (bool, ecma_value_t, ecma_value_t, ecma_value_t);
ecma_completion_value_t
vm_op_delete_prop (ecma_value_t, ecma_value_t, bool);
ecma_completion_value_t
vm_op_delete_var (lit_cpointer_t, ecma_object_t *, bool);
ecma_collection_header_t *
opfunc_for_in (ecma_value_t, ecma_value_t *);
/**
* @}
* @}
*/
#endif /* !OPCODES_H */
-583
View File
@@ -1,583 +0,0 @@
/* 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.
*/
#ifdef JERRY_ENABLE_PRETTY_PRINTER
#include <stdarg.h>
#include "pretty-printer.h"
#include "jrt-libc-includes.h"
#include "lexer.h"
#include "ecma-helpers.h"
#include "ecma-globals.h"
#include "lit-literal.h"
static const char* opcode_names[] =
{
#define VM_OP_0(opcode_name, opcode_name_uppercase) \
#opcode_name,
#define VM_OP_1(opcode_name, opcode_name_uppercase, arg1, arg1_type) \
#opcode_name,
#define VM_OP_2(opcode_name, opcode_name_uppercase, arg1, arg1_type, arg2, arg2_type) \
#opcode_name,
#define VM_OP_3(opcode_name, opcode_name_uppercase, arg1, arg1_type, arg2, arg2_type, arg3, arg3_type) \
#opcode_name,
#include "vm-opcodes.inc.h"
};
static uint8_t opcode_sizes[] =
{
#define VM_OP_0(opcode_name, opcode_name_uppercase) \
0,
#define VM_OP_1(opcode_name, opcode_name_uppercase, arg1, arg1_type) \
1,
#define VM_OP_2(opcode_name, opcode_name_uppercase, arg1, arg1_type, arg2, arg2_type) \
2,
#define VM_OP_3(opcode_name, opcode_name_uppercase, arg1, arg1_type, arg2, arg2_type, arg3, arg3_type) \
3,
#include "vm-opcodes.inc.h"
};
const bytecode_data_header_t *bc_to_print_header_p = NULL;
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_cp_to_str (lit_cpointer_t cp)
{
lit_literal_t lit = lit_get_literal_by_cp (cp);
return lit_literal_to_str_internal_buf (lit);
}
static const char *
tmp_id_to_str (vm_idx_t id)
{
JERRY_ASSERT (id != VM_IDX_REWRITE_LITERAL_UID);
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 (vm_instr_t instr, lit_cpointer_t lit_ids[], vm_instr_counter_t oc, uint8_t current_arg)
{
JERRY_ASSERT (current_arg >= 1 && current_arg <= 3);
if (instr.data.raw_args[current_arg - 1] == VM_IDX_REWRITE_LITERAL_UID)
{
JERRY_ASSERT (lit_ids != NULL);
JERRY_ASSERT (lit_ids[current_arg - 1].packed_value != MEM_CP_NULL);
return lit_cp_to_str (lit_ids[current_arg - 1]);
}
else if (instr.data.raw_args[current_arg - 1] >= 128)
{
return tmp_id_to_str (instr.data.raw_args[current_arg - 1]);
}
else
{
return lit_cp_to_str (bc_get_literal_cp_by_uid (instr.data.raw_args[current_arg - 1],
bc_to_print_header_p,
oc));
}
}
static void
pp_printf (const char *format, vm_instr_t instr, lit_cpointer_t lit_ids[], vm_instr_counter_t oc, uint8_t start_arg)
{
uint8_t current_arg = start_arg;
JERRY_ASSERT (current_arg <= 3);
while (*format)
{
if (*format != '%')
{
jerry_port_putchar (*format);
format++;
continue;
}
format++;
switch (*format)
{
case 'd':
{
JERRY_ASSERT (current_arg >= 1 && current_arg <= 3);
printf ("%d", instr.data.raw_args[current_arg - 1]);
break;
}
case 's':
{
printf ("%s", var_to_str (instr, lit_ids, oc, current_arg));
break;
}
default:
{
jerry_port_putchar ('%');
continue;
}
}
current_arg++;
format++;
}
}
#define PP_OP(op_name, format) \
case op_name: pp_printf (format, opm.op, opm.lit_id, oc, 1); break;
#define VAR(i) var_to_str (opm.op, opm.lit_id, oc, i)
#define OC(i, j) __extension__({ vm_calc_instr_counter_from_idx_idx (opm.op.data.raw_args[i - 1], \
opm.op.data.raw_args[j - 1]); })
static int vargs_num = 0;
static int seen_vargs = 0;
static void
dump_asm (vm_instr_counter_t oc, vm_instr_t instr)
{
uint8_t i = 0;
uint8_t opcode_id = instr.op_idx;
printf ("%3d: %20s ", oc, opcode_names[opcode_id]);
for (i = 1; i <= opcode_sizes[opcode_id]; i++)
{
printf ("%4d ", instr.data.raw_args[i - 1]);
}
for (; i < 4; i++)
{
printf (" ");
}
}
void
pp_op_meta (const bytecode_data_header_t *bytecode_data_p,
vm_instr_counter_t oc,
op_meta opm,
bool rewrite)
{
bc_to_print_header_p = bytecode_data_p;
dump_asm (oc, opm.op);
printf (" // ");
switch (opm.op.op_idx)
{
PP_OP (VM_OP_ADDITION, "%s = %s + %s;");
PP_OP (VM_OP_SUBSTRACTION, "%s = %s - %s;");
PP_OP (VM_OP_DIVISION, "%s = %s / %s;");
PP_OP (VM_OP_MULTIPLICATION, "%s = %s * %s;");
PP_OP (VM_OP_REMAINDER, "%s = %s %% %s;");
PP_OP (VM_OP_UNARY_MINUS, "%s = -%s;");
PP_OP (VM_OP_UNARY_PLUS, "%s = +%s;");
PP_OP (VM_OP_B_SHIFT_LEFT, "%s = %s << %s;");
PP_OP (VM_OP_B_SHIFT_RIGHT, "%s = %s >> %s;");
PP_OP (VM_OP_B_SHIFT_URIGHT, "%s = %s >>> %s;");
PP_OP (VM_OP_B_AND, "%s = %s & %s;");
PP_OP (VM_OP_B_OR, "%s = %s | %s;");
PP_OP (VM_OP_B_XOR, "%s = %s ^ %s;");
PP_OP (VM_OP_B_NOT, "%s = ~ %s;");
PP_OP (VM_OP_LOGICAL_NOT, "%s = ! %s;");
PP_OP (VM_OP_EQUAL_VALUE, "%s = %s == %s;");
PP_OP (VM_OP_NOT_EQUAL_VALUE, "%s = %s != %s;");
PP_OP (VM_OP_EQUAL_VALUE_TYPE, "%s = %s === %s;");
PP_OP (VM_OP_NOT_EQUAL_VALUE_TYPE, "%s = %s !== %s;");
PP_OP (VM_OP_LESS_THAN, "%s = %s < %s;");
PP_OP (VM_OP_GREATER_THAN, "%s = %s > %s;");
PP_OP (VM_OP_LESS_OR_EQUAL_THAN, "%s = %s <= %s;");
PP_OP (VM_OP_GREATER_OR_EQUAL_THAN, "%s = %s >= %s;");
PP_OP (VM_OP_INSTANCEOF, "%s = %s instanceof %s;");
PP_OP (VM_OP_IN, "%s = %s in %s;");
PP_OP (VM_OP_POST_INCR, "%s = %s++;");
PP_OP (VM_OP_POST_DECR, "%s = %s--;");
PP_OP (VM_OP_PRE_INCR, "%s = ++%s;");
PP_OP (VM_OP_PRE_DECR, "%s = --%s;");
PP_OP (VM_OP_THROW_VALUE, "throw %s;");
PP_OP (VM_OP_REG_VAR_DECL, "%d tmp regs, %d local variable regs, %d argument variable regs");
PP_OP (VM_OP_VAR_DECL, "var %s;");
PP_OP (VM_OP_RETVAL, "return %s;");
PP_OP (VM_OP_RET, "ret;");
PP_OP (VM_OP_PROP_GETTER, "%s = %s[%s];");
PP_OP (VM_OP_PROP_SETTER, "%s[%s] = %s;");
PP_OP (VM_OP_DELETE_VAR, "%s = delete %s;");
PP_OP (VM_OP_DELETE_PROP, "%s = delete %s.%s;");
PP_OP (VM_OP_TYPEOF, "%s = typeof %s;");
PP_OP (VM_OP_WITH, "with (%s);");
PP_OP (VM_OP_FOR_IN, "for_in (%s);");
case VM_OP_IS_TRUE_JMP_UP: printf ("if (%s) goto %d;", VAR (1), oc - OC (2, 3)); break;
case VM_OP_IS_FALSE_JMP_UP: printf ("if (%s == false) goto %d;", VAR (1), oc - OC (2, 3)); break;
case VM_OP_IS_TRUE_JMP_DOWN: printf ("if (%s) goto %d;", VAR (1), oc + OC (2, 3)); break;
case VM_OP_IS_FALSE_JMP_DOWN: printf ("if (%s == false) goto %d;", VAR (1), oc + OC (2, 3)); break;
case VM_OP_JMP_UP: printf ("goto %d;", oc - OC (1, 2)); break;
case VM_OP_JMP_DOWN: printf ("goto %d;", oc + OC (1, 2)); break;
case VM_OP_JMP_BREAK_CONTINUE: printf ("goto_nested %d;", oc + OC (1, 2)); break;
case VM_OP_TRY_BLOCK: printf ("try (end: %d);", oc + OC (1, 2)); break;
case VM_OP_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;
case ECMA_SIMPLE_VALUE_ARRAY_HOLE: printf ("hole"); break;
default: JERRY_UNREACHABLE ();
}
printf (": SIMPLE;");
break;
}
}
break;
}
case VM_OP_CALL_N:
{
vargs_num = opm.op.data.call_n.arg_list;
seen_vargs = 0;
break;
}
case VM_OP_CONSTRUCT_N:
{
if (opm.op.data.construct_n.arg_list == 0)
{
pp_printf ("%s = new %s;", opm.op, opm.lit_id, oc, 1);
}
else
{
vargs_num = opm.op.data.construct_n.arg_list;
seen_vargs = 0;
}
break;
}
case VM_OP_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 VM_OP_FUNC_EXPR_REF:
{
printf ("%s = function ();", VAR (1));
break;
}
case VM_OP_FUNC_EXPR_N:
{
if (opm.op.data.func_expr_n.arg_list == 0)
{
if (opm.op.data.func_expr_n.name_lit_idx == VM_IDX_EMPTY)
{
printf ("%s = function ();", VAR (1));
}
else
{
pp_printf ("%s = function %s ();", opm.op, opm.lit_id, oc, 1);
}
}
else
{
vargs_num = opm.op.data.func_expr_n.arg_list;
seen_vargs = 0;
}
break;
}
case VM_OP_ARRAY_DECL:
{
if (opm.op.data.array_decl.list_1 == 0
&& opm.op.data.array_decl.list_2 == 0)
{
printf ("%s = [];", VAR (1));
}
else
{
vargs_num = (((int) opm.op.data.array_decl.list_1 << JERRY_BITSINBYTE)
+ (int) opm.op.data.array_decl.list_2);
seen_vargs = 0;
}
break;
}
case VM_OP_OBJ_DECL:
{
if (opm.op.data.obj_decl.list_1 == 0
&& opm.op.data.obj_decl.list_2 == 0)
{
printf ("%s = {};", VAR (1));
}
else
{
vargs_num = (((int) opm.op.data.obj_decl.list_1 << JERRY_BITSINBYTE)
+ (int) opm.op.data.obj_decl.list_2);
seen_vargs = 0;
}
break;
}
case VM_OP_META:
{
switch (opm.op.data.meta.type)
{
case OPCODE_META_TYPE_UNDEFINED:
{
printf ("unknown meta;");
break;
}
case OPCODE_META_TYPE_CALL_SITE_INFO:
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:
{
if (opm.op.data.meta.type != OPCODE_META_TYPE_CALL_SITE_INFO)
{
seen_vargs++;
}
if (seen_vargs == vargs_num)
{
bool found = false;
vm_instr_counter_t start = oc;
while ((int16_t) start >= 0 && !found)
{
start--;
switch (bc_get_instr (bytecode_data_p, start).op_idx)
{
case VM_OP_CALL_N:
case VM_OP_CONSTRUCT_N:
case VM_OP_FUNC_DECL_N:
case VM_OP_FUNC_EXPR_N:
case VM_OP_ARRAY_DECL:
case VM_OP_OBJ_DECL:
{
found = true;
break;
}
}
}
vm_instr_t start_op = bc_get_instr (bytecode_data_p, start);
switch (start_op.op_idx)
{
case VM_OP_CALL_N:
{
pp_printf ("%s = %s (", start_op, NULL, start, 1);
break;
}
case VM_OP_CONSTRUCT_N:
{
pp_printf ("%s = new %s (", start_op, NULL, start, 1);
break;
}
case VM_OP_FUNC_DECL_N:
{
pp_printf ("function %s (", start_op, NULL, start, 1);
break;
}
case VM_OP_FUNC_EXPR_N:
{
if (start_op.data.func_expr_n.name_lit_idx == VM_IDX_EMPTY)
{
pp_printf ("%s = function (", start_op, NULL, start, 1);
}
else
{
pp_printf ("%s = function %s (", start_op, NULL, start, 1);
}
break;
}
case VM_OP_ARRAY_DECL:
{
pp_printf ("%s = [", start_op, NULL, start, 1);
break;
}
case VM_OP_OBJ_DECL:
{
pp_printf ("%s = {", start_op, NULL, start, 1);
break;
}
default:
{
JERRY_UNREACHABLE ();
}
}
for (vm_instr_counter_t counter = start; counter <= oc; counter++)
{
vm_instr_t meta_op = bc_get_instr (bytecode_data_p, counter);
switch (meta_op.op_idx)
{
case VM_OP_META:
{
switch (meta_op.data.meta.type)
{
case OPCODE_META_TYPE_CALL_SITE_INFO:
{
opcode_call_flags_t call_flags = (opcode_call_flags_t) meta_op.data.meta.data_1;
if (call_flags & OPCODE_CALL_FLAGS_HAVE_THIS_ARG)
{
pp_printf ("this_arg = %s", meta_op, NULL, counter, 3);
}
if (call_flags & OPCODE_CALL_FLAGS_DIRECT_CALL_TO_EVAL_FORM)
{
printf ("['direct call to eval' form]");
}
break;
}
case OPCODE_META_TYPE_VARG:
{
pp_printf ("%s", meta_op, NULL, counter, 2);
break;
}
case OPCODE_META_TYPE_VARG_PROP_DATA:
{
pp_printf ("%s:%s", meta_op, NULL, counter, 2);
break;
}
case OPCODE_META_TYPE_VARG_PROP_GETTER:
{
pp_printf ("%s = get %s ();", meta_op, NULL, counter, 2);
break;
}
case OPCODE_META_TYPE_VARG_PROP_SETTER:
{
pp_printf ("%s = set (%s);", meta_op, NULL, counter, 2);
break;
}
default:
{
continue;
}
}
if (counter != oc)
{
printf (", ");
}
break;
}
}
}
switch (start_op.op_idx)
{
case VM_OP_ARRAY_DECL:
{
printf ("];");
break;
}
case VM_OP_OBJ_DECL:
{
printf ("};");
break;
}
default:
{
printf (");");
}
}
}
break;
}
case OPCODE_META_TYPE_END_WITH:
{
printf ("end with;");
break;
}
case OPCODE_META_TYPE_END_FOR_IN:
{
printf ("end for-in;");
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;
}
default:
{
JERRY_UNREACHABLE ();
}
}
break;
}
default:
{
JERRY_UNREACHABLE ();
}
}
if (rewrite)
{
printf (" // REWRITE");
}
printf ("\n");
}
#endif /* JERRY_ENABLE_PRETTY_PRINTER */
-28
View File
@@ -1,28 +0,0 @@
/* 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 "bytecode-data.h"
#include "vm.h"
#include "scopes-tree.h"
void pp_op_meta (const bytecode_data_header_t *, vm_instr_counter_t, op_meta, bool);
#endif // JERRY_ENABLE_PRETTY_PRINTER
#endif // PRETTY_PRINTER
+61
View File
@@ -0,0 +1,61 @@
/* Copyright 2015-2016 Samsung Electronics Co., Ltd.
* Copyright 2015-2016 University of Szeged.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef VM_DEFINES_H
#define VM_DEFINES_H
#include "byte-code.h"
#include "ecma-globals.h"
/** \addtogroup vm Virtual machine
* @{
*
* \addtogroup vm_executor Executor
* @{
*/
/**
* Helpers for updating uint16_t values.
*/
#define VM_PLUS_EQUAL_U16(base, value) (base) = (uint16_t) ((base) + (value))
#define VM_MINUS_EQUAL_U16(base, value) (base) = (uint16_t) ((base) - (value))
/**
* Instruction counter / position
*/
typedef const uint8_t *vm_instr_counter_t;
/**
* Context of interpreter, related to a JS stack frame
*/
typedef struct
{
const ecma_compiled_code_t *bytecode_header_p; /**< currently executed byte-code data */
uint8_t *byte_code_p; /**< current byte code pointer */
uint8_t *byte_code_start_p; /**< byte code start pointer */
ecma_value_t *registers_p; /**< register start pointer */
lit_cpointer_t *literal_start_p; /**< literal list start pointer */
ecma_object_t *lex_env_p; /**< current lexical environment */
ecma_value_t this_binding; /**< this binding */
uint16_t context_depth; /**< current context depth */
bool is_eval_code; /**< eval mode flag */
} vm_frame_ctx_t;
/**
* @}
* @}
*/
#endif /* !VM_DEFINES_H */
-317
View File
@@ -1,317 +0,0 @@
/* Copyright 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.
*/
/*
* List of VM opcodes
*/
#ifndef VM_OP_0
# define VM_OP_0(opcode_name, opcode_name_uppercase)
#endif /* !VM_OP_0 */
#ifndef VM_OP_1
# define VM_OP_1(opcode_name, opcode_name_uppercase, arg1, arg1_type)
#endif /* !VM_OP_1 */
#ifndef VM_OP_2
# define VM_OP_2(opcode_name, opcode_name_uppercase, arg1, arg1_type, arg2, arg2_type)
#endif /* !VM_OP_2 */
#ifndef VM_OP_3
# define VM_OP_3(opcode_name, opcode_name_uppercase, arg1, arg1_type, arg2, arg2_type, arg3, arg3_type)
#endif /* !VM_OP_3 */
VM_OP_3 (call_n, CALL_N,
lhs, VM_OP_ARG_TYPE_VARIABLE,
function_var_idx, VM_OP_ARG_TYPE_VARIABLE,
arg_list, VM_OP_ARG_TYPE_INTEGER_CONST)
VM_OP_3 (construct_n, CONSTRUCT_N,
lhs, VM_OP_ARG_TYPE_VARIABLE,
name_lit_idx, VM_OP_ARG_TYPE_VARIABLE,
arg_list, VM_OP_ARG_TYPE_INTEGER_CONST)
VM_OP_2 (func_decl_n, FUNC_DECL_N,
name_lit_idx, VM_OP_ARG_TYPE_STRING,
arg_list, VM_OP_ARG_TYPE_INTEGER_CONST)
VM_OP_3 (func_expr_n, FUNC_EXPR_N,
lhs, VM_OP_ARG_TYPE_VARIABLE,
name_lit_idx, VM_OP_ARG_TYPE_STRING |
VM_OP_ARG_TYPE_EMPTY,
arg_list, VM_OP_ARG_TYPE_INTEGER_CONST)
VM_OP_3 (func_expr_ref, FUNC_EXPR_REF,
lhs, VM_OP_ARG_TYPE_VARIABLE,
idx1, VM_OP_ARG_TYPE_INTEGER_CONST,
idx2, VM_OP_ARG_TYPE_INTEGER_CONST)
VM_OP_1 (retval, RETVAL,
ret_value, VM_OP_ARG_TYPE_VARIABLE)
VM_OP_0 (ret, RET)
VM_OP_3 (array_decl, ARRAY_DECL,
lhs, VM_OP_ARG_TYPE_VARIABLE,
list_1, VM_OP_ARG_TYPE_INTEGER_CONST,
list_2, VM_OP_ARG_TYPE_INTEGER_CONST)
VM_OP_3 (obj_decl, OBJ_DECL,
lhs, VM_OP_ARG_TYPE_VARIABLE,
list_1, VM_OP_ARG_TYPE_INTEGER_CONST,
list_2, VM_OP_ARG_TYPE_INTEGER_CONST)
VM_OP_3 (prop_getter, PROP_GETTER,
lhs, VM_OP_ARG_TYPE_VARIABLE,
obj, VM_OP_ARG_TYPE_VARIABLE,
prop, VM_OP_ARG_TYPE_VARIABLE)
VM_OP_3 (prop_setter, PROP_SETTER,
obj, VM_OP_ARG_TYPE_VARIABLE,
prop, VM_OP_ARG_TYPE_VARIABLE,
rhs, VM_OP_ARG_TYPE_VARIABLE)
VM_OP_2 (delete_var, DELETE_VAR,
lhs, VM_OP_ARG_TYPE_VARIABLE,
name, VM_OP_ARG_TYPE_VARIABLE)
VM_OP_3 (delete_prop, DELETE_PROP,
lhs, VM_OP_ARG_TYPE_VARIABLE,
base, VM_OP_ARG_TYPE_VARIABLE,
name, VM_OP_ARG_TYPE_VARIABLE)
VM_OP_2 (typeof, TYPEOF,
lhs, VM_OP_ARG_TYPE_VARIABLE,
obj, VM_OP_ARG_TYPE_VARIABLE)
VM_OP_3 (for_in, FOR_IN,
expr, VM_OP_ARG_TYPE_VARIABLE,
oc_idx_1, VM_OP_ARG_TYPE_INTEGER_CONST,
oc_idx_2, VM_OP_ARG_TYPE_INTEGER_CONST)
VM_OP_3 (with, WITH,
expr, VM_OP_ARG_TYPE_VARIABLE,
oc_idx_1, VM_OP_ARG_TYPE_INTEGER_CONST,
oc_idx_2, VM_OP_ARG_TYPE_INTEGER_CONST)
VM_OP_2 (try_block, TRY_BLOCK,
oc_idx_1, VM_OP_ARG_TYPE_INTEGER_CONST,
oc_idx_2, VM_OP_ARG_TYPE_INTEGER_CONST)
VM_OP_1 (throw_value, THROW_VALUE,
var, VM_OP_ARG_TYPE_VARIABLE)
VM_OP_3 (assignment, ASSIGNMENT,
var_left, VM_OP_ARG_TYPE_VARIABLE,
type_value_right, VM_OP_ARG_TYPE_TYPE_OF_NEXT,
value_right, VM_OP_ARG_TYPE_VARIABLE |
VM_OP_ARG_TYPE_STRING |
VM_OP_ARG_TYPE_NUMBER |
VM_OP_ARG_TYPE_INTEGER_CONST)
VM_OP_3 (b_shift_left, B_SHIFT_LEFT,
dst, VM_OP_ARG_TYPE_VARIABLE,
var_left, VM_OP_ARG_TYPE_VARIABLE,
var_right, VM_OP_ARG_TYPE_VARIABLE)
VM_OP_3 (b_shift_right, B_SHIFT_RIGHT,
dst, VM_OP_ARG_TYPE_VARIABLE,
var_left, VM_OP_ARG_TYPE_VARIABLE,
var_right, VM_OP_ARG_TYPE_VARIABLE)
VM_OP_3 (b_shift_uright, B_SHIFT_URIGHT,
dst, VM_OP_ARG_TYPE_VARIABLE,
var_left, VM_OP_ARG_TYPE_VARIABLE,
var_right, VM_OP_ARG_TYPE_VARIABLE)
VM_OP_3 (b_and, B_AND,
dst, VM_OP_ARG_TYPE_VARIABLE,
var_left, VM_OP_ARG_TYPE_VARIABLE,
var_right, VM_OP_ARG_TYPE_VARIABLE)
VM_OP_3 (b_or, B_OR,
dst, VM_OP_ARG_TYPE_VARIABLE,
var_left, VM_OP_ARG_TYPE_VARIABLE,
var_right, VM_OP_ARG_TYPE_VARIABLE)
VM_OP_3 (b_xor, B_XOR,
dst, VM_OP_ARG_TYPE_VARIABLE,
var_left, VM_OP_ARG_TYPE_VARIABLE,
var_right, VM_OP_ARG_TYPE_VARIABLE)
VM_OP_2 (b_not, B_NOT,
dst, VM_OP_ARG_TYPE_VARIABLE,
var_right, VM_OP_ARG_TYPE_VARIABLE)
VM_OP_2 (logical_not, LOGICAL_NOT,
dst, VM_OP_ARG_TYPE_VARIABLE,
var_right, VM_OP_ARG_TYPE_VARIABLE)
VM_OP_3 (equal_value, EQUAL_VALUE,
dst, VM_OP_ARG_TYPE_VARIABLE,
var_left, VM_OP_ARG_TYPE_VARIABLE,
var_right, VM_OP_ARG_TYPE_VARIABLE)
VM_OP_3 (not_equal_value, NOT_EQUAL_VALUE,
dst, VM_OP_ARG_TYPE_VARIABLE,
var_left, VM_OP_ARG_TYPE_VARIABLE,
var_right, VM_OP_ARG_TYPE_VARIABLE)
VM_OP_3 (equal_value_type, EQUAL_VALUE_TYPE,
dst, VM_OP_ARG_TYPE_VARIABLE,
var_left, VM_OP_ARG_TYPE_VARIABLE,
var_right, VM_OP_ARG_TYPE_VARIABLE)
VM_OP_3 (not_equal_value_type, NOT_EQUAL_VALUE_TYPE,
dst, VM_OP_ARG_TYPE_VARIABLE,
var_left, VM_OP_ARG_TYPE_VARIABLE,
var_right, VM_OP_ARG_TYPE_VARIABLE)
VM_OP_3 (less_than, LESS_THAN,
dst, VM_OP_ARG_TYPE_VARIABLE,
var_left, VM_OP_ARG_TYPE_VARIABLE,
var_right, VM_OP_ARG_TYPE_VARIABLE)
VM_OP_3 (greater_than, GREATER_THAN,
dst, VM_OP_ARG_TYPE_VARIABLE,
var_left, VM_OP_ARG_TYPE_VARIABLE,
var_right, VM_OP_ARG_TYPE_VARIABLE)
VM_OP_3 (less_or_equal_than, LESS_OR_EQUAL_THAN,
dst, VM_OP_ARG_TYPE_VARIABLE,
var_left, VM_OP_ARG_TYPE_VARIABLE,
var_right, VM_OP_ARG_TYPE_VARIABLE)
VM_OP_3 (greater_or_equal_than, GREATER_OR_EQUAL_THAN,
dst, VM_OP_ARG_TYPE_VARIABLE,
var_left, VM_OP_ARG_TYPE_VARIABLE,
var_right, VM_OP_ARG_TYPE_VARIABLE)
VM_OP_3 (instanceof, INSTANCEOF,
dst, VM_OP_ARG_TYPE_VARIABLE,
var_left, VM_OP_ARG_TYPE_VARIABLE,
var_right, VM_OP_ARG_TYPE_VARIABLE)
VM_OP_3 (in, IN,
dst, VM_OP_ARG_TYPE_VARIABLE,
var_left, VM_OP_ARG_TYPE_VARIABLE,
var_right, VM_OP_ARG_TYPE_VARIABLE)
VM_OP_2 (post_incr, POST_INCR,
dst, VM_OP_ARG_TYPE_VARIABLE,
var_right, VM_OP_ARG_TYPE_VARIABLE)
VM_OP_2 (post_decr, POST_DECR,
dst, VM_OP_ARG_TYPE_VARIABLE,
var_right, VM_OP_ARG_TYPE_VARIABLE)
VM_OP_2 (pre_incr, PRE_INCR,
dst, VM_OP_ARG_TYPE_VARIABLE,
var_right, VM_OP_ARG_TYPE_VARIABLE)
VM_OP_2 (pre_decr, PRE_DECR,
dst, VM_OP_ARG_TYPE_VARIABLE,
var_right, VM_OP_ARG_TYPE_VARIABLE)
VM_OP_3 (addition, ADDITION,
dst, VM_OP_ARG_TYPE_VARIABLE,
var_left, VM_OP_ARG_TYPE_VARIABLE,
var_right, VM_OP_ARG_TYPE_VARIABLE)
VM_OP_3 (substraction, SUBSTRACTION,
dst, VM_OP_ARG_TYPE_VARIABLE,
var_left, VM_OP_ARG_TYPE_VARIABLE,
var_right, VM_OP_ARG_TYPE_VARIABLE)
VM_OP_3 (division, DIVISION,
dst, VM_OP_ARG_TYPE_VARIABLE,
var_left, VM_OP_ARG_TYPE_VARIABLE,
var_right, VM_OP_ARG_TYPE_VARIABLE)
VM_OP_3 (multiplication, MULTIPLICATION,
dst, VM_OP_ARG_TYPE_VARIABLE,
var_left, VM_OP_ARG_TYPE_VARIABLE,
var_right, VM_OP_ARG_TYPE_VARIABLE)
VM_OP_3 (remainder, REMAINDER,
dst, VM_OP_ARG_TYPE_VARIABLE,
var_left, VM_OP_ARG_TYPE_VARIABLE,
var_right, VM_OP_ARG_TYPE_VARIABLE)
VM_OP_2 (unary_minus, UNARY_MINUS,
dst, VM_OP_ARG_TYPE_VARIABLE,
var, VM_OP_ARG_TYPE_VARIABLE)
VM_OP_2 (unary_plus, UNARY_PLUS,
dst, VM_OP_ARG_TYPE_VARIABLE,
var, VM_OP_ARG_TYPE_VARIABLE)
VM_OP_2 (jmp_up, JMP_UP,
oc_idx_1, VM_OP_ARG_TYPE_INTEGER_CONST,
oc_idx_2, VM_OP_ARG_TYPE_INTEGER_CONST)
VM_OP_2 (jmp_down, JMP_DOWN,
oc_idx_1, VM_OP_ARG_TYPE_INTEGER_CONST,
oc_idx_2, VM_OP_ARG_TYPE_INTEGER_CONST)
VM_OP_2 (jmp_break_continue, JMP_BREAK_CONTINUE,
oc_idx_1, VM_OP_ARG_TYPE_INTEGER_CONST,
oc_idx_2, VM_OP_ARG_TYPE_INTEGER_CONST)
VM_OP_3 (is_true_jmp_up, IS_TRUE_JMP_UP,
value, VM_OP_ARG_TYPE_VARIABLE,
oc_idx_1, VM_OP_ARG_TYPE_INTEGER_CONST,
oc_idx_2, VM_OP_ARG_TYPE_INTEGER_CONST)
VM_OP_3 (is_true_jmp_down, IS_TRUE_JMP_DOWN,
value, VM_OP_ARG_TYPE_VARIABLE,
oc_idx_1, VM_OP_ARG_TYPE_INTEGER_CONST,
oc_idx_2, VM_OP_ARG_TYPE_INTEGER_CONST)
VM_OP_3 (is_false_jmp_up, IS_FALSE_JMP_UP,
value, VM_OP_ARG_TYPE_VARIABLE,
oc_idx_1, VM_OP_ARG_TYPE_INTEGER_CONST,
oc_idx_2, VM_OP_ARG_TYPE_INTEGER_CONST)
VM_OP_3 (is_false_jmp_down, IS_FALSE_JMP_DOWN,
value, VM_OP_ARG_TYPE_VARIABLE,
oc_idx_1, VM_OP_ARG_TYPE_INTEGER_CONST,
oc_idx_2, VM_OP_ARG_TYPE_INTEGER_CONST)
VM_OP_1 (var_decl, VAR_DECL,
variable_name, VM_OP_ARG_TYPE_STRING)
VM_OP_3 (reg_var_decl, REG_VAR_DECL,
tmp_regs_num, VM_OP_ARG_TYPE_INTEGER_CONST,
local_var_regs_num, VM_OP_ARG_TYPE_INTEGER_CONST,
arg_regs_num, VM_OP_ARG_TYPE_INTEGER_CONST)
VM_OP_3 (meta, META,
type, VM_OP_ARG_TYPE_INTEGER_CONST |
VM_OP_ARG_TYPE_TYPE_OF_NEXT,
data_1, VM_OP_ARG_TYPE_INTEGER_CONST |
VM_OP_ARG_TYPE_STRING |
VM_OP_ARG_TYPE_VARIABLE,
data_2, VM_OP_ARG_TYPE_INTEGER_CONST |
VM_OP_ARG_TYPE_VARIABLE)
#undef VM_OP_0
#undef VM_OP_1
#undef VM_OP_2
#undef VM_OP_3
+195 -253
View File
@@ -1,4 +1,5 @@
/* Copyright 2015 Samsung Electronics Co., Ltd.
/* Copyright 2014-2016 Samsung Electronics Co., Ltd.
* Copyright 2015-2016 University of Szeged.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -13,8 +14,10 @@
* limitations under the License.
*/
#include "ecma-globals.h"
#include "ecma-alloc.h"
#include "ecma-gc.h"
#include "ecma-helpers.h"
#include "vm-defines.h"
#include "vm-stack.h"
/** \addtogroup vm Virtual machine
@@ -25,287 +28,226 @@
*/
/**
* Size of a stack frame's dynamic chunk
*/
#define VM_STACK_DYNAMIC_CHUNK_SIZE (mem_heap_recommend_allocation_size (sizeof (vm_stack_chunk_header_t) + \
sizeof (ecma_value_t)))
/**
* Number of value slots in a stack frame's dynamic chunk
*/
#define VM_STACK_SLOTS_IN_DYNAMIC_CHUNK ((VM_STACK_DYNAMIC_CHUNK_SIZE - sizeof (vm_stack_chunk_header_t)) / \
sizeof (ecma_value_t))
/**
* The top-most stack frame
*/
vm_stack_frame_t* vm_stack_top_frame_p;
/**
* Initialize stack
*/
void
vm_stack_init (void)
{
vm_stack_top_frame_p = NULL;
} /* vm_stack_init */
/**
* Finalize stack
*/
void
vm_stack_finalize ()
{
JERRY_ASSERT (vm_stack_top_frame_p == NULL);
} /* vm_stack_finalize */
/**
* Get stack's top frame
* Abort (finalize) the current stack context, and remove it.
*
* @return pointer to the top frame descriptor
* @return new stack top
*/
vm_stack_frame_t*
vm_stack_get_top_frame (void)
ecma_value_t *
vm_stack_context_abort (vm_frame_ctx_t *frame_ctx_p, /**< frame context */
ecma_value_t *vm_stack_top_p) /**< current stack top */
{
return vm_stack_top_frame_p;
} /* vm_stack_get_top_frame */
/**
* Add the frame to stack
*/
void
vm_stack_add_frame (vm_stack_frame_t *frame_p, /**< frame to initialize */
ecma_value_t *regs_p, /**< array of register variables' values */
uint32_t regs_num, /**< total number of register variables */
uint32_t local_vars_regs_num, /**< number of register variables,
* used for local variables */
uint32_t arg_regs_num, /**< number of register variables,
* used for arguments */
ecma_collection_header_t *arguments_p) /**< collection of arguments
* (for case, their values
* are moved to registers) */
{
frame_p->prev_frame_p = vm_stack_top_frame_p;
vm_stack_top_frame_p = frame_p;
frame_p->top_chunk_p = NULL;
frame_p->dynamically_allocated_value_slots_p = frame_p->inlined_values;
frame_p->current_slot_index = 0;
frame_p->regs_p = regs_p;
frame_p->regs_number = regs_num;
JERRY_ASSERT (regs_num >= VM_SPECIAL_REGS_NUMBER);
for (uint32_t i = 0; i < regs_num - local_vars_regs_num - arg_regs_num; i++)
switch (VM_GET_CONTEXT_TYPE (vm_stack_top_p[-1]))
{
regs_p[i] = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY);
}
for (uint32_t i = regs_num - local_vars_regs_num - arg_regs_num;
i < regs_num;
i++)
{
regs_p[i] = ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED);
}
if (arg_regs_num != 0)
{
ecma_collection_iterator_t args_iterator;
ecma_collection_iterator_init (&args_iterator, arguments_p);
for (uint32_t i = regs_num - arg_regs_num;
i < regs_num && ecma_collection_iterator_next (&args_iterator);
i++)
case VM_CONTEXT_FINALLY_THROW:
case VM_CONTEXT_FINALLY_RETURN:
{
regs_p[i] = ecma_copy_value (*args_iterator.current_value_p, false);
ecma_free_value (vm_stack_top_p[-2], true);
VM_MINUS_EQUAL_U16 (frame_ctx_p->context_depth, PARSER_TRY_CONTEXT_STACK_ALLOCATION);
vm_stack_top_p -= PARSER_TRY_CONTEXT_STACK_ALLOCATION;
break;
}
case VM_CONTEXT_FINALLY_JUMP:
case VM_CONTEXT_TRY:
{
VM_MINUS_EQUAL_U16 (frame_ctx_p->context_depth, PARSER_TRY_CONTEXT_STACK_ALLOCATION);
vm_stack_top_p -= PARSER_TRY_CONTEXT_STACK_ALLOCATION;
break;
}
case VM_CONTEXT_CATCH:
case VM_CONTEXT_WITH:
{
ecma_deref_object (frame_ctx_p->lex_env_p);
frame_ctx_p->lex_env_p = ecma_get_object_from_value (vm_stack_top_p[-2]);
JERRY_ASSERT (PARSER_TRY_CONTEXT_STACK_ALLOCATION == PARSER_WITH_CONTEXT_STACK_ALLOCATION);
VM_MINUS_EQUAL_U16 (frame_ctx_p->context_depth, PARSER_TRY_CONTEXT_STACK_ALLOCATION);
vm_stack_top_p -= PARSER_TRY_CONTEXT_STACK_ALLOCATION;
break;
}
case VM_CONTEXT_FOR_IN:
{
mem_cpointer_t current = (uint16_t) vm_stack_top_p[-2];
while (current != MEM_CP_NULL)
{
ecma_collection_chunk_t *chunk_p = MEM_CP_GET_NON_NULL_POINTER (ecma_collection_chunk_t,
current);
ecma_free_value (*(ecma_value_t *) chunk_p->data, true);
current = chunk_p->next_chunk_cp;
ecma_dealloc_collection_chunk (chunk_p);
}
ecma_free_value (vm_stack_top_p[-3], true);
VM_MINUS_EQUAL_U16 (frame_ctx_p->context_depth, PARSER_FOR_IN_CONTEXT_STACK_ALLOCATION);
vm_stack_top_p -= PARSER_FOR_IN_CONTEXT_STACK_ALLOCATION;
break;
}
default:
{
JERRY_UNREACHABLE ();
break;
}
}
} /* vm_stack_add_frame */
return vm_stack_top_p;
} /* vm_stack_context_abort */
/**
* Free the stack frame
* Decode branch offset.
*
* Note:
* the frame should be the top-most frame
* @return branch offset
*/
void
vm_stack_free_frame (vm_stack_frame_t *frame_p) /**< frame to initialize */
static uint32_t
vm_decode_branch_offset (uint8_t *branch_offset_p, /**< start offset of byte code */
uint32_t length) /**< length of the branch */
{
/* the frame should be the top-most frame */
JERRY_ASSERT (vm_stack_top_frame_p == frame_p);
uint32_t branch_offset = *branch_offset_p;
vm_stack_top_frame_p = frame_p->prev_frame_p;
JERRY_ASSERT (length >= 1 && length <= 3);
while (frame_p->top_chunk_p != NULL)
switch (length)
{
vm_stack_pop (frame_p);
case 3:
{
branch_offset <<= 8;
branch_offset |= *(branch_offset_p++);
/* FALLTHRU */
}
case 2:
{
branch_offset <<= 8;
branch_offset |= *(branch_offset_p++);
break;
}
}
for (uint32_t reg_index = 0;
reg_index < frame_p->regs_number;
reg_index++)
{
ecma_free_value (frame_p->regs_p[reg_index], false);
}
} /* vm_stack_free_frame */
return branch_offset;
} /* vm_decode_branch_offset */
/**
* Get value of specified register variable
* Find a finally up to the end position.
*
* @return ecma-value
* @return true if 'finally' found,
* false otherwise
*/
ecma_value_t
vm_stack_frame_get_reg_value (vm_stack_frame_t *frame_p, /**< frame */
uint32_t reg_index) /**< index of register variable */
bool
vm_stack_find_finally (vm_frame_ctx_t *frame_ctx_p, /**< frame context */
ecma_value_t **vm_stack_top_ref_p, /**< current stack top */
vm_stack_context_type_t finally_type, /**< searching this finally */
uint32_t search_limit) /**< search up-to this byte code */
{
JERRY_ASSERT (reg_index >= VM_REG_FIRST && reg_index < VM_REG_FIRST + frame_p->regs_number);
ecma_value_t *vm_stack_top_p = *vm_stack_top_ref_p;
return frame_p->regs_p[reg_index - VM_REG_FIRST];
} /* vm_stack_frame_get_reg_value */
JERRY_ASSERT (finally_type <= VM_CONTEXT_FINALLY_RETURN);
/**
* Set value of specified register variable
*/
void
vm_stack_frame_set_reg_value (vm_stack_frame_t *frame_p, /**< frame */
uint32_t reg_index, /**< index of register variable */
ecma_value_t value) /**< ecma-value */
{
JERRY_ASSERT (reg_index >= VM_REG_FIRST && reg_index < VM_REG_FIRST + frame_p->regs_number);
frame_p->regs_p[reg_index - VM_REG_FIRST] = value;
} /* vm_stack_frame_set_reg_value */
/**
* Calculate number of value slots in the top-most chunk of the frame
*
* @return number of value slots
*/
static size_t
vm_stack_slots_in_top_chunk (vm_stack_frame_t *frame_p) /**< stack frame */
{
return ((frame_p->top_chunk_p == NULL) ? VM_STACK_FRAME_INLINED_VALUES_NUMBER : VM_STACK_SLOTS_IN_DYNAMIC_CHUNK);
} /* vm_stack_slots_in_top_chunk */
/**
* Longpath for vm_stack_push_value (for case current chunk may be doesn't have free slots)
*/
static void __attr_noinline___
vm_stack_push_value_longpath (vm_stack_frame_t *frame_p) /**< stack frame */
{
JERRY_ASSERT (frame_p->current_slot_index >= JERRY_MIN (VM_STACK_FRAME_INLINED_VALUES_NUMBER,
VM_STACK_SLOTS_IN_DYNAMIC_CHUNK));
const size_t slots_in_top_chunk = vm_stack_slots_in_top_chunk (frame_p);
if (frame_p->current_slot_index == slots_in_top_chunk)
if (finally_type != VM_CONTEXT_FINALLY_JUMP)
{
vm_stack_chunk_header_t *chunk_p;
chunk_p = (vm_stack_chunk_header_t *) mem_heap_alloc_block (VM_STACK_DYNAMIC_CHUNK_SIZE,
MEM_HEAP_ALLOC_SHORT_TERM);
ECMA_SET_POINTER (chunk_p->prev_chunk_p, frame_p->top_chunk_p);
frame_p->top_chunk_p = chunk_p;
frame_p->dynamically_allocated_value_slots_p = (ecma_value_t*) (frame_p->top_chunk_p + 1);
frame_p->current_slot_index = 0;
}
} /* vm_stack_push_value_longpath */
/**
* Push ecma-value to stack
*/
void
vm_stack_push_value (vm_stack_frame_t *frame_p, /**< stack frame */
ecma_value_t value) /**< ecma-value */
{
frame_p->current_slot_index++;
if (frame_p->current_slot_index >= JERRY_MIN (VM_STACK_FRAME_INLINED_VALUES_NUMBER,
VM_STACK_SLOTS_IN_DYNAMIC_CHUNK))
{
vm_stack_push_value_longpath (frame_p);
search_limit = 0xffffffffu;
}
JERRY_ASSERT (frame_p->current_slot_index < vm_stack_slots_in_top_chunk (frame_p));
frame_p->dynamically_allocated_value_slots_p[frame_p->current_slot_index] = value;
} /* vm_stack_push_value */
/**
* Get top value from stack
*/
ecma_value_t __attr_always_inline___
vm_stack_top_value (vm_stack_frame_t *frame_p) /**< stack frame */
{
const size_t slots_in_top_chunk = vm_stack_slots_in_top_chunk (frame_p);
JERRY_ASSERT (frame_p->current_slot_index < slots_in_top_chunk);
return frame_p->dynamically_allocated_value_slots_p[frame_p->current_slot_index];
} /* vm_stack_top_value */
/**
* Longpath for vm_stack_pop (for case a dynamically allocated chunk needs to be deallocated)
*/
static void __attr_noinline___
vm_stack_pop_longpath (vm_stack_frame_t *frame_p) /**< stack frame */
{
JERRY_ASSERT (frame_p->current_slot_index == 0 && frame_p->top_chunk_p != NULL);
vm_stack_chunk_header_t *chunk_to_free_p = frame_p->top_chunk_p;
frame_p->top_chunk_p = ECMA_GET_POINTER (vm_stack_chunk_header_t,
frame_p->top_chunk_p->prev_chunk_p);
if (frame_p->top_chunk_p != NULL)
while (frame_ctx_p->context_depth > 0)
{
frame_p->dynamically_allocated_value_slots_p = (ecma_value_t*) (frame_p->top_chunk_p + 1);
frame_p->current_slot_index = (uint32_t) (VM_STACK_SLOTS_IN_DYNAMIC_CHUNK - 1u);
}
else
{
frame_p->dynamically_allocated_value_slots_p = frame_p->inlined_values;
frame_p->current_slot_index = (uint32_t) (VM_STACK_FRAME_INLINED_VALUES_NUMBER - 1u);
vm_stack_context_type_t context_type;
uint32_t context_end = VM_GET_CONTEXT_END (vm_stack_top_p[-1]);
if (search_limit < context_end)
{
*vm_stack_top_ref_p = vm_stack_top_p;
return false;
}
context_type = VM_GET_CONTEXT_TYPE (vm_stack_top_p[-1]);
if (context_type == VM_CONTEXT_TRY || context_type == VM_CONTEXT_CATCH)
{
uint8_t *byte_code_p;
uint32_t branch_offset_length;
uint32_t branch_offset;
if (search_limit == context_end)
{
*vm_stack_top_ref_p = vm_stack_top_p;
return false;
}
byte_code_p = frame_ctx_p->byte_code_start_p + VM_GET_CONTEXT_END (vm_stack_top_p[-1]);
if (context_type == VM_CONTEXT_TRY)
{
JERRY_ASSERT (byte_code_p[0] == CBC_EXT_OPCODE);
if (byte_code_p[1] >= CBC_EXT_CATCH
&& byte_code_p[1] <= CBC_EXT_CATCH_3)
{
branch_offset_length = CBC_BRANCH_OFFSET_LENGTH (byte_code_p[1]);
branch_offset = vm_decode_branch_offset (byte_code_p + 2,
branch_offset_length);
if (finally_type == VM_CONTEXT_FINALLY_THROW)
{
branch_offset += (uint32_t) (byte_code_p - frame_ctx_p->byte_code_start_p);
vm_stack_top_p[-1] = VM_CREATE_CONTEXT (VM_CONTEXT_CATCH, branch_offset);
byte_code_p += 2 + branch_offset_length;
frame_ctx_p->byte_code_p = byte_code_p;
*vm_stack_top_ref_p = vm_stack_top_p;
return true;
}
byte_code_p += branch_offset;
if (*byte_code_p == CBC_CONTEXT_END)
{
VM_MINUS_EQUAL_U16 (frame_ctx_p->context_depth, PARSER_TRY_CONTEXT_STACK_ALLOCATION);
vm_stack_top_p -= PARSER_TRY_CONTEXT_STACK_ALLOCATION;
continue;
}
}
}
else
{
ecma_deref_object (frame_ctx_p->lex_env_p);
frame_ctx_p->lex_env_p = ecma_get_object_from_value (vm_stack_top_p[-2]);
if (byte_code_p[0] == CBC_CONTEXT_END)
{
VM_MINUS_EQUAL_U16 (frame_ctx_p->context_depth, PARSER_TRY_CONTEXT_STACK_ALLOCATION);
vm_stack_top_p -= PARSER_TRY_CONTEXT_STACK_ALLOCATION;
continue;
}
}
JERRY_ASSERT (byte_code_p[0] == CBC_EXT_OPCODE);
JERRY_ASSERT (byte_code_p[1] >= CBC_EXT_FINALLY
&& byte_code_p[1] <= CBC_EXT_FINALLY_3);
branch_offset_length = CBC_BRANCH_OFFSET_LENGTH (byte_code_p[1]);
branch_offset = vm_decode_branch_offset (byte_code_p + 2,
branch_offset_length);
branch_offset += (uint32_t) (byte_code_p - frame_ctx_p->byte_code_start_p);
vm_stack_top_p[-1] = VM_CREATE_CONTEXT ((uint32_t) finally_type, branch_offset);
byte_code_p += 2 + branch_offset_length;
frame_ctx_p->byte_code_p = byte_code_p;
*vm_stack_top_ref_p = vm_stack_top_p;
return true;
}
vm_stack_top_p = vm_stack_context_abort (frame_ctx_p, vm_stack_top_p);
}
mem_heap_free_block (chunk_to_free_p);
} /* vm_stack_pop_longpath */
/**
* Pop top value from stack and free it
*/
void
vm_stack_pop (vm_stack_frame_t *frame_p) /**< stack frame */
{
JERRY_ASSERT (frame_p->current_slot_index < vm_stack_slots_in_top_chunk (frame_p));
ecma_value_t value = vm_stack_top_value (frame_p);
if (unlikely (frame_p->current_slot_index == 0
&& frame_p->top_chunk_p != NULL))
{
vm_stack_pop_longpath (frame_p);
}
else
{
frame_p->current_slot_index--;
}
ecma_free_value (value, true);
} /* vm_stack_pop */
/**
* Pop multiple top values from stack and free them
*/
void
vm_stack_pop_multiple (vm_stack_frame_t *frame_p, /**< stack frame */
uint32_t number) /**< number of elements to pop */
{
for (uint32_t i = 0; i < number; i++)
{
vm_stack_pop (frame_p);
}
} /* vm_stack_pop_multiple */
*vm_stack_top_ref_p = vm_stack_top_p;
return false;
} /* vm_stack_find_finally */
/**
* @}
+26 -24
View File
@@ -1,4 +1,5 @@
/* Copyright 2015 Samsung Electronics Co., Ltd.
/* Copyright 2015-2016 Samsung Electronics Co., Ltd.
* Copyright 2015-2016 University of Szeged.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -36,7 +37,7 @@
*/
typedef struct
{
uint16_t prev_chunk_p; /**< previous chunk of same frame */
uint16_t prev_chunk_p; /**< previous chunk of same frame */
} vm_stack_chunk_header_t;
/**
@@ -44,30 +45,31 @@ typedef struct
*/
typedef struct vm_stack_frame_t
{
struct vm_stack_frame_t *prev_frame_p; /**< previous frame */
vm_stack_chunk_header_t *top_chunk_p; /**< the top-most chunk of the frame */
ecma_value_t *dynamically_allocated_value_slots_p; /**< pointer to dynamically allocated value slots
* in the top-most chunk */
uint32_t current_slot_index; /**< index of first free slot in the top chunk */
ecma_value_t inlined_values[VM_STACK_FRAME_INLINED_VALUES_NUMBER]; /**< place for values inlined into stack frame
* (instead of being placed on heap) */
ecma_value_t *regs_p; /**< register variables */
uint32_t regs_number; /**< number of register variables */
struct vm_stack_frame_t *prev_frame_p; /**< previous frame */
uint32_t regs_number; /**< number of register variables */
} vm_stack_frame_t;
extern void vm_stack_init (void);
extern void vm_stack_finalize (void);
extern vm_stack_frame_t *
vm_stack_get_top_frame (void);
extern void
vm_stack_add_frame (vm_stack_frame_t *, ecma_value_t *, uint32_t, uint32_t, uint32_t, ecma_collection_header_t *);
extern void vm_stack_free_frame (vm_stack_frame_t *);
extern ecma_value_t vm_stack_frame_get_reg_value (vm_stack_frame_t *, uint32_t);
extern void vm_stack_frame_set_reg_value (vm_stack_frame_t *, uint32_t, ecma_value_t);
extern void vm_stack_push_value (vm_stack_frame_t *, ecma_value_t);
extern ecma_value_t vm_stack_top_value (vm_stack_frame_t *);
extern void vm_stack_pop (vm_stack_frame_t *);
extern void vm_stack_pop_multiple (vm_stack_frame_t *, uint32_t);
#define VM_CREATE_CONTEXT(type, end_offset) ((ecma_value_t) ((type) | (end_offset) << 4))
#define VM_GET_CONTEXT_TYPE(value) ((vm_stack_context_type_t) ((value) & 0xf))
#define VM_GET_CONTEXT_END(value) ((value) >> 4)
/**
* Context types for the vm stack.
*/
typedef enum
{
VM_CONTEXT_FINALLY_JUMP, /**< finally context with a jump */
VM_CONTEXT_FINALLY_THROW, /**< finally context with a throw */
VM_CONTEXT_FINALLY_RETURN, /**< finally context with a return */
VM_CONTEXT_TRY, /**< try context */
VM_CONTEXT_CATCH, /**< catch context */
VM_CONTEXT_WITH, /**< with context */
VM_CONTEXT_FOR_IN, /**< for-in context */
} vm_stack_context_type_t;
extern ecma_value_t *vm_stack_context_abort (vm_frame_ctx_t *, ecma_value_t *);
extern bool vm_stack_find_finally (vm_frame_ctx_t *, ecma_value_t **,
vm_stack_context_type_t, uint32_t);
/**
* @}
+2368 -612
View File
File diff suppressed because it is too large Load Diff
+185 -13
View File
@@ -1,4 +1,5 @@
/* Copyright 2014-2015 Samsung Electronics Co., Ltd.
/* Copyright 2014-2016 Samsung Electronics Co., Ltd.
* Copyright 2015-2016 University of Szeged.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -18,25 +19,196 @@
#include "ecma-globals.h"
#include "jrt.h"
#include "opcodes.h"
#include "vm-defines.h"
extern void vm_init (const bytecode_data_header_t *, bool);
/** \addtogroup vm Virtual machine
* @{
*
* \addtogroup vm_executor Executor
* @{
*/
#define VM_OC_GET_DATA_SHIFT 24
#define VM_OC_GET_DATA_MASK 0x1f
#define VM_OC_GET_DATA_CREATE_ID(V) \
(((V) & VM_OC_GET_DATA_MASK) << VM_OC_GET_DATA_SHIFT)
#define VM_OC_GET_DATA_GET_ID(O) \
(((O) >> VM_OC_GET_DATA_SHIFT) & VM_OC_GET_DATA_MASK)
/**
* Argument getters that are part of the opcodes.
*/
typedef enum
{
VM_OC_GET_NONE = VM_OC_GET_DATA_CREATE_ID (0), /**< do nothing */
VM_OC_GET_STACK = VM_OC_GET_DATA_CREATE_ID (1), /**< pop one elemnet from the stack */
VM_OC_GET_STACK_STACK = VM_OC_GET_DATA_CREATE_ID (2), /**< pop two elemnets from the stack */
VM_OC_GET_BYTE = VM_OC_GET_DATA_CREATE_ID (3), /**< read a byte */
VM_OC_GET_LITERAL = VM_OC_GET_DATA_CREATE_ID (4), /**< resolve literal */
VM_OC_GET_STACK_LITERAL = VM_OC_GET_DATA_CREATE_ID (5), /**< pop one elemnet from the stack and resolve a literal*/
VM_OC_GET_LITERAL_BYTE = VM_OC_GET_DATA_CREATE_ID (6), /**< pop one elemnet from stack and read a byte */
VM_OC_GET_LITERAL_LITERAL = VM_OC_GET_DATA_CREATE_ID (7), /**< resolve two literals */
VM_OC_GET_THIS_LITERAL = VM_OC_GET_DATA_CREATE_ID (8), /**< get this and resolve a literal */
} vm_oc_get_types;
#define VM_OC_GROUP_MASK 0xff
#define VM_OC_GROUP_GET_INDEX(O) \
((O) & VM_OC_GROUP_MASK)
/**
* Opcodes.
*/
typedef enum
{
VM_OC_NONE, /**< do nothing */
VM_OC_POP, /**< pop from stack */
VM_OC_POP_BLOCK, /**< pop block */
VM_OC_PUSH, /**< push one element */
VM_OC_PUSH_TWO, /**< push two elements onto the stack */
VM_OC_PUSH_THREE, /**< push three elements onto the stack */
VM_OC_PUSH_UNDEFINED, /**< push undefined value */
VM_OC_PUSH_TRUE, /**< push true value */
VM_OC_PUSH_FALSE, /**< push false value */
VM_OC_PUSH_NULL, /**< push null value */
VM_OC_PUSH_THIS, /**< push this */
VM_OC_PUSH_NUMBER, /**< push number */
VM_OC_PUSH_OBJECT, /**< push object */
VM_OC_SET_PROPERTY, /**< set property */
VM_OC_SET_GETTER, /**< set getter */
VM_OC_SET_SETTER, /**< set setter */
VM_OC_PUSH_UNDEFINED_BASE, /**< push undefined base */
VM_OC_PUSH_ARRAY, /**< push array */
VM_OC_PUSH_ELISON, /**< push elison */
VM_OC_APPEND_ARRAY, /**< append array */
VM_OC_IDENT_REFERENCE, /**< ident reference */
VM_OC_PROP_REFERENCE, /**< prop reference */
VM_OC_PROP_GET, /**< prop get */
/* These eight opcodes must be in this order. */
VM_OC_PROP_PRE_INCR, /**< prefix increment of a property */
VM_OC_PRE_INCR, /**< prefix increment */
VM_OC_PROP_PRE_DECR, /**< prop prefix decrement of a property */
VM_OC_PRE_DECR, /**< prefix decrement */
VM_OC_PROP_POST_INCR, /**< prop postfix increment of a property */
VM_OC_POST_INCR, /**< postfix increment */
VM_OC_PROP_POST_DECR, /**< prop postfix decrement of a property */
VM_OC_POST_DECR, /**< postfix decrement */
VM_OC_PROP_DELETE, /**< delete property */
VM_OC_DELETE, /**< delete */
VM_OC_ASSIGN, /**< assign */
VM_OC_ASSIGN_PROP, /**< assign property */
VM_OC_ASSIGN_PROP_THIS, /**< assign prop this */
VM_OC_RET, /**< return */
VM_OC_THROW, /**< throw */
VM_OC_THROW_REFERENCE_ERROR, /**< throw reference error */
/* The PROP forms must get the highest opcodes. */
VM_OC_EVAL, /**< eval */
VM_OC_CALL_N, /**< call n */
VM_OC_CALL, /**< call */
VM_OC_CALL_PROP_N, /**< call property n */
VM_OC_CALL_PROP, /**< call property */
VM_OC_NEW_N, /**< new n */
VM_OC_NEW, /**< new */
VM_OC_JUMP, /**< jump */
VM_OC_BRANCH_IF_STRICT_EQUAL, /**< branch if stric equal */
/* These four opcodes must be in this order. */
VM_OC_BRANCH_IF_TRUE, /**< branch if true */
VM_OC_BRANCH_IF_FALSE, /**< branch if false */
VM_OC_BRANCH_IF_LOGICAL_TRUE, /**< branch if logical true */
VM_OC_BRANCH_IF_LOGICAL_FALSE, /**< branch if logical false */
VM_OC_PLUS, /**< unary plus */
VM_OC_MINUS, /**< unary minus */
VM_OC_NOT, /**< not */
VM_OC_BIT_NOT, /**< bitwise not */
VM_OC_VOID, /**< void */
VM_OC_TYPEOF_IDENT, /**< typeof identifier */
VM_OC_TYPEOF, /**< typeof */
VM_OC_ADD, /**< binary add */
VM_OC_SUB, /**< binary sub */
VM_OC_MUL, /**< mul */
VM_OC_DIV, /**< div */
VM_OC_MOD, /**< mod */
VM_OC_EQUAL, /**< equal */
VM_OC_NOT_EQUAL, /**< not equal */
VM_OC_STRICT_EQUAL, /**< strict equal */
VM_OC_STRICT_NOT_EQUAL, /**< strict not equal */
VM_OC_LESS, /**< less */
VM_OC_GREATER, /**< greater */
VM_OC_LESS_EQUAL, /**< less equal */
VM_OC_GREATER_EQUAL, /**< greater equal */
VM_OC_IN, /**< in */
VM_OC_INSTANCEOF, /**< instanceof */
VM_OC_BIT_OR, /**< bitwise or */
VM_OC_BIT_XOR, /**< bitwise xor */
VM_OC_BIT_AND, /**< bitwise and */
VM_OC_LEFT_SHIFT, /**< left shift */
VM_OC_RIGHT_SHIFT, /**< right shift */
VM_OC_UNS_RIGHT_SHIFT, /**< unsigned right shift */
VM_OC_WITH, /**< with */
VM_OC_FOR_IN_CREATE_CONTEXT, /**< for in create context */
VM_OC_FOR_IN_GET_NEXT, /**< get next */
VM_OC_FOR_IN_HAS_NEXT, /**< has next */
VM_OC_TRY, /**< try */
VM_OC_CATCH, /**< catch */
VM_OC_FINALLY, /**< finally */
VM_OC_CONTEXT_END, /**< context end */
VM_OC_JUMP_AND_EXIT_CONTEXT, /**< jump and exit context */
} vm_oc_types;
#define VM_OC_PUT_DATA_SHIFT 12
#define VM_OC_PUT_DATA_MASK 0xf
#define VM_OC_PUT_DATA_CREATE_FLAG(V) \
(((V) & VM_OC_PUT_DATA_MASK) << VM_OC_PUT_DATA_SHIFT)
/**
* Result writers that are part of the opcodes.
*/
typedef enum
{
VM_OC_PUT_IDENT = VM_OC_PUT_DATA_CREATE_FLAG (0x1),
VM_OC_PUT_REFERENCE = VM_OC_PUT_DATA_CREATE_FLAG (0x2),
VM_OC_PUT_STACK = VM_OC_PUT_DATA_CREATE_FLAG (0x4),
VM_OC_PUT_BLOCK = VM_OC_PUT_DATA_CREATE_FLAG (0x8),
} vm_oc_put_types;
extern void vm_init (ecma_compiled_code_t *, bool);
extern void vm_finalize (void);
extern jerry_completion_code_t vm_run_global (void);
extern ecma_completion_value_t vm_run_eval (const bytecode_data_header_t *, bool);
extern ecma_completion_value_t vm_run_eval (ecma_compiled_code_t *, bool);
extern ecma_completion_value_t vm_loop (vm_frame_ctx_t *, vm_run_scope_t *);
extern ecma_completion_value_t vm_run_from_pos (const bytecode_data_header_t *, vm_instr_counter_t,
ecma_value_t, ecma_object_t *, bool, bool, ecma_collection_header_t *);
extern ecma_completion_value_t vm_loop (vm_frame_ctx_t *);
extern ecma_completion_value_t vm_run (const ecma_compiled_code_t *,
ecma_value_t,
ecma_object_t *,
bool,
ecma_collection_header_t *);
extern vm_instr_t vm_get_instr (const vm_instr_t *, vm_instr_counter_t);
extern uint8_t vm_get_scope_args_num (const bytecode_data_header_t *, vm_instr_counter_t);
extern ecma_completion_value_t vm_run_array_args (const ecma_compiled_code_t *,
ecma_value_t,
ecma_object_t *,
bool,
const ecma_value_t *,
ecma_length_t);
extern bool vm_is_strict_mode (void);
extern bool vm_is_direct_eval_form_call (void);
extern ecma_value_t vm_get_this_binding (void);
extern ecma_object_t *vm_get_lex_env (void);
#endif /* VM_H */
/**
* @}
* @}
*/
#endif /* !VM_H */