mirror of
https://github.com/jerryscript-project/jerryscript.git
synced 2026-01-28 14:33:44 +00:00
Refactoring of libcoreint part1
This commit is contained in:
parent
6fbf3e4eed
commit
d4a9d9430e
@ -119,7 +119,7 @@ run_int_from_pos (opcode_counter_t start_pos,
|
||||
__memset (regs, 0, sizeof (regs));
|
||||
JERRY_ASSERT (ecma_is_value_empty (regs[0]));
|
||||
|
||||
struct __int_data int_data;
|
||||
__int_data int_data;
|
||||
int_data.pos = (opcode_counter_t) (start_pos + 1);
|
||||
int_data.this_binding = this_binding_value;
|
||||
int_data.lex_env_p = lex_env_p;
|
||||
|
||||
@ -20,21 +20,7 @@
|
||||
#include "globals.h"
|
||||
#include "opcodes.h"
|
||||
|
||||
typedef uint16_t opcode_counter_t;
|
||||
|
||||
struct __int_data
|
||||
{
|
||||
opcode_counter_t pos; /**< current opcode to execute */
|
||||
ecma_value_t this_binding; /**< this binding for current context */
|
||||
ecma_object_t *lex_env_p; /**< current lexical environment */
|
||||
bool is_strict; /**< is current code execution mode strict? */
|
||||
bool is_eval_code; /**< is current code executed with eval */
|
||||
T_IDX min_reg_num; /**< minimum idx used for register identification */
|
||||
T_IDX max_reg_num; /**< maximum idx used for register identification */
|
||||
ecma_value_t *regs_p; /**< register variables */
|
||||
};
|
||||
|
||||
void init_int (const OPCODE* program_p);
|
||||
void init_int (const __opcode* program_p);
|
||||
bool run_int (void);
|
||||
ecma_completion_value_t run_int_from_pos (opcode_counter_t start_pos,
|
||||
ecma_value_t this_binding_value,
|
||||
@ -45,7 +31,7 @@ ecma_completion_value_t run_int_from_pos (opcode_counter_t start_pos,
|
||||
ssize_t try_get_string_by_idx (T_IDX idx, ecma_char_t *buffer_p, ssize_t buffer_size);
|
||||
ecma_number_t get_number_by_idx (T_IDX idx);
|
||||
|
||||
OPCODE read_opcode (opcode_counter_t counter);
|
||||
__opcode read_opcode (opcode_counter_t counter);
|
||||
|
||||
#endif /* INTERPRETER_H */
|
||||
|
||||
|
||||
@ -1,434 +0,0 @@
|
||||
/* Copyright 2014 Samsung Electronics Co., Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef OPCODE_STRUCTURES_H
|
||||
#define OPCODE_STRUCTURES_H
|
||||
|
||||
#define OP_DEF(name, list) struct __op_##name { list ; } ;
|
||||
|
||||
|
||||
#define OP_CODE_DECL_VOID(name) \
|
||||
struct __op_##name { T_IDX __do_not_use; }; \
|
||||
OPCODE getop_##name (void);
|
||||
|
||||
#define OP_CODE_DECL(name, type, ...) \
|
||||
OP_DEF (name, type##_DECL(__VA_ARGS__)) \
|
||||
OPCODE getop_##name (type);
|
||||
|
||||
#define T_IDX_IDX T_IDX, T_IDX
|
||||
#define T_IDX_IDX_IDX T_IDX, T_IDX, T_IDX
|
||||
|
||||
#define T_IDX_DECL(name) T_IDX name
|
||||
#define T_IDX_IDX_DECL(name1, name2) \
|
||||
T_IDX_DECL (name1) ; \
|
||||
T_IDX_DECL (name2)
|
||||
#define T_IDX_IDX_IDX_DECL(name1, name2, name3) \
|
||||
T_IDX_DECL (name1) ; \
|
||||
T_IDX_DECL (name2); \
|
||||
T_IDX_DECL (name3)
|
||||
|
||||
#define GETOP_IMPL_0(name) \
|
||||
OPCODE getop_##name () \
|
||||
{ \
|
||||
OPCODE opdata; \
|
||||
opdata.op_idx = __op__idx_##name; \
|
||||
return opdata; \
|
||||
}
|
||||
|
||||
#define GETOP_IMPL_1(name, field1) \
|
||||
OPCODE getop_##name (T_IDX arg1) \
|
||||
{ \
|
||||
OPCODE opdata; \
|
||||
opdata.op_idx = __op__idx_##name; \
|
||||
opdata.data.name.field1 = arg1; \
|
||||
return opdata; \
|
||||
}
|
||||
|
||||
#define GETOP_IMPL_2(name, field1, field2) \
|
||||
OPCODE getop_##name (T_IDX arg1, T_IDX arg2) \
|
||||
{ \
|
||||
OPCODE opdata; \
|
||||
opdata.op_idx = __op__idx_##name; \
|
||||
opdata.data.name.field1 = arg1; \
|
||||
opdata.data.name.field2 = arg2; \
|
||||
return opdata; \
|
||||
}
|
||||
|
||||
#define GETOP_IMPL_3(name, field1, field2, field3) \
|
||||
OPCODE getop_##name (T_IDX arg1, T_IDX arg2, T_IDX arg3) \
|
||||
{ \
|
||||
OPCODE opdata; \
|
||||
opdata.op_idx = __op__idx_##name; \
|
||||
opdata.data.name.field1 = arg1; \
|
||||
opdata.data.name.field2 = arg2; \
|
||||
opdata.data.name.field3 = arg3; \
|
||||
return opdata; \
|
||||
}
|
||||
|
||||
/** Instruction tests if BOOLEAN value is TRUE and JMP to DST */
|
||||
OP_CODE_DECL (is_true_jmp, T_IDX_IDX,
|
||||
value,
|
||||
opcode)
|
||||
|
||||
/** Instruction tests if BOOLEAN value is FALSE and JMP to DST */
|
||||
OP_CODE_DECL (is_false_jmp, T_IDX_IDX,
|
||||
value,
|
||||
opcode)
|
||||
|
||||
/** Unconditional JMP to the specified opcode index */
|
||||
OP_CODE_DECL (jmp, T_IDX,
|
||||
opcode_idx)
|
||||
|
||||
/** Unconditional JMP on opcode_count up */
|
||||
OP_CODE_DECL (jmp_up, T_IDX,
|
||||
opcode_count)
|
||||
|
||||
/** Unconditional JMP on opcode_count down */
|
||||
OP_CODE_DECL (jmp_down, T_IDX,
|
||||
opcode_count)
|
||||
|
||||
/** dst = L + R */
|
||||
OP_CODE_DECL (addition, T_IDX_IDX_IDX,
|
||||
dst,
|
||||
var_left,
|
||||
var_right)
|
||||
|
||||
/** dst = L - R */
|
||||
OP_CODE_DECL (substraction, T_IDX_IDX_IDX,
|
||||
dst,
|
||||
var_left,
|
||||
var_right)
|
||||
|
||||
/** dst = L / R */
|
||||
OP_CODE_DECL (division, T_IDX_IDX_IDX,
|
||||
dst,
|
||||
var_left,
|
||||
var_right)
|
||||
|
||||
/** dst = L * R */
|
||||
OP_CODE_DECL (multiplication, T_IDX_IDX_IDX,
|
||||
dst,
|
||||
var_left,
|
||||
var_right)
|
||||
|
||||
/** dst = L % R */
|
||||
OP_CODE_DECL (remainder, T_IDX_IDX_IDX,
|
||||
dst,
|
||||
var_left,
|
||||
var_right)
|
||||
|
||||
/** dst = L << R */
|
||||
OP_CODE_DECL (b_shift_left, T_IDX_IDX_IDX,
|
||||
dst,
|
||||
var_left,
|
||||
var_right)
|
||||
|
||||
/** dst = L >> R */
|
||||
OP_CODE_DECL (b_shift_right, T_IDX_IDX_IDX,
|
||||
dst,
|
||||
var_left,
|
||||
var_right)
|
||||
|
||||
/** dst = L >>> R */
|
||||
OP_CODE_DECL (b_shift_uright, T_IDX_IDX_IDX,
|
||||
dst,
|
||||
var_left,
|
||||
var_right)
|
||||
|
||||
// Binary bitwise operators.
|
||||
// Operands is a set of 32 bits
|
||||
// Returns numerical.
|
||||
|
||||
/** dst = L & R */
|
||||
OP_CODE_DECL (b_and, T_IDX_IDX_IDX,
|
||||
dst,
|
||||
var_left,
|
||||
var_right)
|
||||
|
||||
/** dst = L | R */
|
||||
OP_CODE_DECL (b_or, T_IDX_IDX_IDX,
|
||||
dst,
|
||||
var_left,
|
||||
var_right)
|
||||
|
||||
/** dst = L ^ R */
|
||||
OP_CODE_DECL (b_xor, T_IDX_IDX_IDX,
|
||||
dst,
|
||||
var_left,
|
||||
var_right)
|
||||
|
||||
/** dst = ~ R */
|
||||
OP_CODE_DECL (b_not, T_IDX_IDX,
|
||||
dst,
|
||||
var_right)
|
||||
|
||||
// Binary logical operators.
|
||||
// Operands are booleans.
|
||||
// Return boolean.
|
||||
|
||||
/** dst = L && R */
|
||||
OP_CODE_DECL (logical_and, T_IDX_IDX_IDX,
|
||||
dst,
|
||||
var_left,
|
||||
var_right)
|
||||
|
||||
/** dst = L || R */
|
||||
OP_CODE_DECL (logical_or, T_IDX_IDX_IDX,
|
||||
dst,
|
||||
var_left,
|
||||
var_right)
|
||||
|
||||
/** dst = ! R */
|
||||
OP_CODE_DECL (logical_not, T_IDX_IDX,
|
||||
dst,
|
||||
var_right)
|
||||
|
||||
// Equality operations.
|
||||
|
||||
/** dst = L == R. */
|
||||
OP_CODE_DECL (equal_value, T_IDX_IDX_IDX,
|
||||
dst,
|
||||
var_left,
|
||||
var_right)
|
||||
|
||||
/** dst = L != R. */
|
||||
OP_CODE_DECL (not_equal_value, T_IDX_IDX_IDX,
|
||||
dst,
|
||||
var_left,
|
||||
var_right)
|
||||
|
||||
/** dst = L === R. */
|
||||
OP_CODE_DECL (equal_value_type, T_IDX_IDX_IDX,
|
||||
dst,
|
||||
var_left,
|
||||
var_right)
|
||||
|
||||
/** dst = L !== R. */
|
||||
OP_CODE_DECL (not_equal_value_type, T_IDX_IDX_IDX,
|
||||
dst,
|
||||
var_left,
|
||||
var_right)
|
||||
|
||||
// Relational operations.
|
||||
|
||||
/** dst = L < R. */
|
||||
OP_CODE_DECL (less_than, T_IDX_IDX_IDX,
|
||||
dst,
|
||||
var_left,
|
||||
var_right)
|
||||
|
||||
/** dst = L > R. */
|
||||
OP_CODE_DECL (greater_than, T_IDX_IDX_IDX,
|
||||
dst,
|
||||
var_left,
|
||||
var_right)
|
||||
|
||||
/** dst = L <= R. */
|
||||
OP_CODE_DECL (less_or_equal_than, T_IDX_IDX_IDX,
|
||||
dst,
|
||||
var_left,
|
||||
var_right)
|
||||
|
||||
/** dst = L >= R. */
|
||||
OP_CODE_DECL (greater_or_equal_than, T_IDX_IDX_IDX,
|
||||
dst,
|
||||
var_left,
|
||||
var_right)
|
||||
|
||||
/** dst = L instanceof R. */
|
||||
OP_CODE_DECL (instanceof, T_IDX_IDX_IDX,
|
||||
dst,
|
||||
var_left,
|
||||
var_right)
|
||||
|
||||
/** dst = L in R. */
|
||||
OP_CODE_DECL (in, T_IDX_IDX_IDX,
|
||||
dst,
|
||||
var_left,
|
||||
var_right)
|
||||
|
||||
/** dst = var_right++. */
|
||||
OP_CODE_DECL (post_incr, T_IDX_IDX,
|
||||
dst,
|
||||
var_right)
|
||||
|
||||
/** dst = var_right--. */
|
||||
OP_CODE_DECL (post_decr, T_IDX_IDX,
|
||||
dst,
|
||||
var_right)
|
||||
|
||||
/** dst = ++var_right. */
|
||||
OP_CODE_DECL (pre_incr, T_IDX_IDX,
|
||||
dst,
|
||||
var_right)
|
||||
|
||||
/** dst = --var_right. */
|
||||
OP_CODE_DECL (pre_decr, T_IDX_IDX,
|
||||
dst,
|
||||
var_right)
|
||||
|
||||
// Assignment operators.
|
||||
// Assign value to LEFT operand based on value of RIGHT operand.
|
||||
|
||||
/** L = R */
|
||||
OP_CODE_DECL (assignment, T_IDX_IDX_IDX,
|
||||
var_left,
|
||||
type_value_right,
|
||||
value_right)
|
||||
|
||||
// Functions calls, declarations and argument handling
|
||||
|
||||
/** a = name (); */
|
||||
OP_CODE_DECL (call_0, T_IDX_IDX,
|
||||
lhs,
|
||||
name_lit_idx)
|
||||
|
||||
/** a = name (arg1); */
|
||||
OP_CODE_DECL (call_1, T_IDX_IDX_IDX,
|
||||
lhs,
|
||||
name_lit_idx,
|
||||
arg1_lit_idx)
|
||||
|
||||
/** a = name (arg1, ... */
|
||||
OP_CODE_DECL (call_n, T_IDX_IDX_IDX,
|
||||
lhs,
|
||||
name_lit_idx,
|
||||
arg1_lit_idx)
|
||||
|
||||
/** lhs = name (arg_list) */
|
||||
OP_CODE_DECL (native_call, T_IDX_IDX_IDX,
|
||||
lhs,
|
||||
name,
|
||||
arg_list)
|
||||
|
||||
/** a = new name (arg_list */
|
||||
OP_CODE_DECL (construct_decl, T_IDX_IDX_IDX,
|
||||
lhs,
|
||||
name_lit_idx,
|
||||
arg_list)
|
||||
|
||||
/** name (); */
|
||||
OP_CODE_DECL (func_decl_0, T_IDX,
|
||||
name_lit_idx)
|
||||
|
||||
/** name (arg1); */
|
||||
OP_CODE_DECL (func_decl_1, T_IDX_IDX,
|
||||
name_lit_idx,
|
||||
arg1_lit_idx)
|
||||
|
||||
/** name (arg1, arg2); */
|
||||
OP_CODE_DECL (func_decl_2, T_IDX_IDX_IDX,
|
||||
name_lit_idx,
|
||||
arg1_lit_idx,
|
||||
arg2_lit_idx)
|
||||
|
||||
/** name (arg1, arg2, ... */
|
||||
OP_CODE_DECL (func_decl_n, T_IDX_IDX_IDX,
|
||||
name_lit_idx,
|
||||
arg1_lit_idx,
|
||||
arg2_lit_idx)
|
||||
|
||||
/** arg1, arg2, arg3 */
|
||||
OP_CODE_DECL (varg_list, T_IDX_IDX_IDX,
|
||||
arg1_lit_idx,
|
||||
arg2_lit_idx,
|
||||
arg3_lit_idx)
|
||||
|
||||
/** exit with status code; */
|
||||
OP_CODE_DECL (exitval, T_IDX,
|
||||
status_code)
|
||||
|
||||
/** return value; */
|
||||
OP_CODE_DECL (retval, T_IDX,
|
||||
ret_value)
|
||||
OP_CODE_DECL_VOID (ret)
|
||||
|
||||
OP_CODE_DECL_VOID (nop)
|
||||
|
||||
/** a = [list] */
|
||||
OP_CODE_DECL (array_decl, T_IDX_IDX,
|
||||
lhs,
|
||||
list)
|
||||
|
||||
/** a = b : c */
|
||||
OP_CODE_DECL (prop, T_IDX_IDX_IDX,
|
||||
lhs,
|
||||
name,
|
||||
value)
|
||||
|
||||
/** a = b.c OR a = b[c] */
|
||||
OP_CODE_DECL (prop_getter, T_IDX_IDX_IDX,
|
||||
lhs,
|
||||
obj,
|
||||
prop)
|
||||
|
||||
/** a.b = c OR a[b] = c */
|
||||
OP_CODE_DECL (prop_setter, T_IDX_IDX_IDX,
|
||||
obj,
|
||||
prop,
|
||||
rhs)
|
||||
|
||||
/** a = get prop () */
|
||||
OP_CODE_DECL (prop_get_decl, T_IDX_IDX,
|
||||
lhs,
|
||||
prop)
|
||||
|
||||
/** a = set prop (arg) */
|
||||
OP_CODE_DECL (prop_set_decl, T_IDX_IDX_IDX,
|
||||
lhs,
|
||||
prop,
|
||||
arg)
|
||||
|
||||
/** a = { } */
|
||||
OP_CODE_DECL (obj_decl, T_IDX_IDX,
|
||||
lhs,
|
||||
list)
|
||||
|
||||
/** a = this */
|
||||
OP_CODE_DECL (this, T_IDX,
|
||||
lhs)
|
||||
|
||||
/** a = delete b */
|
||||
OP_CODE_DECL (delete, T_IDX_IDX,
|
||||
lhs,
|
||||
obj)
|
||||
|
||||
/** a = typeof b */
|
||||
OP_CODE_DECL (typeof, T_IDX_IDX,
|
||||
lhs,
|
||||
obj)
|
||||
|
||||
/** with (b) { */
|
||||
OP_CODE_DECL (with, T_IDX,
|
||||
expr)
|
||||
|
||||
/** } */
|
||||
OP_CODE_DECL_VOID (end_with)
|
||||
|
||||
// Variable declaration
|
||||
OP_CODE_DECL (var_decl, T_IDX,
|
||||
variable_name)
|
||||
|
||||
OP_CODE_DECL (reg_var_decl, T_IDX_IDX,
|
||||
min,
|
||||
max)
|
||||
|
||||
/** meta */
|
||||
OP_CODE_DECL (meta, T_IDX_IDX_IDX,
|
||||
type,
|
||||
data_1,
|
||||
data_2)
|
||||
|
||||
#endif /* OPCODE_STRUCTURES_H */
|
||||
140
src/libcoreint/opcodes-agnostic.c
Normal file
140
src/libcoreint/opcodes-agnostic.c
Normal file
@ -0,0 +1,140 @@
|
||||
/* Copyright 2014 Samsung Electronics Co., Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "opcodes.h"
|
||||
#include "opcodes-ecma-support.h"
|
||||
|
||||
/**
|
||||
* 'Jump if true' opcode handler.
|
||||
*
|
||||
* Note:
|
||||
* the opcode changes current opcode position to specified opcode index
|
||||
* if argument evaluates to true.
|
||||
*/
|
||||
ecma_completion_value_t
|
||||
opfunc_is_true_jmp (OPCODE opdata, /**< operation data */
|
||||
__int_data *int_data) /**< interpreter context */
|
||||
{
|
||||
const T_IDX cond_var_idx = opdata.data.is_true_jmp.value;
|
||||
const T_IDX dst_opcode_idx = opdata.data.is_true_jmp.opcode;
|
||||
|
||||
ecma_completion_value_t ret_value;
|
||||
|
||||
ECMA_TRY_CATCH (cond_value, get_variable_value (int_data, cond_var_idx, false), ret_value);
|
||||
|
||||
ecma_completion_value_t to_bool_completion = ecma_op_to_boolean (cond_value.value);
|
||||
JERRY_ASSERT (ecma_is_completion_value_normal (to_bool_completion));
|
||||
|
||||
if (ecma_is_value_true (to_bool_completion.value))
|
||||
{
|
||||
int_data->pos = dst_opcode_idx;
|
||||
}
|
||||
else
|
||||
{
|
||||
int_data->pos++;
|
||||
}
|
||||
|
||||
ret_value = ecma_make_empty_completion_value ();
|
||||
|
||||
ECMA_FINALIZE (cond_value);
|
||||
|
||||
return ret_value;
|
||||
} /* opfunc_is_true_jmp */
|
||||
|
||||
/**
|
||||
* 'Jump if false' opcode handler.
|
||||
*
|
||||
* Note:
|
||||
* the opcode changes current opcode position to specified opcode index
|
||||
* if argument evaluates to false.
|
||||
*/
|
||||
ecma_completion_value_t
|
||||
opfunc_is_false_jmp (OPCODE opdata, /**< operation data */
|
||||
__int_data *int_data) /**< interpreter context */
|
||||
{
|
||||
const T_IDX cond_var_idx = opdata.data.is_false_jmp.value;
|
||||
const T_IDX dst_opcode_idx = opdata.data.is_false_jmp.opcode;
|
||||
|
||||
ecma_completion_value_t ret_value;
|
||||
|
||||
ECMA_TRY_CATCH (cond_value, get_variable_value (int_data, cond_var_idx, false), ret_value);
|
||||
|
||||
ecma_completion_value_t to_bool_completion = ecma_op_to_boolean (cond_value.value);
|
||||
JERRY_ASSERT (ecma_is_completion_value_normal (to_bool_completion));
|
||||
|
||||
if (!ecma_is_value_true (to_bool_completion.value))
|
||||
{
|
||||
int_data->pos = dst_opcode_idx;
|
||||
}
|
||||
else
|
||||
{
|
||||
int_data->pos++;
|
||||
}
|
||||
|
||||
ret_value = ecma_make_empty_completion_value ();
|
||||
|
||||
ECMA_FINALIZE (cond_value);
|
||||
|
||||
return ret_value;
|
||||
} /* opfunc_is_false_jmp */
|
||||
|
||||
/**
|
||||
* 'Jump' opcode handler.
|
||||
*
|
||||
* Note:
|
||||
* the opcode changes current opcode position to specified opcode index
|
||||
*/
|
||||
ecma_completion_value_t
|
||||
opfunc_jmp (OPCODE opdata, /**< operation data */
|
||||
__int_data *int_data) /**< interpreter context */
|
||||
{
|
||||
int_data->pos = opdata.data.jmp.opcode_idx;
|
||||
|
||||
return ecma_make_empty_completion_value ();
|
||||
} /* opfunc_jmp */
|
||||
|
||||
/**
|
||||
* 'Jump down' opcode handler.
|
||||
*
|
||||
* Note:
|
||||
* the opcode changes adds specified value to current opcode position
|
||||
*/
|
||||
ecma_completion_value_t
|
||||
opfunc_jmp_down (OPCODE opdata, /**< operation data */
|
||||
__int_data *int_data) /**< interpreter context */
|
||||
{
|
||||
JERRY_ASSERT (int_data->pos <= int_data->pos + opdata.data.jmp_up.opcode_count);
|
||||
|
||||
int_data->pos = (opcode_counter_t) (int_data->pos + opdata.data.jmp_down.opcode_count);
|
||||
|
||||
return ecma_make_empty_completion_value ();
|
||||
} /* opfunc_jmp_down */
|
||||
|
||||
/**
|
||||
* 'Jump up' opcode handler.
|
||||
*
|
||||
* Note:
|
||||
* the opcode changes substracts specified value from current opcode position
|
||||
*/
|
||||
ecma_completion_value_t
|
||||
opfunc_jmp_up (OPCODE opdata, /**< operation data */
|
||||
__int_data *int_data) /**< interpreter context */
|
||||
{
|
||||
JERRY_ASSERT (int_data->pos >= opdata.data.jmp_up.opcode_count);
|
||||
|
||||
int_data->pos = (opcode_counter_t) (int_data->pos - opdata.data.jmp_down.opcode_count);
|
||||
|
||||
return ecma_make_empty_completion_value ();
|
||||
} /* opfunc_jmp_up */
|
||||
359
src/libcoreint/opcodes-bitwise.c
Normal file
359
src/libcoreint/opcodes-bitwise.c
Normal file
@ -0,0 +1,359 @@
|
||||
/* Copyright 2014 Samsung Electronics Co., Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "opcodes.h"
|
||||
#include "opcodes-ecma-support.h"
|
||||
|
||||
/**
|
||||
* Number bitwise logic operations.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
number_bitwise_logic_and, /**< bitwise AND calculation */
|
||||
number_bitwise_logic_or, /**< bitwise OR calculation */
|
||||
number_bitwise_logic_xor, /**< bitwise XOR calculation */
|
||||
number_bitwise_shift_left, /**< bitwise LEFT SHIFT calculation */
|
||||
number_bitwise_shift_right, /**< bitwise RIGHT_SHIFT calculation */
|
||||
number_bitwise_shift_uright, /**< bitwise UNSIGNED RIGHT SHIFT calculation */
|
||||
number_bitwise_not, /**< bitwise NOT calculation */
|
||||
} number_bitwise_logic_op;
|
||||
|
||||
/**
|
||||
* Perform ECMA number logic operation.
|
||||
*
|
||||
* The algorithm of the operation is following:
|
||||
* leftNum = ToNumber (leftValue);
|
||||
* rightNum = ToNumber (rightValue);
|
||||
* result = leftNum BitwiseLogicOp rightNum;
|
||||
*
|
||||
* @return completion value
|
||||
* Returned value must be freed with ecma_free_completion_value
|
||||
*/
|
||||
static ecma_completion_value_t
|
||||
do_number_bitwise_logic (__int_data *int_data, /**< interpreter context */
|
||||
T_IDX dst_var_idx, /**< destination variable identifier */
|
||||
number_bitwise_logic_op op, /**< number bitwise logic operation */
|
||||
ecma_value_t left_value, /**< left value */
|
||||
ecma_value_t right_value) /** right value */
|
||||
{
|
||||
ecma_completion_value_t ret_value;
|
||||
|
||||
ECMA_TRY_CATCH (num_left_value, ecma_op_to_number (left_value), ret_value);
|
||||
ECMA_TRY_CATCH (num_right_value, ecma_op_to_number (right_value), ret_value);
|
||||
|
||||
ecma_number_t *left_p, *right_p;
|
||||
left_p = (ecma_number_t*) ECMA_GET_POINTER (num_left_value.value.value);
|
||||
right_p = (ecma_number_t*) ECMA_GET_POINTER (num_right_value.value.value);
|
||||
|
||||
ecma_number_t* res_p = ecma_alloc_number ();
|
||||
|
||||
int32_t left_int32 = ecma_number_to_int32 (*left_p);
|
||||
int32_t right_int32 = ecma_number_to_int32 (*right_p);
|
||||
|
||||
uint32_t left_uint32 = ecma_number_to_uint32 (*left_p);
|
||||
uint32_t right_uint32 = ecma_number_to_uint32 (*right_p);
|
||||
|
||||
switch (op)
|
||||
{
|
||||
case number_bitwise_logic_and:
|
||||
{
|
||||
*res_p = ecma_int32_to_number (left_int32 & right_int32);
|
||||
break;
|
||||
}
|
||||
case number_bitwise_logic_or:
|
||||
{
|
||||
*res_p = ecma_int32_to_number (left_int32 | right_int32);
|
||||
break;
|
||||
}
|
||||
case number_bitwise_logic_xor:
|
||||
{
|
||||
*res_p = ecma_int32_to_number (left_int32 ^ right_int32);
|
||||
break;
|
||||
}
|
||||
case number_bitwise_shift_left:
|
||||
{
|
||||
*res_p = ecma_int32_to_number (left_int32 << (right_uint32 & 0x1F));
|
||||
break;
|
||||
}
|
||||
case number_bitwise_shift_right:
|
||||
{
|
||||
*res_p = ecma_int32_to_number (left_int32 >> (right_uint32 & 0x1F));
|
||||
break;
|
||||
}
|
||||
case number_bitwise_shift_uright:
|
||||
{
|
||||
*res_p = ecma_uint32_to_number (left_uint32 >> (right_uint32 & 0x1F));
|
||||
break;
|
||||
}
|
||||
case number_bitwise_not:
|
||||
{
|
||||
*res_p = ecma_int32_to_number (~right_int32);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ret_value = set_variable_value (int_data,
|
||||
dst_var_idx,
|
||||
ecma_make_number_value (res_p));
|
||||
|
||||
ecma_dealloc_number (res_p);
|
||||
|
||||
ECMA_FINALIZE (num_right_value);
|
||||
ECMA_FINALIZE (num_left_value);
|
||||
|
||||
return ret_value;
|
||||
} /* do_number_bitwise_logic */
|
||||
|
||||
/**
|
||||
* 'Bitwise AND' opcode handler.
|
||||
*
|
||||
* See also: ECMA-262 v5, 11.10
|
||||
*
|
||||
* @return completion value
|
||||
* Returned value must be freed with ecma_free_completion_value
|
||||
*/
|
||||
ecma_completion_value_t
|
||||
opfunc_b_and (OPCODE opdata, /**< operation data */
|
||||
__int_data *int_data) /**< interpreter context */
|
||||
{
|
||||
const T_IDX dst_var_idx = opdata.data.b_and.dst;
|
||||
const T_IDX left_var_idx = opdata.data.b_and.var_left;
|
||||
const T_IDX right_var_idx = opdata.data.b_and.var_right;
|
||||
|
||||
int_data->pos++;
|
||||
|
||||
ecma_completion_value_t ret_value;
|
||||
|
||||
ECMA_TRY_CATCH (left_value, get_variable_value (int_data, left_var_idx, false), ret_value);
|
||||
ECMA_TRY_CATCH (right_value, get_variable_value (int_data, right_var_idx, false), ret_value);
|
||||
|
||||
ret_value = do_number_bitwise_logic (int_data,
|
||||
dst_var_idx,
|
||||
number_bitwise_logic_and,
|
||||
left_value.value,
|
||||
right_value.value);
|
||||
|
||||
ECMA_FINALIZE (right_value);
|
||||
ECMA_FINALIZE (left_value);
|
||||
|
||||
return ret_value;
|
||||
} /* opfunc_b_and */
|
||||
|
||||
/**
|
||||
* 'Bitwise OR' opcode handler.
|
||||
*
|
||||
* See also: ECMA-262 v5, 11.10
|
||||
*
|
||||
* @return completion value
|
||||
* Returned value must be freed with ecma_free_completion_value
|
||||
*/
|
||||
ecma_completion_value_t
|
||||
opfunc_b_or (OPCODE opdata, /**< operation data */
|
||||
__int_data *int_data) /**< interpreter context */
|
||||
{
|
||||
const T_IDX dst_var_idx = opdata.data.b_or.dst;
|
||||
const T_IDX left_var_idx = opdata.data.b_or.var_left;
|
||||
const T_IDX right_var_idx = opdata.data.b_or.var_right;
|
||||
|
||||
int_data->pos++;
|
||||
|
||||
ecma_completion_value_t ret_value;
|
||||
|
||||
ECMA_TRY_CATCH (left_value, get_variable_value (int_data, left_var_idx, false), ret_value);
|
||||
ECMA_TRY_CATCH (right_value, get_variable_value (int_data, right_var_idx, false), ret_value);
|
||||
|
||||
ret_value = do_number_bitwise_logic (int_data,
|
||||
dst_var_idx,
|
||||
number_bitwise_logic_or,
|
||||
left_value.value,
|
||||
right_value.value);
|
||||
|
||||
ECMA_FINALIZE (right_value);
|
||||
ECMA_FINALIZE (left_value);
|
||||
|
||||
return ret_value;
|
||||
} /* opfunc_b_or */
|
||||
|
||||
/**
|
||||
* 'Bitwise XOR' opcode handler.
|
||||
*
|
||||
* See also: ECMA-262 v5, 11.10
|
||||
*
|
||||
* @return completion value
|
||||
* Returned value must be freed with ecma_free_completion_value
|
||||
*/
|
||||
ecma_completion_value_t
|
||||
opfunc_b_xor (OPCODE opdata, /**< operation data */
|
||||
__int_data *int_data) /**< interpreter context */
|
||||
{
|
||||
const T_IDX dst_var_idx = opdata.data.b_xor.dst;
|
||||
const T_IDX left_var_idx = opdata.data.b_xor.var_left;
|
||||
const T_IDX right_var_idx = opdata.data.b_xor.var_right;
|
||||
|
||||
int_data->pos++;
|
||||
|
||||
ecma_completion_value_t ret_value;
|
||||
|
||||
ECMA_TRY_CATCH (left_value, get_variable_value (int_data, left_var_idx, false), ret_value);
|
||||
ECMA_TRY_CATCH (right_value, get_variable_value (int_data, right_var_idx, false), ret_value);
|
||||
|
||||
ret_value = do_number_bitwise_logic (int_data,
|
||||
dst_var_idx,
|
||||
number_bitwise_logic_xor,
|
||||
left_value.value,
|
||||
right_value.value);
|
||||
|
||||
ECMA_FINALIZE (right_value);
|
||||
ECMA_FINALIZE (left_value);
|
||||
|
||||
return ret_value;
|
||||
} /* opfunc_b_xor */
|
||||
|
||||
/**
|
||||
* 'Left Shift Operator' opcode handler.
|
||||
*
|
||||
* See also: ECMA-262 v5, 11.7.1
|
||||
*
|
||||
* @return completion value
|
||||
* Returned value must be freed with ecma_free_completion_value
|
||||
*/
|
||||
ecma_completion_value_t
|
||||
opfunc_b_shift_left (OPCODE opdata, /**< operation data */
|
||||
__int_data *int_data) /**< interpreter context */
|
||||
{
|
||||
const T_IDX dst_var_idx = opdata.data.b_shift_left.dst;
|
||||
const T_IDX left_var_idx = opdata.data.b_shift_left.var_left;
|
||||
const T_IDX right_var_idx = opdata.data.b_shift_left.var_right;
|
||||
|
||||
int_data->pos++;
|
||||
|
||||
ecma_completion_value_t ret_value;
|
||||
|
||||
ECMA_TRY_CATCH (left_value, get_variable_value (int_data, left_var_idx, false), ret_value);
|
||||
ECMA_TRY_CATCH (right_value, get_variable_value (int_data, right_var_idx, false), ret_value);
|
||||
|
||||
ret_value = do_number_bitwise_logic (int_data,
|
||||
dst_var_idx,
|
||||
number_bitwise_shift_left,
|
||||
left_value.value,
|
||||
right_value.value);
|
||||
|
||||
ECMA_FINALIZE (right_value);
|
||||
ECMA_FINALIZE (left_value);
|
||||
|
||||
return ret_value;
|
||||
} /* opfunc_b_shift_left */
|
||||
|
||||
/**
|
||||
* 'Right Shift Operator' opcode handler.
|
||||
*
|
||||
* See also: ECMA-262 v5, 11.7.2
|
||||
*
|
||||
* @return completion value
|
||||
* Returned value must be freed with ecma_free_completion_value
|
||||
*/
|
||||
ecma_completion_value_t
|
||||
opfunc_b_shift_right (OPCODE opdata, /**< operation data */
|
||||
__int_data *int_data) /**< interpreter context */
|
||||
{
|
||||
const T_IDX dst_var_idx = opdata.data.b_shift_right.dst;
|
||||
const T_IDX left_var_idx = opdata.data.b_shift_right.var_left;
|
||||
const T_IDX right_var_idx = opdata.data.b_shift_right.var_right;
|
||||
|
||||
int_data->pos++;
|
||||
|
||||
ecma_completion_value_t ret_value;
|
||||
|
||||
ECMA_TRY_CATCH (left_value, get_variable_value (int_data, left_var_idx, false), ret_value);
|
||||
ECMA_TRY_CATCH (right_value, get_variable_value (int_data, right_var_idx, false), ret_value);
|
||||
|
||||
ret_value = do_number_bitwise_logic (int_data,
|
||||
dst_var_idx,
|
||||
number_bitwise_shift_right,
|
||||
left_value.value,
|
||||
right_value.value);
|
||||
|
||||
ECMA_FINALIZE (right_value);
|
||||
ECMA_FINALIZE (left_value);
|
||||
|
||||
return ret_value;
|
||||
} /* opfunc_b_shift_right */
|
||||
|
||||
/**
|
||||
* 'Unsigned Right Shift Operator' opcode handler.
|
||||
*
|
||||
* See also: ECMA-262 v5, 11.7.3
|
||||
*
|
||||
* @return completion value
|
||||
* Returned value must be freed with ecma_free_completion_value
|
||||
*/
|
||||
ecma_completion_value_t
|
||||
opfunc_b_shift_uright (OPCODE opdata, /**< operation data */
|
||||
__int_data *int_data) /**< interpreter context */
|
||||
{
|
||||
const T_IDX dst_var_idx = opdata.data.b_shift_uright.dst;
|
||||
const T_IDX left_var_idx = opdata.data.b_shift_uright.var_left;
|
||||
const T_IDX right_var_idx = opdata.data.b_shift_uright.var_right;
|
||||
|
||||
int_data->pos++;
|
||||
|
||||
ecma_completion_value_t ret_value;
|
||||
|
||||
ECMA_TRY_CATCH (left_value, get_variable_value (int_data, left_var_idx, false), ret_value);
|
||||
ECMA_TRY_CATCH (right_value, get_variable_value (int_data, right_var_idx, false), ret_value);
|
||||
|
||||
ret_value = do_number_bitwise_logic (int_data,
|
||||
dst_var_idx,
|
||||
number_bitwise_shift_uright,
|
||||
left_value.value,
|
||||
right_value.value);
|
||||
|
||||
ECMA_FINALIZE (right_value);
|
||||
ECMA_FINALIZE (left_value);
|
||||
|
||||
return ret_value;
|
||||
} /* opfunc_b_shift_uright */
|
||||
|
||||
/**
|
||||
* 'Bitwise NOT Operator' opcode handler.
|
||||
*
|
||||
* See also: ECMA-262 v5, 10.4
|
||||
*
|
||||
* @return completion value
|
||||
* Returned value must be freed with ecma_free_completion_value
|
||||
*/
|
||||
ecma_completion_value_t
|
||||
opfunc_b_not (OPCODE opdata, /**< operation data */
|
||||
__int_data *int_data) /**< interpreter context */
|
||||
{
|
||||
const T_IDX dst_var_idx = opdata.data.b_not.dst;
|
||||
const T_IDX right_var_idx = opdata.data.b_not.var_right;
|
||||
|
||||
int_data->pos++;
|
||||
|
||||
ecma_completion_value_t ret_value;
|
||||
|
||||
ECMA_TRY_CATCH (right_value, get_variable_value (int_data, right_var_idx, false), ret_value);
|
||||
|
||||
ret_value = do_number_bitwise_logic (int_data,
|
||||
dst_var_idx,
|
||||
number_bitwise_not,
|
||||
right_value.value,
|
||||
right_value.value);
|
||||
|
||||
ECMA_FINALIZE (right_value);
|
||||
|
||||
return ret_value;
|
||||
} /* opfunc_b_not */
|
||||
287
src/libcoreint/opcodes-ecma-arithmetics.c
Normal file
287
src/libcoreint/opcodes-ecma-arithmetics.c
Normal file
@ -0,0 +1,287 @@
|
||||
/* Copyright 2014 Samsung Electronics Co., Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "opcodes.h"
|
||||
#include "opcodes-ecma-support.h"
|
||||
#include "ecma-number-arithmetic.h"
|
||||
|
||||
/**
|
||||
* Number arithmetic operations.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
number_arithmetic_addition, /**< addition */
|
||||
number_arithmetic_substraction, /**< substraction */
|
||||
number_arithmetic_multiplication, /**< multiplication */
|
||||
number_arithmetic_division, /**< division */
|
||||
number_arithmetic_remainder, /**< remainder calculation */
|
||||
} number_arithmetic_op;
|
||||
|
||||
/**
|
||||
* Perform ECMA number arithmetic operation.
|
||||
*
|
||||
* The algorithm of the operation is following:
|
||||
* leftNum = ToNumber (leftValue);
|
||||
* rightNum = ToNumber (rightValue);
|
||||
* result = leftNum ArithmeticOp rightNum;
|
||||
*
|
||||
* @return completion value
|
||||
* Returned value must be freed with ecma_free_completion_value
|
||||
*/
|
||||
static ecma_completion_value_t
|
||||
do_number_arithmetic (__int_data *int_data, /**< interpreter context */
|
||||
T_IDX dst_var_idx, /**< destination variable identifier */
|
||||
number_arithmetic_op op, /**< number arithmetic operation */
|
||||
ecma_value_t left_value, /**< left value */
|
||||
ecma_value_t right_value) /** right value */
|
||||
{
|
||||
ecma_completion_value_t ret_value;
|
||||
|
||||
ECMA_TRY_CATCH (num_left_value, ecma_op_to_number (left_value), ret_value);
|
||||
ECMA_TRY_CATCH (num_right_value, ecma_op_to_number (right_value), ret_value);
|
||||
|
||||
ecma_number_t *left_p, *right_p, *res_p;
|
||||
left_p = (ecma_number_t*) ECMA_GET_POINTER (num_left_value.value.value);
|
||||
right_p = (ecma_number_t*) ECMA_GET_POINTER (num_right_value.value.value);
|
||||
|
||||
res_p = ecma_alloc_number ();
|
||||
|
||||
switch (op)
|
||||
{
|
||||
case number_arithmetic_addition:
|
||||
{
|
||||
*res_p = ecma_op_number_add (*left_p, *right_p);
|
||||
break;
|
||||
}
|
||||
case number_arithmetic_substraction:
|
||||
{
|
||||
*res_p = ecma_op_number_substract (*left_p, *right_p);
|
||||
break;
|
||||
}
|
||||
case number_arithmetic_multiplication:
|
||||
{
|
||||
*res_p = ecma_op_number_multiply (*left_p, *right_p);
|
||||
break;
|
||||
}
|
||||
case number_arithmetic_division:
|
||||
{
|
||||
*res_p = ecma_op_number_divide (*left_p, *right_p);
|
||||
break;
|
||||
}
|
||||
case number_arithmetic_remainder:
|
||||
{
|
||||
*res_p = ecma_op_number_remainder (*left_p, *right_p);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ret_value = set_variable_value (int_data,
|
||||
dst_var_idx,
|
||||
ecma_make_number_value (res_p));
|
||||
|
||||
ecma_dealloc_number (res_p);
|
||||
|
||||
ECMA_FINALIZE (num_right_value);
|
||||
ECMA_FINALIZE (num_left_value);
|
||||
|
||||
return ret_value;
|
||||
} /* do_number_arithmetic */
|
||||
|
||||
/**
|
||||
* 'Addition' opcode handler.
|
||||
*
|
||||
* See also: ECMA-262 v5, 11.6.1
|
||||
*
|
||||
* @return completion value
|
||||
* Returned value must be freed with ecma_free_completion_value
|
||||
*/
|
||||
ecma_completion_value_t
|
||||
opfunc_addition (OPCODE opdata, /**< operation data */
|
||||
__int_data *int_data) /**< interpreter context */
|
||||
{
|
||||
const T_IDX dst_var_idx = opdata.data.addition.dst;
|
||||
const T_IDX left_var_idx = opdata.data.addition.var_left;
|
||||
const T_IDX right_var_idx = opdata.data.addition.var_right;
|
||||
|
||||
int_data->pos++;
|
||||
|
||||
ecma_completion_value_t ret_value;
|
||||
|
||||
ECMA_TRY_CATCH (left_value, get_variable_value (int_data, left_var_idx, false), ret_value);
|
||||
ECMA_TRY_CATCH (right_value, get_variable_value (int_data, right_var_idx, false), ret_value);
|
||||
ECMA_TRY_CATCH (prim_left_value, ecma_op_to_primitive (left_value.value, ECMA_PREFERRED_TYPE_NO), ret_value);
|
||||
ECMA_TRY_CATCH (prim_right_value, ecma_op_to_primitive (right_value.value, ECMA_PREFERRED_TYPE_NO), ret_value);
|
||||
|
||||
if (prim_left_value.value.value_type == ECMA_TYPE_STRING
|
||||
|| prim_right_value.value.value_type == ECMA_TYPE_STRING)
|
||||
{
|
||||
JERRY_UNIMPLEMENTED ();
|
||||
}
|
||||
else
|
||||
{
|
||||
ret_value = do_number_arithmetic (int_data,
|
||||
dst_var_idx,
|
||||
number_arithmetic_addition,
|
||||
prim_left_value.value,
|
||||
prim_right_value.value);
|
||||
}
|
||||
|
||||
ECMA_FINALIZE (prim_right_value);
|
||||
ECMA_FINALIZE (prim_left_value);
|
||||
ECMA_FINALIZE (right_value);
|
||||
ECMA_FINALIZE (left_value);
|
||||
|
||||
return ret_value;
|
||||
} /* opfunc_addition */
|
||||
|
||||
/**
|
||||
* 'Substraction' opcode handler.
|
||||
*
|
||||
* See also: ECMA-262 v5, 11.6.2
|
||||
*
|
||||
* @return completion value
|
||||
* Returned value must be freed with ecma_free_completion_value
|
||||
*/
|
||||
ecma_completion_value_t
|
||||
opfunc_substraction (OPCODE opdata, /**< operation data */
|
||||
__int_data *int_data) /**< interpreter context */
|
||||
{
|
||||
const T_IDX dst_var_idx = opdata.data.substraction.dst;
|
||||
const T_IDX left_var_idx = opdata.data.substraction.var_left;
|
||||
const T_IDX right_var_idx = opdata.data.substraction.var_right;
|
||||
|
||||
int_data->pos++;
|
||||
|
||||
ecma_completion_value_t ret_value;
|
||||
|
||||
ECMA_TRY_CATCH (left_value, get_variable_value (int_data, left_var_idx, false), ret_value);
|
||||
ECMA_TRY_CATCH (right_value, get_variable_value (int_data, right_var_idx, false), ret_value);
|
||||
|
||||
ret_value = do_number_arithmetic (int_data,
|
||||
dst_var_idx,
|
||||
number_arithmetic_substraction,
|
||||
left_value.value,
|
||||
right_value.value);
|
||||
|
||||
ECMA_FINALIZE (right_value);
|
||||
ECMA_FINALIZE (left_value);
|
||||
|
||||
return ret_value;
|
||||
} /* opfunc_substraction */
|
||||
|
||||
/**
|
||||
* 'Multiplication' opcode handler.
|
||||
*
|
||||
* See also: ECMA-262 v5, 11.5, 11.5.1
|
||||
*
|
||||
* @return completion value
|
||||
* Returned value must be freed with ecma_free_completion_value
|
||||
*/
|
||||
ecma_completion_value_t
|
||||
opfunc_multiplication (OPCODE opdata, /**< operation data */
|
||||
__int_data *int_data) /**< interpreter context */
|
||||
{
|
||||
const T_IDX dst_var_idx = opdata.data.multiplication.dst;
|
||||
const T_IDX left_var_idx = opdata.data.multiplication.var_left;
|
||||
const T_IDX right_var_idx = opdata.data.multiplication.var_right;
|
||||
|
||||
int_data->pos++;
|
||||
|
||||
ecma_completion_value_t ret_value;
|
||||
|
||||
ECMA_TRY_CATCH (left_value, get_variable_value (int_data, left_var_idx, false), ret_value);
|
||||
ECMA_TRY_CATCH (right_value, get_variable_value (int_data, right_var_idx, false), ret_value);
|
||||
|
||||
ret_value = do_number_arithmetic (int_data,
|
||||
dst_var_idx,
|
||||
number_arithmetic_multiplication,
|
||||
left_value.value,
|
||||
right_value.value);
|
||||
|
||||
ECMA_FINALIZE (right_value);
|
||||
ECMA_FINALIZE (left_value);
|
||||
|
||||
return ret_value;
|
||||
} /* opfunc_multiplication */
|
||||
|
||||
/**
|
||||
* 'Division' opcode handler.
|
||||
*
|
||||
* See also: ECMA-262 v5, 11.5, 11.5.2
|
||||
*
|
||||
* @return completion value
|
||||
* Returned value must be freed with ecma_free_completion_value
|
||||
*/
|
||||
ecma_completion_value_t
|
||||
opfunc_division (OPCODE opdata, /**< operation data */
|
||||
__int_data *int_data) /**< interpreter context */
|
||||
{
|
||||
const T_IDX dst_var_idx = opdata.data.division.dst;
|
||||
const T_IDX left_var_idx = opdata.data.division.var_left;
|
||||
const T_IDX right_var_idx = opdata.data.division.var_right;
|
||||
|
||||
int_data->pos++;
|
||||
|
||||
ecma_completion_value_t ret_value;
|
||||
|
||||
ECMA_TRY_CATCH (left_value, get_variable_value (int_data, left_var_idx, false), ret_value);
|
||||
ECMA_TRY_CATCH (right_value, get_variable_value (int_data, right_var_idx, false), ret_value);
|
||||
|
||||
ret_value = do_number_arithmetic (int_data,
|
||||
dst_var_idx,
|
||||
number_arithmetic_division,
|
||||
left_value.value,
|
||||
right_value.value);
|
||||
|
||||
ECMA_FINALIZE (right_value);
|
||||
ECMA_FINALIZE (left_value);
|
||||
|
||||
return ret_value;
|
||||
} /* opfunc_division */
|
||||
|
||||
/**
|
||||
* 'Remainder calculation' opcode handler.
|
||||
*
|
||||
* See also: ECMA-262 v5, 11.5, 11.5.3
|
||||
*
|
||||
* @return completion value
|
||||
* Returned value must be freed with ecma_free_completion_value
|
||||
*/
|
||||
ecma_completion_value_t
|
||||
opfunc_remainder (OPCODE opdata, /**< operation data */
|
||||
__int_data *int_data) /**< interpreter context */
|
||||
{
|
||||
const T_IDX dst_var_idx = opdata.data.remainder.dst;
|
||||
const T_IDX left_var_idx = opdata.data.remainder.var_left;
|
||||
const T_IDX right_var_idx = opdata.data.remainder.var_right;
|
||||
|
||||
int_data->pos++;
|
||||
|
||||
ecma_completion_value_t ret_value;
|
||||
|
||||
ECMA_TRY_CATCH (left_value, get_variable_value (int_data, left_var_idx, false), ret_value);
|
||||
ECMA_TRY_CATCH (right_value, get_variable_value (int_data, right_var_idx, false), ret_value);
|
||||
|
||||
ret_value = do_number_arithmetic (int_data,
|
||||
dst_var_idx,
|
||||
number_arithmetic_remainder,
|
||||
left_value.value,
|
||||
right_value.value);
|
||||
|
||||
ECMA_FINALIZE (right_value);
|
||||
ECMA_FINALIZE (left_value);
|
||||
|
||||
return ret_value;
|
||||
} /* opfunc_remainder */
|
||||
182
src/libcoreint/opcodes-ecma-support.h
Normal file
182
src/libcoreint/opcodes-ecma-support.h
Normal file
@ -0,0 +1,182 @@
|
||||
/* Copyright 2014 Samsung Electronics Co., Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef OPCODES_ECMA_SUPPORT_H
|
||||
#define OPCODES_ECMA_SUPPORT_H
|
||||
|
||||
#include "ecma-alloc.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-magic-strings.h"
|
||||
#include "ecma-number-arithmetic.h"
|
||||
#include "ecma-operations.h"
|
||||
#include "ecma-try-catch-macro.h"
|
||||
#include "ecma-objects.h"
|
||||
|
||||
#include "opcodes.h"
|
||||
|
||||
static bool do_strict_eval_arguments_check (ecma_reference_t) __unused;
|
||||
static ecma_completion_value_t get_variable_value (__int_data *, T_IDX, bool) __unused;
|
||||
static ecma_completion_value_t set_variable_value (__int_data *, T_IDX, ecma_value_t) __unused;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* @return true - if ref is strict reference
|
||||
* and it's base is lexical environment
|
||||
* and it's referenced name is 'eval' or 'arguments';
|
||||
* false - otherwise.
|
||||
*/
|
||||
static bool
|
||||
do_strict_eval_arguments_check (ecma_reference_t ref) /**< ECMA-reference */
|
||||
{
|
||||
bool ret;
|
||||
|
||||
if (ref.is_strict
|
||||
&& (ref.base.value_type == ECMA_TYPE_OBJECT)
|
||||
&& (ECMA_GET_POINTER (ref.base.value) != NULL)
|
||||
&& (((ecma_object_t*) ECMA_GET_POINTER (ref.base.value))->is_lexical_environment))
|
||||
{
|
||||
ecma_string_t* magic_string_eval = ecma_get_magic_string (ECMA_MAGIC_STRING_EVAL);
|
||||
ecma_string_t* magic_string_arguments = ecma_get_magic_string (ECMA_MAGIC_STRING_ARGUMENTS);
|
||||
|
||||
ret = (ecma_compare_ecma_string_to_ecma_string (ref.referenced_name_p,
|
||||
magic_string_eval) == 0
|
||||
|| ecma_compare_ecma_string_to_ecma_string (ref.referenced_name_p,
|
||||
magic_string_arguments) == 0);
|
||||
|
||||
ecma_deref_ecma_string (magic_string_eval);
|
||||
ecma_deref_ecma_string (magic_string_arguments);
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = false;
|
||||
}
|
||||
|
||||
return ret;
|
||||
} /* do_strict_eval_arguments_check */
|
||||
|
||||
/**
|
||||
* Get variable's value.
|
||||
*
|
||||
* @return completion value
|
||||
* Returned value must be freed with ecma_free_completion_value
|
||||
*/
|
||||
static ecma_completion_value_t
|
||||
get_variable_value (__int_data *int_data, /**< interpreter context */
|
||||
T_IDX var_idx, /**< variable identifier */
|
||||
bool do_eval_or_arguments_check) /** run 'strict eval or arguments reference' check
|
||||
See also: do_strict_eval_arguments_check */
|
||||
{
|
||||
ecma_completion_value_t ret_value;
|
||||
|
||||
if (var_idx >= int_data->min_reg_num
|
||||
&& var_idx <= int_data->max_reg_num)
|
||||
{
|
||||
ecma_value_t reg_value = int_data->regs_p[ var_idx - int_data->min_reg_num ];
|
||||
|
||||
JERRY_ASSERT (!ecma_is_value_empty (reg_value));
|
||||
|
||||
ret_value = ecma_make_completion_value (ECMA_COMPLETION_TYPE_NORMAL,
|
||||
ecma_copy_value (reg_value, true),
|
||||
ECMA_TARGET_ID_RESERVED);
|
||||
}
|
||||
else
|
||||
{
|
||||
ecma_reference_t ref;
|
||||
|
||||
ecma_string_t *var_name_string_p = ecma_new_ecma_string_from_lit_index (var_idx);
|
||||
|
||||
ref = ecma_op_get_identifier_reference (int_data->lex_env_p,
|
||||
var_name_string_p,
|
||||
int_data->is_strict);
|
||||
|
||||
if (unlikely (do_eval_or_arguments_check
|
||||
&& do_strict_eval_arguments_check (ref)))
|
||||
{
|
||||
ret_value = ecma_make_throw_value (ecma_new_standard_error (ECMA_ERROR_SYNTAX));
|
||||
}
|
||||
else
|
||||
{
|
||||
ret_value = ecma_op_get_value (ref);
|
||||
}
|
||||
|
||||
ecma_deref_ecma_string (var_name_string_p);
|
||||
ecma_free_reference (ref);
|
||||
}
|
||||
|
||||
return ret_value;
|
||||
} /* get_variable_value */
|
||||
|
||||
/**
|
||||
* Set variable's value.
|
||||
*
|
||||
* @return completion value
|
||||
* Returned value must be freed with ecma_free_completion_value
|
||||
*/
|
||||
static ecma_completion_value_t
|
||||
set_variable_value (__int_data *int_data, /**< interpreter context */
|
||||
T_IDX var_idx, /**< variable identifier */
|
||||
ecma_value_t value) /**< value to set */
|
||||
{
|
||||
ecma_completion_value_t ret_value;
|
||||
|
||||
if (var_idx >= int_data->min_reg_num
|
||||
&& var_idx <= int_data->max_reg_num)
|
||||
{
|
||||
ecma_value_t reg_value = int_data->regs_p[ var_idx - int_data->min_reg_num ];
|
||||
|
||||
if (!ecma_is_value_empty (reg_value))
|
||||
{
|
||||
ecma_free_value (reg_value, true);
|
||||
}
|
||||
|
||||
int_data->regs_p[ var_idx - int_data->min_reg_num ] = ecma_copy_value (value, true);
|
||||
|
||||
ret_value = ecma_make_empty_completion_value ();
|
||||
}
|
||||
else
|
||||
{
|
||||
ecma_reference_t ref;
|
||||
|
||||
ecma_string_t *var_name_string_p = ecma_new_ecma_string_from_lit_index (var_idx);
|
||||
|
||||
ref = ecma_op_get_identifier_reference (int_data->lex_env_p,
|
||||
var_name_string_p,
|
||||
int_data->is_strict);
|
||||
|
||||
if (unlikely (do_strict_eval_arguments_check (ref)))
|
||||
{
|
||||
ret_value = ecma_make_throw_value (ecma_new_standard_error (ECMA_ERROR_SYNTAX));
|
||||
}
|
||||
else
|
||||
{
|
||||
ret_value = ecma_op_put_value (ref, value);
|
||||
}
|
||||
|
||||
ecma_deref_ecma_string (var_name_string_p);
|
||||
ecma_free_reference (ref);
|
||||
}
|
||||
|
||||
return ret_value;
|
||||
} /* set_variable_value */
|
||||
|
||||
#endif /* OPCODES_ECMA_SUPPORT_H */
|
||||
155
src/libcoreint/opcodes-equality.c
Normal file
155
src/libcoreint/opcodes-equality.c
Normal file
@ -0,0 +1,155 @@
|
||||
/* Copyright 2014 Samsung Electronics Co., Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "opcodes.h"
|
||||
#include "opcodes-ecma-support.h"
|
||||
|
||||
/**
|
||||
* 'Equals' opcode handler.
|
||||
*
|
||||
* See also: ECMA-262 v5, 11.9.1
|
||||
*
|
||||
* @return completion value
|
||||
* Returned value must be freed with ecma_free_completion_value
|
||||
*/
|
||||
ecma_completion_value_t
|
||||
opfunc_equal_value (OPCODE opdata, /**< operation data */
|
||||
__int_data *int_data) /**< interpreter context */
|
||||
{
|
||||
const T_IDX dst_var_idx = opdata.data.equal_value.dst;
|
||||
const T_IDX left_var_idx = opdata.data.equal_value.var_left;
|
||||
const T_IDX right_var_idx = opdata.data.equal_value.var_right;
|
||||
|
||||
int_data->pos++;
|
||||
|
||||
ecma_completion_value_t ret_value;
|
||||
|
||||
ECMA_TRY_CATCH (left_value, get_variable_value (int_data, left_var_idx, false), ret_value);
|
||||
ECMA_TRY_CATCH (right_value, get_variable_value (int_data, right_var_idx, false), ret_value);
|
||||
|
||||
bool is_equal = ecma_op_abstract_equality_compare (left_value.value, right_value.value);
|
||||
|
||||
ret_value = set_variable_value (int_data, 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);
|
||||
|
||||
return ret_value;
|
||||
} /* opfunc_equal_value */
|
||||
|
||||
/**
|
||||
* 'Does-not-equals' opcode handler.
|
||||
*
|
||||
* See also: ECMA-262 v5, 11.9.2
|
||||
*
|
||||
* @return completion value
|
||||
* Returned value must be freed with ecma_free_completion_value
|
||||
*/
|
||||
ecma_completion_value_t
|
||||
opfunc_not_equal_value (OPCODE opdata, /**< operation data */
|
||||
__int_data *int_data) /**< interpreter context */
|
||||
{
|
||||
const T_IDX dst_var_idx = opdata.data.not_equal_value.dst;
|
||||
const T_IDX left_var_idx = opdata.data.not_equal_value.var_left;
|
||||
const T_IDX right_var_idx = opdata.data.not_equal_value.var_right;
|
||||
|
||||
int_data->pos++;
|
||||
|
||||
ecma_completion_value_t ret_value;
|
||||
|
||||
ECMA_TRY_CATCH (left_value, get_variable_value (int_data, left_var_idx, false), ret_value);
|
||||
ECMA_TRY_CATCH (right_value, get_variable_value (int_data, right_var_idx, false), ret_value);
|
||||
|
||||
bool is_equal = ecma_op_abstract_equality_compare (left_value.value, right_value.value);
|
||||
|
||||
ret_value = set_variable_value (int_data, 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);
|
||||
|
||||
return ret_value;
|
||||
} /* opfunc_not_equal_value */
|
||||
|
||||
/**
|
||||
* 'Strict Equals' opcode handler.
|
||||
*
|
||||
* See also: ECMA-262 v5, 11.9.4
|
||||
*
|
||||
* @return completion value
|
||||
* Returned value must be freed with ecma_free_completion_value
|
||||
*/
|
||||
ecma_completion_value_t
|
||||
opfunc_equal_value_type (OPCODE opdata, /**< operation data */
|
||||
__int_data *int_data) /**< interpreter context */
|
||||
{
|
||||
const T_IDX dst_var_idx = opdata.data.equal_value_type.dst;
|
||||
const T_IDX left_var_idx = opdata.data.equal_value_type.var_left;
|
||||
const T_IDX right_var_idx = opdata.data.equal_value_type.var_right;
|
||||
|
||||
int_data->pos++;
|
||||
|
||||
ecma_completion_value_t ret_value;
|
||||
|
||||
ECMA_TRY_CATCH (left_value, get_variable_value (int_data, left_var_idx, false), ret_value);
|
||||
ECMA_TRY_CATCH (right_value, get_variable_value (int_data, right_var_idx, false), ret_value);
|
||||
|
||||
bool is_equal = ecma_op_strict_equality_compare (left_value.value, right_value.value);
|
||||
|
||||
ret_value = set_variable_value (int_data, 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);
|
||||
|
||||
return ret_value;
|
||||
} /* opfunc_equal_value_type */
|
||||
|
||||
/**
|
||||
* 'Strict Does-not-equals' opcode handler.
|
||||
*
|
||||
* See also: ECMA-262 v5, 11.9.5
|
||||
*
|
||||
* @return completion value
|
||||
* Returned value must be freed with ecma_free_completion_value
|
||||
*/
|
||||
ecma_completion_value_t
|
||||
opfunc_not_equal_value_type (OPCODE opdata, /**< operation data */
|
||||
__int_data *int_data) /**< interpreter context */
|
||||
{
|
||||
const T_IDX dst_var_idx = opdata.data.not_equal_value_type.dst;
|
||||
const T_IDX left_var_idx = opdata.data.not_equal_value_type.var_left;
|
||||
const T_IDX right_var_idx = opdata.data.not_equal_value_type.var_right;
|
||||
|
||||
int_data->pos++;
|
||||
|
||||
ecma_completion_value_t ret_value;
|
||||
|
||||
ECMA_TRY_CATCH (left_value, get_variable_value (int_data, left_var_idx, false), ret_value);
|
||||
ECMA_TRY_CATCH (right_value, get_variable_value (int_data, right_var_idx, false), ret_value);
|
||||
|
||||
bool is_equal = ecma_op_strict_equality_compare (left_value.value, right_value.value);
|
||||
|
||||
ret_value = set_variable_value (int_data, 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);
|
||||
|
||||
return ret_value;
|
||||
} /* opfunc_not_equal_value_type */
|
||||
331
src/libcoreint/opcodes-relational.c
Normal file
331
src/libcoreint/opcodes-relational.c
Normal file
@ -0,0 +1,331 @@
|
||||
/* Copyright 2014 Samsung Electronics Co., Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "opcodes.h"
|
||||
#include "opcodes-ecma-support.h"
|
||||
|
||||
/**
|
||||
* 'Less-than' opcode handler.
|
||||
*
|
||||
* See also: ECMA-262 v5, 11.8.1
|
||||
*
|
||||
* @return completion value
|
||||
* Returned value must be freed with ecma_free_completion_value
|
||||
*/
|
||||
ecma_completion_value_t
|
||||
opfunc_less_than (OPCODE opdata, /**< operation data */
|
||||
__int_data *int_data) /**< interpreter context */
|
||||
{
|
||||
const T_IDX dst_var_idx = opdata.data.less_than.dst;
|
||||
const T_IDX left_var_idx = opdata.data.less_than.var_left;
|
||||
const T_IDX right_var_idx = opdata.data.less_than.var_right;
|
||||
|
||||
int_data->pos++;
|
||||
|
||||
ecma_completion_value_t ret_value;
|
||||
|
||||
ECMA_TRY_CATCH (left_value, get_variable_value (int_data, left_var_idx, false), ret_value);
|
||||
ECMA_TRY_CATCH (right_value, get_variable_value (int_data, right_var_idx, false), ret_value);
|
||||
ECMA_TRY_CATCH (compare_result,
|
||||
ecma_op_abstract_relational_compare (left_value.value,
|
||||
right_value.value,
|
||||
true),
|
||||
ret_value);
|
||||
|
||||
ecma_simple_value_t res;
|
||||
|
||||
if (ecma_is_value_undefined (compare_result.value))
|
||||
{
|
||||
res = ECMA_SIMPLE_VALUE_FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
JERRY_ASSERT (ecma_is_value_boolean (compare_result.value));
|
||||
|
||||
res = compare_result.value.value;
|
||||
}
|
||||
|
||||
ret_value = set_variable_value (int_data, dst_var_idx, ecma_make_simple_value (res));
|
||||
|
||||
ECMA_FINALIZE (compare_result);
|
||||
ECMA_FINALIZE (right_value);
|
||||
ECMA_FINALIZE (left_value);
|
||||
|
||||
return ret_value;
|
||||
} /* opfunc_less_than */
|
||||
|
||||
/**
|
||||
* 'Greater-than' opcode handler.
|
||||
*
|
||||
* See also: ECMA-262 v5, 11.8.2
|
||||
*
|
||||
* @return completion value
|
||||
* Returned value must be freed with ecma_free_completion_value
|
||||
*/
|
||||
ecma_completion_value_t
|
||||
opfunc_greater_than (OPCODE opdata, /**< operation data */
|
||||
__int_data *int_data) /**< interpreter context */
|
||||
{
|
||||
const T_IDX dst_var_idx = opdata.data.greater_than.dst;
|
||||
const T_IDX left_var_idx = opdata.data.greater_than.var_left;
|
||||
const T_IDX right_var_idx = opdata.data.greater_than.var_right;
|
||||
|
||||
int_data->pos++;
|
||||
|
||||
ecma_completion_value_t ret_value;
|
||||
|
||||
ECMA_TRY_CATCH (left_value, get_variable_value (int_data, left_var_idx, false), ret_value);
|
||||
ECMA_TRY_CATCH (right_value, get_variable_value (int_data, right_var_idx, false), ret_value);
|
||||
ECMA_TRY_CATCH (compare_result,
|
||||
ecma_op_abstract_relational_compare (right_value.value,
|
||||
left_value.value,
|
||||
false),
|
||||
ret_value);
|
||||
|
||||
ecma_simple_value_t res;
|
||||
|
||||
if (ecma_is_value_undefined (compare_result.value))
|
||||
{
|
||||
res = ECMA_SIMPLE_VALUE_FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
JERRY_ASSERT (ecma_is_value_boolean (compare_result.value));
|
||||
|
||||
res = compare_result.value.value;
|
||||
}
|
||||
|
||||
ret_value = set_variable_value (int_data, dst_var_idx, ecma_make_simple_value (res));
|
||||
|
||||
ECMA_FINALIZE (compare_result);
|
||||
ECMA_FINALIZE (right_value);
|
||||
ECMA_FINALIZE (left_value);
|
||||
|
||||
return ret_value;
|
||||
} /* opfunc_greater_than */
|
||||
|
||||
/**
|
||||
* 'Less-than-or-equal' opcode handler.
|
||||
*
|
||||
* See also: ECMA-262 v5, 11.8.3
|
||||
*
|
||||
* @return completion value
|
||||
* Returned value must be freed with ecma_free_completion_value
|
||||
*/
|
||||
ecma_completion_value_t
|
||||
opfunc_less_or_equal_than (OPCODE opdata, /**< operation data */
|
||||
__int_data *int_data) /**< interpreter context */
|
||||
{
|
||||
const T_IDX dst_var_idx = opdata.data.less_or_equal_than.dst;
|
||||
const T_IDX left_var_idx = opdata.data.less_or_equal_than.var_left;
|
||||
const T_IDX right_var_idx = opdata.data.less_or_equal_than.var_right;
|
||||
|
||||
int_data->pos++;
|
||||
|
||||
ecma_completion_value_t ret_value;
|
||||
|
||||
ECMA_TRY_CATCH (left_value, get_variable_value (int_data, left_var_idx, false), ret_value);
|
||||
ECMA_TRY_CATCH (right_value, get_variable_value (int_data, right_var_idx, false), ret_value);
|
||||
ECMA_TRY_CATCH (compare_result,
|
||||
ecma_op_abstract_relational_compare (right_value.value,
|
||||
left_value.value,
|
||||
false),
|
||||
ret_value);
|
||||
|
||||
ecma_simple_value_t res;
|
||||
|
||||
if (ecma_is_value_undefined (compare_result.value))
|
||||
{
|
||||
res = ECMA_SIMPLE_VALUE_FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
JERRY_ASSERT (ecma_is_value_boolean (compare_result.value));
|
||||
|
||||
if (compare_result.value.value == ECMA_SIMPLE_VALUE_TRUE)
|
||||
{
|
||||
res = ECMA_SIMPLE_VALUE_FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
res = ECMA_SIMPLE_VALUE_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
ret_value = set_variable_value (int_data, dst_var_idx, ecma_make_simple_value (res));
|
||||
|
||||
ECMA_FINALIZE (compare_result);
|
||||
ECMA_FINALIZE (right_value);
|
||||
ECMA_FINALIZE (left_value);
|
||||
|
||||
return ret_value;
|
||||
} /* opfunc_less_or_equal_than */
|
||||
|
||||
/**
|
||||
* 'Greater-than-or-equal' opcode handler.
|
||||
*
|
||||
* See also: ECMA-262 v5, 11.8.4
|
||||
*
|
||||
* @return completion value
|
||||
* Returned value must be freed with ecma_free_completion_value
|
||||
*/
|
||||
ecma_completion_value_t
|
||||
opfunc_greater_or_equal_than (OPCODE opdata, /**< operation data */
|
||||
__int_data *int_data) /**< interpreter context */
|
||||
{
|
||||
const T_IDX dst_var_idx = opdata.data.greater_or_equal_than.dst;
|
||||
const T_IDX left_var_idx = opdata.data.greater_or_equal_than.var_left;
|
||||
const T_IDX right_var_idx = opdata.data.greater_or_equal_than.var_right;
|
||||
|
||||
int_data->pos++;
|
||||
|
||||
ecma_completion_value_t ret_value;
|
||||
|
||||
ECMA_TRY_CATCH (left_value, get_variable_value (int_data, left_var_idx, false), ret_value);
|
||||
ECMA_TRY_CATCH (right_value, get_variable_value (int_data, right_var_idx, false), ret_value);
|
||||
ECMA_TRY_CATCH (compare_result,
|
||||
ecma_op_abstract_relational_compare (left_value.value,
|
||||
right_value.value,
|
||||
true),
|
||||
ret_value);
|
||||
|
||||
ecma_simple_value_t res;
|
||||
|
||||
if (ecma_is_value_undefined (compare_result.value))
|
||||
{
|
||||
res = ECMA_SIMPLE_VALUE_FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
JERRY_ASSERT (ecma_is_value_boolean (compare_result.value));
|
||||
|
||||
if (compare_result.value.value == ECMA_SIMPLE_VALUE_TRUE)
|
||||
{
|
||||
res = ECMA_SIMPLE_VALUE_FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
res = ECMA_SIMPLE_VALUE_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
ret_value = set_variable_value (int_data, dst_var_idx, ecma_make_simple_value (res));
|
||||
|
||||
ECMA_FINALIZE (compare_result);
|
||||
ECMA_FINALIZE (right_value);
|
||||
ECMA_FINALIZE (left_value);
|
||||
|
||||
return ret_value;
|
||||
} /* opfunc_greater_or_equal_than */
|
||||
|
||||
/**
|
||||
* 'instanceof' opcode handler.
|
||||
*
|
||||
* See also: ECMA-262 v5, 11.8.6
|
||||
*
|
||||
* @return completion value
|
||||
* returned value must be freed with ecma_free_completion_value.
|
||||
*/
|
||||
ecma_completion_value_t
|
||||
opfunc_instanceof (OPCODE opdata __unused, /**< operation data */
|
||||
__int_data *int_data __unused) /**< interpreter context */
|
||||
{
|
||||
const T_IDX dst_idx = opdata.data.instanceof.dst;
|
||||
const T_IDX left_var_idx = opdata.data.instanceof.var_left;
|
||||
const T_IDX right_var_idx = opdata.data.instanceof.var_right;
|
||||
|
||||
ecma_completion_value_t ret_value;
|
||||
|
||||
ECMA_TRY_CATCH (left_value, get_variable_value (int_data, left_var_idx, false), ret_value);
|
||||
ECMA_TRY_CATCH (right_value, get_variable_value (int_data, right_var_idx, false), ret_value);
|
||||
|
||||
if (right_value.value.value_type != ECMA_TYPE_OBJECT)
|
||||
{
|
||||
ret_value = ecma_make_throw_value (ecma_new_standard_error (ECMA_ERROR_TYPE));
|
||||
}
|
||||
else
|
||||
{
|
||||
ecma_object_t *right_value_obj_p = ECMA_GET_POINTER (right_value.value.value);
|
||||
|
||||
ECMA_TRY_CATCH (is_instance_of,
|
||||
ecma_op_object_has_instance (right_value_obj_p,
|
||||
left_value.value),
|
||||
ret_value);
|
||||
|
||||
ret_value = set_variable_value (int_data, dst_idx, is_instance_of.value);
|
||||
|
||||
ECMA_FINALIZE (is_instance_of);
|
||||
}
|
||||
|
||||
ECMA_FINALIZE (right_value);
|
||||
ECMA_FINALIZE (left_value);
|
||||
|
||||
return ret_value;
|
||||
} /* opfunc_instanceof */
|
||||
|
||||
/**
|
||||
* 'in' opcode handler.
|
||||
*
|
||||
* See also: ECMA-262 v5, 11.8.7
|
||||
*
|
||||
* @return completion value
|
||||
* returned value must be freed with ecma_free_completion_value.
|
||||
*/
|
||||
ecma_completion_value_t
|
||||
opfunc_in (OPCODE opdata __unused, /**< operation data */
|
||||
__int_data *int_data __unused) /**< interpreter context */
|
||||
{
|
||||
const T_IDX dst_idx = opdata.data.in.dst;
|
||||
const T_IDX left_var_idx = opdata.data.in.var_left;
|
||||
const T_IDX right_var_idx = opdata.data.in.var_right;
|
||||
|
||||
ecma_completion_value_t ret_value;
|
||||
|
||||
ECMA_TRY_CATCH (left_value, get_variable_value (int_data, left_var_idx, false), ret_value);
|
||||
ECMA_TRY_CATCH (right_value, get_variable_value (int_data, right_var_idx, false), ret_value);
|
||||
|
||||
if (right_value.value.value_type != ECMA_TYPE_OBJECT)
|
||||
{
|
||||
ret_value = ecma_make_throw_value (ecma_new_standard_error (ECMA_ERROR_TYPE));
|
||||
}
|
||||
else
|
||||
{
|
||||
ECMA_TRY_CATCH (str_left_value, ecma_op_to_string (left_value.value), ret_value);
|
||||
|
||||
ecma_simple_value_t is_in = ECMA_SIMPLE_VALUE_UNDEFINED;
|
||||
ecma_string_t *left_value_prop_name_p = ECMA_GET_POINTER (str_left_value.value.value);
|
||||
ecma_object_t *right_value_obj_p = ECMA_GET_POINTER (right_value.value.value);
|
||||
|
||||
if (ecma_op_object_has_property (right_value_obj_p, left_value_prop_name_p))
|
||||
{
|
||||
is_in = ECMA_SIMPLE_VALUE_TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
is_in = ECMA_SIMPLE_VALUE_FALSE;
|
||||
}
|
||||
|
||||
ret_value = set_variable_value (int_data,
|
||||
dst_idx,
|
||||
ecma_make_simple_value (is_in));
|
||||
|
||||
ECMA_FINALIZE (str_left_value);
|
||||
}
|
||||
|
||||
ECMA_FINALIZE (right_value);
|
||||
ECMA_FINALIZE (left_value);
|
||||
|
||||
return ret_value;
|
||||
} /* opfunc_in */
|
||||
119
src/libcoreint/opcodes-support.c
Normal file
119
src/libcoreint/opcodes-support.c
Normal file
@ -0,0 +1,119 @@
|
||||
/* Copyright 2014 Samsung Electronics Co., Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "opcodes-support.h"
|
||||
|
||||
#define GETOP_DEF_0(name) \
|
||||
__opcode getop_##name (void) \
|
||||
{ \
|
||||
__opcode opdata; \
|
||||
opdata.op_idx = __op__idx_##name; \
|
||||
return opdata; \
|
||||
}
|
||||
|
||||
#define GETOP_DEF_1(name, field1) \
|
||||
__opcode getop_##name (T_IDX arg1) \
|
||||
{ \
|
||||
__opcode opdata; \
|
||||
opdata.op_idx = __op__idx_##name; \
|
||||
opdata.data.name.field1 = arg1; \
|
||||
return opdata; \
|
||||
}
|
||||
|
||||
#define GETOP_DEF_2(name, field1, field2) \
|
||||
__opcode getop_##name (T_IDX arg1, T_IDX arg2) \
|
||||
{ \
|
||||
__opcode opdata; \
|
||||
opdata.op_idx = __op__idx_##name; \
|
||||
opdata.data.name.field1 = arg1; \
|
||||
opdata.data.name.field2 = arg2; \
|
||||
return opdata; \
|
||||
}
|
||||
|
||||
#define GETOP_DEF_3(name, field1, field2, field3) \
|
||||
__opcode getop_##name (T_IDX arg1, T_IDX arg2, T_IDX arg3) \
|
||||
{ \
|
||||
__opcode opdata; \
|
||||
opdata.op_idx = __op__idx_##name; \
|
||||
opdata.data.name.field1 = arg1; \
|
||||
opdata.data.name.field2 = arg2; \
|
||||
opdata.data.name.field3 = arg3; \
|
||||
return opdata; \
|
||||
}
|
||||
|
||||
GETOP_DEF_3 (construct_decl, lhs, name_lit_idx, arg_list)
|
||||
GETOP_DEF_1 (func_decl_0, name_lit_idx)
|
||||
GETOP_DEF_2 (array_decl, lhs, list)
|
||||
GETOP_DEF_3 (prop, lhs, name, value)
|
||||
GETOP_DEF_3 (prop_getter, lhs, obj, prop)
|
||||
GETOP_DEF_3 (prop_setter, obj, prop, rhs)
|
||||
GETOP_DEF_2 (prop_get_decl, lhs, prop)
|
||||
GETOP_DEF_3 (prop_set_decl, lhs, prop, arg)
|
||||
GETOP_DEF_2 (obj_decl, lhs, list)
|
||||
GETOP_DEF_1 (this, lhs)
|
||||
GETOP_DEF_2 (delete, lhs, obj)
|
||||
GETOP_DEF_2 (typeof, lhs, obj)
|
||||
GETOP_DEF_1 (with, expr)
|
||||
GETOP_DEF_0 (end_with)
|
||||
GETOP_DEF_1 (var_decl, variable_name)
|
||||
GETOP_DEF_2 (reg_var_decl, min, max)
|
||||
GETOP_DEF_3 (meta, type, data_1, data_2)
|
||||
GETOP_DEF_2 (is_true_jmp, value, opcode)
|
||||
GETOP_DEF_2 (is_false_jmp, value, opcode)
|
||||
GETOP_DEF_1 (jmp, opcode_idx)
|
||||
GETOP_DEF_1 (jmp_up, opcode_count)
|
||||
GETOP_DEF_1 (jmp_down, opcode_count)
|
||||
GETOP_DEF_3 (addition, dst, var_left, var_right)
|
||||
GETOP_DEF_2 (post_incr, dst, var_right)
|
||||
GETOP_DEF_2 (post_decr, dst, var_right)
|
||||
GETOP_DEF_2 (pre_incr, dst, var_right)
|
||||
GETOP_DEF_2 (pre_decr, dst, var_right)
|
||||
GETOP_DEF_3 (substraction, dst, var_left, var_right)
|
||||
GETOP_DEF_3 (division, dst, var_left, var_right)
|
||||
GETOP_DEF_3 (multiplication, dst, var_left, var_right)
|
||||
GETOP_DEF_3 (remainder, dst, var_left, var_right)
|
||||
GETOP_DEF_3 (b_shift_left, dst, var_left, var_right)
|
||||
GETOP_DEF_3 (b_shift_right, dst, var_left, var_right)
|
||||
GETOP_DEF_3 (b_shift_uright, dst, var_left, var_right)
|
||||
GETOP_DEF_3 (b_and, dst, var_left, var_right)
|
||||
GETOP_DEF_3 (b_or, dst, var_left, var_right)
|
||||
GETOP_DEF_3 (b_xor, dst, var_left, var_right)
|
||||
GETOP_DEF_3 (logical_and, dst, var_left, var_right)
|
||||
GETOP_DEF_3 (logical_or, dst, var_left, var_right)
|
||||
GETOP_DEF_3 (equal_value, dst, var_left, var_right)
|
||||
GETOP_DEF_3 (not_equal_value, dst, var_left, var_right)
|
||||
GETOP_DEF_3 (equal_value_type, dst, var_left, var_right)
|
||||
GETOP_DEF_3 (not_equal_value_type, dst, var_left, var_right)
|
||||
GETOP_DEF_3 (less_than, dst, var_left, var_right)
|
||||
GETOP_DEF_3 (greater_than, dst, var_left, var_right)
|
||||
GETOP_DEF_3 (less_or_equal_than, dst, var_left, var_right)
|
||||
GETOP_DEF_3 (greater_or_equal_than, dst, var_left, var_right)
|
||||
GETOP_DEF_3 (assignment, var_left, type_value_right, value_right)
|
||||
GETOP_DEF_2 (call_0, lhs, name_lit_idx)
|
||||
GETOP_DEF_3 (call_1, lhs, name_lit_idx, arg1_lit_idx)
|
||||
GETOP_DEF_3 (call_n, lhs, name_lit_idx, arg1_lit_idx)
|
||||
GETOP_DEF_3 (native_call, lhs, name, arg_list)
|
||||
GETOP_DEF_2 (func_decl_1, name_lit_idx, arg1_lit_idx)
|
||||
GETOP_DEF_3 (func_decl_2, name_lit_idx, arg1_lit_idx, arg2_lit_idx)
|
||||
GETOP_DEF_3 (func_decl_n, name_lit_idx, arg1_lit_idx, arg2_lit_idx)
|
||||
GETOP_DEF_3 (varg_list, arg1_lit_idx, arg2_lit_idx, arg3_lit_idx)
|
||||
GETOP_DEF_1 (exitval, status_code)
|
||||
GETOP_DEF_1 (retval, ret_value)
|
||||
GETOP_DEF_0 (ret)
|
||||
GETOP_DEF_0 (nop)
|
||||
GETOP_DEF_2 (b_not, dst, var_right)
|
||||
GETOP_DEF_2 (logical_not, dst, var_right)
|
||||
GETOP_DEF_3 (instanceof, dst, var_left, var_right)
|
||||
GETOP_DEF_3 (in, dst, var_left, var_right)
|
||||
99
src/libcoreint/opcodes-support.h
Normal file
99
src/libcoreint/opcodes-support.h
Normal file
@ -0,0 +1,99 @@
|
||||
/* Copyright 2014 Samsung Electronics Co., Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef OPCODES_SUPPORT_H
|
||||
#define OPCODES_SUPPORT_H
|
||||
|
||||
#include "opcodes.h"
|
||||
|
||||
#define GETOP_DECL_0(name) \
|
||||
__opcode getop_##name (void);
|
||||
|
||||
#define GETOP_DECL_1(name, field1) \
|
||||
__opcode getop_##name (T_IDX);
|
||||
|
||||
#define GETOP_DECL_2(name, field1, field2) \
|
||||
__opcode getop_##name (T_IDX, T_IDX);
|
||||
|
||||
#define GETOP_DECL_3(name, field1, field2, field3) \
|
||||
__opcode getop_##name (T_IDX, T_IDX, T_IDX);
|
||||
|
||||
GETOP_DECL_3 (construct_decl, lhs, name_lit_idx, arg_list)
|
||||
GETOP_DECL_1 (func_decl_0, name_lit_idx)
|
||||
GETOP_DECL_2 (array_decl, lhs, list)
|
||||
GETOP_DECL_3 (prop, lhs, name, value)
|
||||
GETOP_DECL_3 (prop_getter, lhs, obj, prop)
|
||||
GETOP_DECL_3 (prop_setter, obj, prop, rhs)
|
||||
GETOP_DECL_2 (prop_get_decl, lhs, prop)
|
||||
GETOP_DECL_3 (prop_set_decl, lhs, prop, arg)
|
||||
GETOP_DECL_2 (obj_decl, lhs, list)
|
||||
GETOP_DECL_1 (this, lhs)
|
||||
GETOP_DECL_2 (delete, lhs, obj)
|
||||
GETOP_DECL_2 (typeof, lhs, obj)
|
||||
GETOP_DECL_1 (with, expr)
|
||||
GETOP_DECL_0 (end_with)
|
||||
GETOP_DECL_1 (var_decl, variable_name)
|
||||
GETOP_DECL_2 (reg_var_decl, min, max)
|
||||
GETOP_DECL_3 (meta, type, data_1, data_2)
|
||||
GETOP_DECL_2 (is_true_jmp, value, opcode)
|
||||
GETOP_DECL_2 (is_false_jmp, value, opcode)
|
||||
GETOP_DECL_1 (jmp, opcode_idx)
|
||||
GETOP_DECL_1 (jmp_up, opcode_count)
|
||||
GETOP_DECL_1 (jmp_down, opcode_count)
|
||||
GETOP_DECL_3 (addition, dst, var_left, var_right)
|
||||
GETOP_DECL_2 (post_incr, dst, var_right)
|
||||
GETOP_DECL_2 (post_decr, dst, var_right)
|
||||
GETOP_DECL_2 (pre_incr, dst, var_right)
|
||||
GETOP_DECL_2 (pre_decr, dst, var_right)
|
||||
GETOP_DECL_3 (substraction, dst, var_left, var_right)
|
||||
GETOP_DECL_3 (division, dst, var_left, var_right)
|
||||
GETOP_DECL_3 (multiplication, dst, var_left, var_right)
|
||||
GETOP_DECL_3 (remainder, dst, var_left, var_right)
|
||||
GETOP_DECL_3 (b_shift_left, dst, var_left, var_right)
|
||||
GETOP_DECL_3 (b_shift_right, dst, var_left, var_right)
|
||||
GETOP_DECL_3 (b_shift_uright, dst, var_left, var_right)
|
||||
GETOP_DECL_3 (b_and, dst, var_left, var_right)
|
||||
GETOP_DECL_3 (b_or, dst, var_left, var_right)
|
||||
GETOP_DECL_3 (b_xor, dst, var_left, var_right)
|
||||
GETOP_DECL_3 (logical_and, dst, var_left, var_right)
|
||||
GETOP_DECL_3 (logical_or, dst, var_left, var_right)
|
||||
GETOP_DECL_3 (equal_value, dst, var_left, var_right)
|
||||
GETOP_DECL_3 (not_equal_value, dst, var_left, var_right)
|
||||
GETOP_DECL_3 (equal_value_type, dst, var_left, var_right)
|
||||
GETOP_DECL_3 (not_equal_value_type, dst, var_left, var_right)
|
||||
GETOP_DECL_3 (less_than, dst, var_left, var_right)
|
||||
GETOP_DECL_3 (greater_than, dst, var_left, var_right)
|
||||
GETOP_DECL_3 (less_or_equal_than, dst, var_left, var_right)
|
||||
GETOP_DECL_3 (greater_or_equal_than, dst, var_left, var_right)
|
||||
GETOP_DECL_3 (assignment, var_left, type_value_right, value_right)
|
||||
GETOP_DECL_2 (call_0, lhs, name_lit_idx)
|
||||
GETOP_DECL_3 (call_1, lhs, name_lit_idx, arg1_lit_idx)
|
||||
GETOP_DECL_3 (call_n, lhs, name_lit_idx, arg1_lit_idx)
|
||||
GETOP_DECL_3 (native_call, lhs, name, arg_list)
|
||||
GETOP_DECL_2 (func_decl_1, name_lit_idx, arg1_lit_idx)
|
||||
GETOP_DECL_3 (func_decl_2, name_lit_idx, arg1_lit_idx, arg2_lit_idx)
|
||||
GETOP_DECL_3 (func_decl_n, name_lit_idx, arg1_lit_idx, arg2_lit_idx)
|
||||
GETOP_DECL_3 (varg_list, arg1_lit_idx, arg2_lit_idx, arg3_lit_idx)
|
||||
GETOP_DECL_1 (exitval, status_code)
|
||||
GETOP_DECL_1 (retval, ret_value)
|
||||
GETOP_DECL_0 (ret)
|
||||
GETOP_DECL_0 (nop)
|
||||
GETOP_DECL_2 (b_not, dst, var_right)
|
||||
GETOP_DECL_2 (logical_not, dst, var_right)
|
||||
GETOP_DECL_3 (instanceof, dst, var_left, var_right)
|
||||
GETOP_DECL_3 (in, dst, var_left, var_right)
|
||||
|
||||
#endif /* OPCODES_SUPPORT_H */
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -19,22 +19,26 @@
|
||||
#include "ecma-globals.h"
|
||||
#include "globals.h"
|
||||
|
||||
#define OPCODE struct __opcode
|
||||
struct __int_data;
|
||||
|
||||
#define OP_STRUCT_FIELD(name) struct __op_##name name;
|
||||
#define OP_ENUM_FIELD(name) __op__idx_##name ,
|
||||
#define OP_FUNC_DECL(name) ecma_completion_value_t opfunc_##name (OPCODE, struct __int_data *);
|
||||
|
||||
/** A single bytecode instruction is 32bit wide and has an 8bit opcode field
|
||||
and several operand of 8 of 16 bit.*/
|
||||
|
||||
// OPCODE FIELD TYPES
|
||||
#define T_IDX uint8_t /** index values */
|
||||
#define OPCODE __opcode
|
||||
|
||||
OPCODE;
|
||||
typedef
|
||||
ecma_completion_value_t (*opfunc) (OPCODE, struct __int_data *);
|
||||
#define OP_STRUCT_FIELD(name) __op_##name name;
|
||||
#define OP_ENUM_FIELD(name) __op__idx_##name ,
|
||||
#define OP_FUNC_DECL(name) ecma_completion_value_t opfunc_##name (__opcode, __int_data*);
|
||||
|
||||
typedef uint16_t opcode_counter_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
opcode_counter_t pos; /**< current opcode to execute */
|
||||
ecma_value_t this_binding; /**< this binding for current context */
|
||||
ecma_object_t *lex_env_p; /**< current lexical environment */
|
||||
bool is_strict; /**< is current code execution mode strict? */
|
||||
bool is_eval_code; /**< is current code executed with eval */
|
||||
T_IDX min_reg_num; /**< minimum idx used for register identification */
|
||||
T_IDX max_reg_num; /**< maximum idx used for register identification */
|
||||
ecma_value_t *regs_p; /**< register variables */
|
||||
} __int_data;
|
||||
|
||||
#define OP_CALLS_AND_ARGS(op) \
|
||||
op (call_0) \
|
||||
@ -135,7 +139,108 @@ ecma_completion_value_t (*opfunc) (OPCODE, struct __int_data *);
|
||||
op (reg_var_decl)\
|
||||
op (meta)
|
||||
|
||||
#include "opcode-structures.h"
|
||||
#define OP_DATA (name, list) typedef struct { list ; } __op_##name;
|
||||
|
||||
#define OP_DATA_0(name) \
|
||||
typedef struct \
|
||||
{ \
|
||||
T_IDX __do_not_use; \
|
||||
} __op_##name
|
||||
|
||||
#define OP_DATA_1(name, arg1) \
|
||||
typedef struct \
|
||||
{ \
|
||||
T_IDX arg1; \
|
||||
} __op_##name
|
||||
|
||||
#define OP_DATA_2(name, arg1, arg2) \
|
||||
typedef struct \
|
||||
{ \
|
||||
T_IDX arg1; \
|
||||
T_IDX arg2; \
|
||||
} __op_##name
|
||||
|
||||
#define OP_DATA_3(name, arg1, arg2, arg3) \
|
||||
typedef struct \
|
||||
{ \
|
||||
T_IDX arg1; \
|
||||
T_IDX arg2; \
|
||||
T_IDX arg3; \
|
||||
} __op_##name
|
||||
|
||||
OP_DATA_2 (is_true_jmp, value, opcode);
|
||||
OP_DATA_2 (is_false_jmp, value, opcode);
|
||||
OP_DATA_1 (jmp, opcode_idx);
|
||||
OP_DATA_1 (jmp_up, opcode_count);
|
||||
OP_DATA_1 (jmp_down, opcode_count);
|
||||
OP_DATA_3 (addition, dst, var_left, var_right);
|
||||
OP_DATA_2 (post_incr, dst, var_right);
|
||||
OP_DATA_2 (post_decr, dst, var_right);
|
||||
OP_DATA_2 (pre_incr, dst, var_right);
|
||||
OP_DATA_2 (pre_decr, dst, var_right);
|
||||
OP_DATA_3 (substraction, dst, var_left, var_right);
|
||||
OP_DATA_3 (division, dst, var_left, var_right);
|
||||
OP_DATA_3 (multiplication, dst, var_left, var_right);
|
||||
OP_DATA_3 (remainder, dst, var_left, var_right);
|
||||
OP_DATA_3 (b_shift_left, dst, var_left, var_right);
|
||||
OP_DATA_3 (b_shift_right, dst, var_left, var_right);
|
||||
OP_DATA_3 (b_shift_uright, dst, var_left, var_right);
|
||||
OP_DATA_3 (b_and, dst, var_left, var_right);
|
||||
OP_DATA_3 (b_or, dst, var_left, var_right);
|
||||
OP_DATA_3 (b_xor, dst, var_left, var_right);
|
||||
OP_DATA_3 (logical_and, dst, var_left, var_right);
|
||||
OP_DATA_3 (logical_or, dst, var_left, var_right);
|
||||
OP_DATA_3 (equal_value, dst, var_left, var_right);
|
||||
OP_DATA_3 (not_equal_value, dst, var_left, var_right);
|
||||
OP_DATA_3 (equal_value_type, dst, var_left, var_right);
|
||||
OP_DATA_3 (not_equal_value_type, dst, var_left, var_right);
|
||||
OP_DATA_3 (less_than, dst, var_left, var_right);
|
||||
OP_DATA_3 (greater_than, dst, var_left, var_right);
|
||||
OP_DATA_3 (less_or_equal_than, dst, var_left, var_right);
|
||||
OP_DATA_3 (greater_or_equal_than, dst, var_left, var_right);
|
||||
OP_DATA_3 (assignment, var_left, type_value_right, value_right);
|
||||
OP_DATA_2 (call_0, lhs, name_lit_idx);
|
||||
OP_DATA_3 (call_1, lhs, name_lit_idx, arg1_lit_idx);
|
||||
OP_DATA_3 (call_n, lhs, name_lit_idx, arg1_lit_idx);
|
||||
OP_DATA_3 (native_call, lhs, name, arg_list);
|
||||
OP_DATA_2 (func_decl_1, name_lit_idx, arg1_lit_idx);
|
||||
OP_DATA_3 (func_decl_2, name_lit_idx, arg1_lit_idx, arg2_lit_idx);
|
||||
OP_DATA_3 (func_decl_n, name_lit_idx, arg1_lit_idx, arg2_lit_idx);
|
||||
OP_DATA_3 (varg_list, arg1_lit_idx, arg2_lit_idx, arg3_lit_idx);
|
||||
OP_DATA_1 (exitval, status_code);
|
||||
OP_DATA_1 (retval, ret_value);
|
||||
OP_DATA_0 (ret);
|
||||
OP_DATA_0 (nop);
|
||||
OP_DATA_1 (var_decl, variable_name);
|
||||
OP_DATA_2 (b_not, dst, var_right);
|
||||
OP_DATA_2 (logical_not, dst, var_right);
|
||||
OP_DATA_3 (instanceof, dst, var_left, var_right);
|
||||
OP_DATA_3 (in, dst, var_left, var_right);
|
||||
OP_DATA_3 (construct_decl, lhs, name_lit_idx, arg_list);
|
||||
OP_DATA_1 (func_decl_0, name_lit_idx);
|
||||
OP_DATA_2 (array_decl, lhs, list);
|
||||
OP_DATA_3 (prop, lhs, name, value);
|
||||
OP_DATA_3 (prop_getter, lhs, obj, prop);
|
||||
OP_DATA_3 (prop_setter, obj, prop, rhs);
|
||||
OP_DATA_2 (prop_get_decl, lhs, prop);
|
||||
OP_DATA_3 (prop_set_decl, lhs, prop, arg);
|
||||
OP_DATA_2 (obj_decl, lhs, list);
|
||||
OP_DATA_1 (this, lhs);
|
||||
OP_DATA_2 (delete, lhs, obj);
|
||||
OP_DATA_2 (typeof, lhs, obj);
|
||||
OP_DATA_1 (with, expr);
|
||||
OP_DATA_0 (end_with);
|
||||
OP_DATA_2 (reg_var_decl, min, max);
|
||||
OP_DATA_3 (meta, type, data_1, data_2);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
T_IDX op_idx;
|
||||
union
|
||||
{
|
||||
OP_LIST (OP_STRUCT_FIELD)
|
||||
} data;
|
||||
} __opcode;
|
||||
|
||||
enum __opcode_idx
|
||||
{
|
||||
@ -143,19 +248,10 @@ enum __opcode_idx
|
||||
LAST_OP
|
||||
};
|
||||
|
||||
union __opdata
|
||||
{
|
||||
OP_LIST (OP_STRUCT_FIELD)
|
||||
};
|
||||
|
||||
OP_LIST (OP_FUNC_DECL)
|
||||
|
||||
OPCODE
|
||||
{
|
||||
T_IDX op_idx;
|
||||
union __opdata data;
|
||||
}
|
||||
__packed;
|
||||
|
||||
typedef ecma_completion_value_t (*opfunc) (__opcode, __int_data *);
|
||||
|
||||
/**
|
||||
* Descriptor of assignment's second argument
|
||||
|
||||
@ -17,7 +17,7 @@
|
||||
#include "jerry-libc.h"
|
||||
#include "lexer.h"
|
||||
#include "parser.h"
|
||||
#include "opcodes.h"
|
||||
#include "opcodes-support.h"
|
||||
#include "serializer.h"
|
||||
#include "interpreter.h"
|
||||
|
||||
|
||||
@ -25,7 +25,7 @@
|
||||
#op,
|
||||
|
||||
#define OPCODE_SIZE(op) \
|
||||
sizeof (struct __op_##op) + 1,
|
||||
sizeof (__op_##op) + 1,
|
||||
|
||||
static char* opcode_names[] =
|
||||
{
|
||||
|
||||
@ -19,7 +19,7 @@
|
||||
#define NAME_TO_ID(op) (__op__idx_##op)
|
||||
|
||||
#define OPCODE_SIZE(op) \
|
||||
sizeof (struct __op_##op) + 1,
|
||||
sizeof (__op_##op) + 1,
|
||||
|
||||
static uint8_t opcode_sizes[] = {
|
||||
OP_LIST (OPCODE_SIZE)
|
||||
@ -28,7 +28,7 @@ static uint8_t opcode_sizes[] = {
|
||||
|
||||
static bool
|
||||
opcodes_equal (const OPCODE *opcodes1, OPCODE *opcodes2, uint16_t size)
|
||||
{
|
||||
{
|
||||
uint16_t i;
|
||||
for (i = 0; i < size; i++)
|
||||
{
|
||||
@ -37,11 +37,11 @@ opcodes_equal (const OPCODE *opcodes1, OPCODE *opcodes2, uint16_t size)
|
||||
|
||||
if (opcode_num1 != opcode_num2)
|
||||
return false;
|
||||
|
||||
|
||||
if (opcode_num1 == NAME_TO_ID (nop) || opcode_num1 == NAME_TO_ID (ret)
|
||||
|| opcode_num1 == NAME_TO_ID (end_with))
|
||||
return true;
|
||||
|
||||
|
||||
for (j = 1; j < opcode_sizes[opcode_num1]; j++)
|
||||
if (((uint8_t*)&opcodes1[i])[j] != ((uint8_t*)&opcodes2[i])[j])
|
||||
return false;
|
||||
|
||||
@ -16,7 +16,7 @@
|
||||
#include "globals.h"
|
||||
#include "interpreter.h"
|
||||
#include "mem-allocator.h"
|
||||
#include "opcodes.h"
|
||||
#include "opcodes-support.h"
|
||||
#include "serializer.h"
|
||||
|
||||
/**
|
||||
|
||||
@ -16,7 +16,7 @@
|
||||
#include "globals.h"
|
||||
#include "interpreter.h"
|
||||
#include "mem-allocator.h"
|
||||
#include "opcodes.h"
|
||||
#include "opcodes-support.h"
|
||||
#include "serializer.h"
|
||||
|
||||
/**
|
||||
|
||||
@ -16,7 +16,7 @@
|
||||
#include "globals.h"
|
||||
#include "interpreter.h"
|
||||
#include "mem-allocator.h"
|
||||
#include "opcodes.h"
|
||||
#include "opcodes-support.h"
|
||||
#include "serializer.h"
|
||||
|
||||
/**
|
||||
|
||||
@ -16,7 +16,7 @@
|
||||
#include "globals.h"
|
||||
#include "interpreter.h"
|
||||
#include "mem-allocator.h"
|
||||
#include "opcodes.h"
|
||||
#include "opcodes-support.h"
|
||||
#include "serializer.h"
|
||||
|
||||
/**
|
||||
|
||||
@ -16,7 +16,7 @@
|
||||
#include "globals.h"
|
||||
#include "interpreter.h"
|
||||
#include "mem-allocator.h"
|
||||
#include "opcodes.h"
|
||||
#include "opcodes-support.h"
|
||||
#include "serializer.h"
|
||||
#include "optimizer-passes.h"
|
||||
#include "jerry-libc.h"
|
||||
@ -91,4 +91,4 @@ main( int __unused argc,
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -22,6 +22,7 @@
|
||||
#include "lexer.h"
|
||||
#include "parser.h"
|
||||
#include "mem-allocator.h"
|
||||
#include "opcodes-support.h"
|
||||
|
||||
#define MAX_STRINGS 100
|
||||
#define MAX_NUMS 25
|
||||
@ -55,43 +56,43 @@ main( int __unused argc,
|
||||
|
||||
offset = serializer_dump_strings (strings, strings_num);
|
||||
serializer_dump_nums (nums, nums_count, offset, strings_num);
|
||||
|
||||
|
||||
parser_init ();
|
||||
parser_parse_program ();
|
||||
|
||||
opcodes = deserialize_bytecode ();
|
||||
serializer_print_opcodes ();
|
||||
if (!opcodes_equal (opcodes, (OPCODE[]) {
|
||||
[0] = getop_reg_var_decl (2, 5), // var tmp2 .. tmp5;
|
||||
[1] = getop_var_decl (0), // var i;
|
||||
[2] = getop_var_decl (1), // var j;
|
||||
[3] = getop_assignment (2, 1, 0), // tmp2 = 0;
|
||||
[4] = getop_assignment (0, 4, 2), // i = tmp2;
|
||||
[5] = getop_assignment (4, 1, 10),// tmp4 = 10;
|
||||
[6] = getop_less_than (3, 0, 4), // tmp3 = i < tmp4;
|
||||
[7] = getop_is_false_jmp (3, 14), // if (!tmp3) goto 14;
|
||||
[8] = getop_jmp_down (3), // goto 11;
|
||||
[9] = getop_post_incr (5, 0), // tmp5 = i ++;
|
||||
[10] = getop_jmp_up (5), // goto 5;
|
||||
[11] = getop_assignment (2, 1, 10),// tmp2 = 10;
|
||||
[12] = getop_assignment (1, 4, 2), // j = tmp2;
|
||||
[13] = getop_jmp_up (5), // goto 8;
|
||||
[14] = getop_nop (), // ;
|
||||
[15] = getop_assignment (2, 1, 0), // tmp2 = 0;
|
||||
[16] = getop_assignment (0, 4, 2), // i = tmp2;
|
||||
[17] = getop_assignment (4, 1, 10),// tmp7 = 10;
|
||||
[18] = getop_less_than (3, 0, 4), // tmp3 = i < tmp7;
|
||||
[19] = getop_is_false_jmp (3, 27), // if (!tmp3) goto 27;
|
||||
[20] = getop_jmp_down (3), // goto 23;
|
||||
[21] = getop_post_incr (5, 0), // tmp5 = i ++;
|
||||
[22] = getop_jmp_up (5), // goto 17;
|
||||
[23] = getop_nop (), // ;
|
||||
[24] = getop_assignment (2, 1, 10),// tmp2 = 10;
|
||||
[25] = getop_assignment (1, 4, 5), // j = tmp2;
|
||||
[26] = getop_jmp_up (5), // goto 21;
|
||||
[27] = getop_exitval (0) // exit 0;
|
||||
[0] = getop_reg_var_decl (2, 5), // var tmp2 .. tmp5;
|
||||
[1] = getop_var_decl (0), // var i;
|
||||
[2] = getop_var_decl (1), // var j;
|
||||
[3] = getop_assignment (2, 1, 0), // tmp2 = 0;
|
||||
[4] = getop_assignment (0, 4, 2), // i = tmp2;
|
||||
[5] = getop_assignment (4, 1, 10),// tmp4 = 10;
|
||||
[6] = getop_less_than (3, 0, 4), // tmp3 = i < tmp4;
|
||||
[7] = getop_is_false_jmp (3, 14), // if (!tmp3) goto 14;
|
||||
[8] = getop_jmp_down (3), // goto 11;
|
||||
[9] = getop_post_incr (5, 0), // tmp5 = i ++;
|
||||
[10] = getop_jmp_up (5), // goto 5;
|
||||
[11] = getop_assignment (2, 1, 10),// tmp2 = 10;
|
||||
[12] = getop_assignment (1, 4, 2), // j = tmp2;
|
||||
[13] = getop_jmp_up (5), // goto 8;
|
||||
[14] = getop_nop (), // ;
|
||||
[15] = getop_assignment (2, 1, 0), // tmp2 = 0;
|
||||
[16] = getop_assignment (0, 4, 2), // i = tmp2;
|
||||
[17] = getop_assignment (4, 1, 10),// tmp7 = 10;
|
||||
[18] = getop_less_than (3, 0, 4), // tmp3 = i < tmp7;
|
||||
[19] = getop_is_false_jmp (3, 27), // if (!tmp3) goto 27;
|
||||
[20] = getop_jmp_down (3), // goto 23;
|
||||
[21] = getop_post_incr (5, 0), // tmp5 = i ++;
|
||||
[22] = getop_jmp_up (5), // goto 17;
|
||||
[23] = getop_nop (), // ;
|
||||
[24] = getop_assignment (2, 1, 10),// tmp2 = 10;
|
||||
[25] = getop_assignment (1, 4, 5), // j = tmp2;
|
||||
[26] = getop_jmp_up (5), // goto 21;
|
||||
[27] = getop_exitval (0) // exit 0;
|
||||
}, 28))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -16,7 +16,7 @@
|
||||
#include "globals.h"
|
||||
#include "interpreter.h"
|
||||
#include "mem-allocator.h"
|
||||
#include "opcodes.h"
|
||||
#include "opcodes-support.h"
|
||||
#include "serializer.h"
|
||||
#include "optimizer-passes.h"
|
||||
#include "jerry-libc.h"
|
||||
@ -35,12 +35,12 @@ main( int __unused argc,
|
||||
[0] = getop_reg_var_decl (5, 5), // tmp6
|
||||
[1] = getop_assignment (0, OPCODE_ARG_TYPE_STRING, 1), // a = "b"
|
||||
[2] = getop_var_decl (1), // var b
|
||||
[3] = getop_func_decl_0 (2), // function c()
|
||||
[3] = getop_func_decl_0 (2), // function c()
|
||||
[4] = getop_jmp_down (3), // {
|
||||
[5] = getop_var_decl (1), // var b
|
||||
[6] = getop_retval (1), // return b; }
|
||||
[7] = getop_assignment (5, OPCODE_ARG_TYPE_STRING, 3), // "use strict"
|
||||
[8] = getop_exitval (0)
|
||||
[8] = getop_exitval (0)
|
||||
};
|
||||
|
||||
mem_init();
|
||||
@ -60,16 +60,16 @@ main( int __unused argc,
|
||||
if (!opcodes_equal (opcodes, (OPCODE[]) {
|
||||
[0] = getop_reg_var_decl (5, 5), // tmp6
|
||||
[1] = getop_assignment (5, OPCODE_ARG_TYPE_STRING, 3), // "use strict"
|
||||
[2] = getop_func_decl_0 (2), // function c()
|
||||
[2] = getop_func_decl_0 (2), // function c()
|
||||
[3] = getop_jmp_down (3), // {
|
||||
[4] = getop_var_decl (1), // var b
|
||||
[5] = getop_retval (1), // return b; }
|
||||
[6] = getop_var_decl (1), // var b
|
||||
[7] = getop_assignment (0, OPCODE_ARG_TYPE_STRING, 1), // a = "b"
|
||||
[8] = getop_exitval (0)
|
||||
[8] = getop_exitval (0)
|
||||
}, 9))
|
||||
return 1;
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -16,7 +16,7 @@
|
||||
#include "globals.h"
|
||||
#include "interpreter.h"
|
||||
#include "mem-allocator.h"
|
||||
#include "opcodes.h"
|
||||
#include "opcodes-support.h"
|
||||
#include "serializer.h"
|
||||
|
||||
/**
|
||||
|
||||
@ -16,7 +16,7 @@
|
||||
#include "globals.h"
|
||||
#include "interpreter.h"
|
||||
#include "mem-allocator.h"
|
||||
#include "opcodes.h"
|
||||
#include "opcodes-support.h"
|
||||
#include "serializer.h"
|
||||
|
||||
/**
|
||||
|
||||
@ -16,7 +16,7 @@
|
||||
#include "globals.h"
|
||||
#include "interpreter.h"
|
||||
#include "mem-allocator.h"
|
||||
#include "opcodes.h"
|
||||
#include "opcodes-support.h"
|
||||
#include "serializer.h"
|
||||
|
||||
/**
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user