/** * Handle calling [[Construct]] of built-in Object object * * @return completion-value */ ecma_completion_value_t ecma_builtin_object_dispatch_construct (const ecma_value_t *arguments_list_p, /**< arguments list */ ecma_length_t arguments_list_len) /**< number of arguments */ { JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); if (arguments_list_len == 0) { ecma_object_t *obj_p = ecma_op_create_object_object_noarg (); return ecma_make_normal_completion_value (ecma_make_object_value (obj_p)); } else { ecma_completion_value_t new_obj_value = ecma_op_create_object_object_arg (arguments_list_p[0]); if (!ecma_is_completion_value_normal (new_obj_value)) { return new_obj_value; } else { return ecma_make_normal_completion_value (ecma_get_completion_value_value (new_obj_value)); } } } /* ecma_builtin_object_dispatch_construct */
/** * Number object creation operation. * * See also: ECMA-262 v5, 15.7.2.1 * * @return completion value * Returned value must be freed with ecma_free_completion_value */ ecma_completion_value_t ecma_op_create_number_object (ecma_value_t arg) /**< argument passed to the Number constructor */ { ecma_completion_value_t conv_to_num_completion = ecma_op_to_number (arg); if (!ecma_is_completion_value_normal (conv_to_num_completion)) { return conv_to_num_completion; } ecma_number_t *prim_value_p = ecma_get_number_from_completion_value (conv_to_num_completion); #ifndef CONFIG_ECMA_COMPACT_PROFILE_DISABLE_NUMBER_BUILTIN ecma_object_t *prototype_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_NUMBER_PROTOTYPE); #else /* !CONFIG_ECMA_COMPACT_PROFILE_DISABLE_NUMBER_BUILTIN */ ecma_object_t *prototype_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_OBJECT_PROTOTYPE); #endif /* CONFIG_ECMA_COMPACT_PROFILE_DISABLE_NUMBER_BUILTIN */ ecma_object_t *obj_p = ecma_create_object (prototype_obj_p, true, ECMA_OBJECT_TYPE_GENERAL); ecma_deref_object (prototype_obj_p); ecma_property_t *class_prop_p = ecma_create_internal_property (obj_p, ECMA_INTERNAL_PROPERTY_CLASS); class_prop_p->u.internal_property.value = LIT_MAGIC_STRING_NUMBER_UL; ecma_property_t *prim_value_prop_p = ecma_create_internal_property (obj_p, ECMA_INTERNAL_PROPERTY_PRIMITIVE_NUMBER_VALUE); ECMA_SET_POINTER (prim_value_prop_p->u.internal_property.value, prim_value_p); return ecma_make_normal_completion_value (ecma_make_object_value (obj_p)); } /* ecma_op_create_number_object */
/** * Run the code, starting from specified opcode */ ecma_completion_value_t vm_run_from_pos (opcode_counter_t start_pos, /**< identifier of starting opcode */ ecma_value_t this_binding_value, /**< value of 'ThisBinding' */ ecma_object_t *lex_env_p, /**< lexical environment to use */ bool is_strict, /**< is the code is strict mode code (ECMA-262 v5, 10.1.1) */ bool is_eval_code) /**< is the code is eval code (ECMA-262 v5, 10.1) */ { ecma_completion_value_t completion; const opcode_t *curr = &__program[start_pos]; JERRY_ASSERT (curr->op_idx == __op__idx_reg_var_decl); const idx_t min_reg_num = curr->data.reg_var_decl.min; const idx_t max_reg_num = curr->data.reg_var_decl.max; JERRY_ASSERT (max_reg_num >= min_reg_num); const int32_t regs_num = max_reg_num - min_reg_num + 1; MEM_DEFINE_LOCAL_ARRAY (regs, regs_num, ecma_value_t); int_data_t int_data; int_data.pos = (opcode_counter_t) (start_pos + 1); int_data.this_binding = this_binding_value; int_data.lex_env_p = lex_env_p; int_data.is_strict = is_strict; int_data.is_eval_code = is_eval_code; int_data.min_reg_num = min_reg_num; int_data.max_reg_num = max_reg_num; int_data.tmp_num_p = ecma_alloc_number (); ecma_stack_add_frame (&int_data.stack_frame, regs, regs_num); int_data_t *prev_context_p = vm_top_context_p; vm_top_context_p = &int_data; #ifdef MEM_STATS interp_mem_stats_context_enter (&int_data, start_pos); #endif /* MEM_STATS */ completion = vm_loop (&int_data, NULL); JERRY_ASSERT (ecma_is_completion_value_normal (completion) || ecma_is_completion_value_throw (completion) || ecma_is_completion_value_return (completion) || ecma_is_completion_value_exit (completion)); vm_top_context_p = prev_context_p; ecma_stack_free_frame (&int_data.stack_frame); ecma_dealloc_number (int_data.tmp_num_p); #ifdef MEM_STATS interp_mem_stats_context_exit (&int_data, start_pos); #endif /* MEM_STATS */ MEM_FINALIZE_LOCAL_ARRAY (regs); return completion; } /* vm_run_from_pos */
/** * Fill arguments' list * * @return empty completion value if argument list was filled successfully, * otherwise - not normal completion value indicating completion type * of last expression evaluated */ ecma_completion_value_t fill_varg_list (vm_frame_ctx_t *frame_ctx_p, /**< interpreter context */ ecma_length_t args_number, /**< number of arguments */ ecma_value_t arg_values[], /**< out: arguments' values */ ecma_length_t *out_arg_number_p) /**< out: number of arguments successfully read */ { ecma_completion_value_t ret_value = ecma_make_empty_completion_value (); ecma_length_t arg_index; for (arg_index = 0; arg_index < args_number && ecma_is_completion_value_empty (ret_value); ) { ecma_completion_value_t evaluate_arg_completion = vm_loop (frame_ctx_p, NULL); if (ecma_is_completion_value_empty (evaluate_arg_completion)) { vm_instr_t next_instr = vm_get_instr (frame_ctx_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 idx_t varg_var_idx = next_instr.data.meta.data_1; ecma_completion_value_t get_arg_completion = get_variable_value (frame_ctx_p, varg_var_idx, false); if (ecma_is_completion_value_normal (get_arg_completion)) { arg_values[arg_index++] = ecma_get_completion_value_value (get_arg_completion); } else { JERRY_ASSERT (ecma_is_completion_value_throw (get_arg_completion)); ret_value = get_arg_completion; } } else { JERRY_ASSERT (ecma_is_completion_value_throw (evaluate_arg_completion)); ret_value = evaluate_arg_completion; } frame_ctx_p->pos++; } *out_arg_number_p = arg_index; return ret_value; } /* fill_varg_list */
/** * [[DefineOwnProperty]] ecma array object's operation * * See also: * ECMA-262 v5, 8.6.2; ECMA-262 v5, Table 8 * ECMA-262 v5, 15.4.5.1 * * @return completion value * Returned value must be freed with ecma_free_completion_value */ ecma_completion_value_t ecma_op_array_object_define_own_property (ecma_object_t *obj_p, /**< the array object */ ecma_string_t *property_name_p, /**< property name */ const ecma_property_descriptor_t *property_desc_p, /**< property descriptor */ bool is_throw) /**< flag that controls failure handling */ { JERRY_ASSERT (ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_ARRAY); // 1. ecma_string_t *magic_string_length_p = ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH); ecma_property_t *len_prop_p = ecma_op_object_get_own_property (obj_p, magic_string_length_p); JERRY_ASSERT (len_prop_p != NULL && len_prop_p->type == ECMA_PROPERTY_NAMEDDATA); // 2. ecma_value_t old_len_value = ecma_get_named_data_property_value (len_prop_p); ecma_number_t *num_p = ecma_get_number_from_value (old_len_value); uint32_t old_len_uint32 = ecma_number_to_uint32 (*num_p); // 3. bool is_property_name_equal_length = ecma_compare_ecma_strings (property_name_p, magic_string_length_p); ecma_deref_ecma_string (magic_string_length_p); if (is_property_name_equal_length) { // a. if (!property_desc_p->is_value_defined) { // i. return ecma_op_general_object_define_own_property (obj_p, property_name_p, property_desc_p, is_throw); } ecma_number_t new_len_num; // c. ecma_completion_value_t completion = ecma_op_to_number (property_desc_p->value); if (ecma_is_completion_value_throw (completion)) { return completion; } JERRY_ASSERT (ecma_is_completion_value_normal (completion) && ecma_is_value_number (ecma_get_completion_value_value (completion))); new_len_num = *ecma_get_number_from_completion_value (completion); ecma_free_completion_value (completion); uint32_t new_len_uint32 = ecma_number_to_uint32 (new_len_num); // d. if (ecma_uint32_to_number (new_len_uint32) != new_len_num) { return ecma_make_throw_obj_completion_value (ecma_new_standard_error (ECMA_ERROR_RANGE)); } else { // b., e. ecma_number_t *new_len_num_p = ecma_alloc_number (); *new_len_num_p = new_len_num; ecma_property_descriptor_t new_len_property_desc = *property_desc_p; new_len_property_desc.value = ecma_make_number_value (new_len_num_p); ecma_completion_value_t ret_value = ecma_make_empty_completion_value (); // f. if (new_len_uint32 >= old_len_uint32) { // i. magic_string_length_p = ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH); ret_value = ecma_op_general_object_define_own_property (obj_p, magic_string_length_p, &new_len_property_desc, is_throw); ecma_deref_ecma_string (magic_string_length_p); } else { // g. if (!ecma_is_property_writable (len_prop_p)) { ret_value = ecma_reject (is_throw); } else { // h. bool new_writable; if (!new_len_property_desc.is_writable_defined || new_len_property_desc.is_writable) { new_writable = true; } else { // ii. new_writable = false; // iii. new_len_property_desc.is_writable_defined = true; new_len_property_desc.is_writable = true; } // j. magic_string_length_p = ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH); ecma_completion_value_t succeeded = ecma_op_general_object_define_own_property (obj_p, magic_string_length_p, &new_len_property_desc, is_throw); ecma_deref_ecma_string (magic_string_length_p); /* Handling normal false and throw values */ if (!ecma_is_completion_value_normal_true (succeeded)) { JERRY_ASSERT (ecma_is_completion_value_normal_false (succeeded) || ecma_is_completion_value_throw (succeeded)); // k. ret_value = succeeded; } else { // l JERRY_ASSERT (new_len_uint32 < old_len_uint32); /* * Item i. is replaced with faster iteration: only indices that actually exist in the array, are iterated */ bool is_reduce_succeeded = true; ecma_collection_header_t *array_index_props_p = ecma_op_object_get_property_names (obj_p, true, false, false); ecma_length_t array_index_props_num = array_index_props_p->unit_number; MEM_DEFINE_LOCAL_ARRAY (array_index_values_p, array_index_props_num, uint32_t); ecma_collection_iterator_t iter; ecma_collection_iterator_init (&iter, array_index_props_p); uint32_t array_index_values_pos = 0; while (ecma_collection_iterator_next (&iter)) { ecma_string_t *property_name_p = ecma_get_string_from_value (*iter.current_value_p); uint32_t index; bool is_index = ecma_string_get_array_index (property_name_p, &index); JERRY_ASSERT (is_index); JERRY_ASSERT (index < old_len_uint32); array_index_values_p[array_index_values_pos++] = index; } JERRY_ASSERT (array_index_values_pos == array_index_props_num); while (array_index_values_pos != 0 && array_index_values_p[--array_index_values_pos] >= new_len_uint32) { uint32_t index = array_index_values_p[array_index_values_pos]; // ii. ecma_string_t *index_string_p = ecma_new_ecma_string_from_uint32 (index); ecma_completion_value_t delete_succeeded = ecma_op_object_delete (obj_p, index_string_p, false); ecma_deref_ecma_string (index_string_p); if (ecma_is_completion_value_normal_false (delete_succeeded)) { // iii. new_len_uint32 = (index + 1u); ecma_number_t *new_len_num_p = ecma_get_number_from_value (new_len_property_desc.value); // 1. *new_len_num_p = ecma_uint32_to_number (index + 1u); // 2. if (!new_writable) { new_len_property_desc.is_writable_defined = true; new_len_property_desc.is_writable = false; } // 3. ecma_string_t *magic_string_length_p = ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH); ecma_completion_value_t completion = ecma_op_general_object_define_own_property (obj_p, magic_string_length_p, &new_len_property_desc, false); ecma_deref_ecma_string (magic_string_length_p); JERRY_ASSERT (ecma_is_completion_value_normal_true (completion) || ecma_is_completion_value_normal_false (completion)); is_reduce_succeeded = false; break; } } MEM_FINALIZE_LOCAL_ARRAY (array_index_values_p); ecma_free_values_collection (array_index_props_p, true); if (!is_reduce_succeeded) { ret_value = ecma_reject (is_throw); } else { // m. if (!new_writable) { ecma_property_descriptor_t prop_desc_not_writable = ecma_make_empty_property_descriptor (); prop_desc_not_writable.is_writable_defined = true; prop_desc_not_writable.is_writable = false; ecma_completion_value_t completion_set_not_writable; magic_string_length_p = ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH); completion_set_not_writable = ecma_op_general_object_define_own_property (obj_p, magic_string_length_p, &prop_desc_not_writable, false); ecma_deref_ecma_string (magic_string_length_p); JERRY_ASSERT (ecma_is_completion_value_normal_true (completion_set_not_writable)); } ret_value = ecma_make_simple_completion_value (ECMA_SIMPLE_VALUE_TRUE); } } } } ecma_dealloc_number (new_len_num_p); return ret_value; } JERRY_UNREACHABLE (); } else { // 4.a. uint32_t index; if (!ecma_string_get_array_index (property_name_p, &index)) { // 5. return ecma_op_general_object_define_own_property (obj_p, property_name_p, property_desc_p, is_throw); } // 4. // b. if (index >= old_len_uint32 && !ecma_is_property_writable (len_prop_p)) { return ecma_reject (is_throw); } // c. ecma_completion_value_t succeeded = ecma_op_general_object_define_own_property (obj_p, property_name_p, property_desc_p, false); // d. JERRY_ASSERT (ecma_is_completion_value_normal_true (succeeded) || ecma_is_completion_value_normal_false (succeeded)); if (ecma_is_completion_value_normal_false (succeeded)) { return ecma_reject (is_throw); } // e. if (index >= old_len_uint32) { // i., ii. ecma_number_t *num_p = ecma_alloc_number (); *num_p = ecma_number_add (ecma_uint32_to_number (index), ECMA_NUMBER_ONE); ecma_named_data_property_assign_value (obj_p, len_prop_p, ecma_make_number_value (num_p)); ecma_dealloc_number (num_p); } // f. return ecma_make_simple_completion_value (ECMA_SIMPLE_VALUE_TRUE); } JERRY_UNREACHABLE (); } /* ecma_op_array_object_define_own_property */
ecma_completion_value_t ecma_builtin_helper_object_to_string (const ecma_value_t this_arg) /**< this argument */ { lit_magic_string_id_t type_string; if (ecma_is_value_undefined (this_arg)) { type_string = LIT_MAGIC_STRING_UNDEFINED_UL; } else if (ecma_is_value_null (this_arg)) { type_string = LIT_MAGIC_STRING_NULL_UL; } else { ecma_completion_value_t obj_this = ecma_op_to_object (this_arg); if (!ecma_is_completion_value_normal (obj_this)) { return obj_this; } JERRY_ASSERT (ecma_is_value_object (ecma_get_completion_value_value (obj_this))); ecma_object_t *obj_p = ecma_get_object_from_completion_value (obj_this); type_string = ecma_object_get_class_name (obj_p); ecma_free_completion_value (obj_this); } ecma_string_t *ret_string_p; /* Building string "[object #type#]" where type is 'Undefined', 'Null' or one of possible object's classes. The string with null character is maximum 19 characters long. */ const ssize_t buffer_size = 19; MEM_DEFINE_LOCAL_ARRAY (str_buffer, buffer_size, lit_utf8_byte_t); lit_utf8_byte_t *buffer_ptr = str_buffer; ssize_t buffer_size_left = buffer_size; const lit_magic_string_id_t magic_string_ids[] = { LIT_MAGIC_STRING_LEFT_SQUARE_CHAR, LIT_MAGIC_STRING_OBJECT, LIT_MAGIC_STRING_SPACE_CHAR, type_string, LIT_MAGIC_STRING_RIGHT_SQUARE_CHAR }; for (uint32_t i = 0; i < sizeof (magic_string_ids) / sizeof (lit_magic_string_id_t); ++i) { buffer_ptr = lit_copy_magic_string_to_buffer (magic_string_ids[i], buffer_ptr, buffer_size_left); buffer_size_left = buffer_size - (buffer_ptr - str_buffer); } JERRY_ASSERT (buffer_size_left >= 0); ret_string_p = ecma_new_ecma_string_from_utf8 (str_buffer, (lit_utf8_size_t) (buffer_size - buffer_size_left)); MEM_FINALIZE_LOCAL_ARRAY (str_buffer); return ecma_make_normal_completion_value (ecma_make_string_value (ret_string_p)); } /* ecma_builtin_helper_object_to_string */
/** * The Object.keys and Object.getOwnPropertyName routine's common part. * * See also: * ECMA-262 v5, 15.2.3.4 steps 2-5 * ECMA-262 v5, 15.2.3.14 steps 3-6 * * @return completion value - Array of property names. * Returned value must be freed with ecma_free_completion_value. */ ecma_completion_value_t ecma_builtin_helper_object_get_properties (ecma_object_t *obj_p, /** < object */ bool only_enumerable_properties) /** < list enumerable properties? */ { JERRY_ASSERT (obj_p != NULL); ecma_completion_value_t new_array = ecma_op_create_array_object (NULL, 0, false); JERRY_ASSERT (ecma_is_completion_value_normal (new_array)); ecma_object_t *new_array_p = ecma_get_object_from_completion_value (new_array); uint32_t index = 0; for (ecma_property_t *property_p = ecma_get_property_list (obj_p); property_p != NULL; property_p = ECMA_GET_POINTER (ecma_property_t, property_p->next_property_p)) { ecma_string_t *property_name_p; if (property_p->type == ECMA_PROPERTY_NAMEDDATA) { property_name_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t, property_p->u.named_data_property.name_p); } else if (property_p->type == ECMA_PROPERTY_NAMEDACCESSOR) { property_name_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t, property_p->u.named_accessor_property.name_p); } else { continue; } if (only_enumerable_properties && !ecma_is_property_enumerable (property_p)) { continue; } JERRY_ASSERT (property_name_p != NULL); ecma_string_t *index_string_p = ecma_new_ecma_string_from_uint32 (index); ecma_property_descriptor_t item_prop_desc = ecma_make_empty_property_descriptor (); { item_prop_desc.is_value_defined = true; item_prop_desc.value = ecma_make_string_value (property_name_p); item_prop_desc.is_writable_defined = true; item_prop_desc.is_writable = true; item_prop_desc.is_enumerable_defined = true; item_prop_desc.is_enumerable = true; item_prop_desc.is_configurable_defined = true; item_prop_desc.is_configurable = true; } ecma_completion_value_t completion = ecma_op_object_define_own_property (new_array_p, index_string_p, &item_prop_desc, false); JERRY_ASSERT (ecma_is_completion_value_normal_true (completion)); ecma_free_completion_value (completion); ecma_deref_ecma_string (index_string_p); index++; } return new_array; } /* ecma_builtin_helper_object_get_properties */
/** * 'Native call' opcode handler. */ ecma_completion_value_t opfunc_native_call (opcode_t opdata, /**< operation data */ int_data_t *int_data) /**< interpreter context */ { const idx_t dst_var_idx = opdata.data.native_call.lhs; const idx_t native_call_id_idx = opdata.data.native_call.name; const idx_t args_number = opdata.data.native_call.arg_list; const opcode_counter_t lit_oc = int_data->pos; JERRY_ASSERT (native_call_id_idx < OPCODE_NATIVE_CALL__COUNT); int_data->pos++; JERRY_STATIC_ASSERT (OPCODE_NATIVE_CALL__COUNT < (1u << (sizeof (native_call_id_idx) * JERRY_BITSINBYTE))); ecma_completion_value_t ret_value = ecma_make_empty_completion_value (); MEM_DEFINE_LOCAL_ARRAY (arg_values, args_number, ecma_value_t); ecma_length_t args_read; ecma_completion_value_t get_arg_completion = fill_varg_list (int_data, args_number, arg_values, &args_read); if (ecma_is_completion_value_empty (get_arg_completion)) { JERRY_ASSERT (args_read == args_number); switch ((opcode_native_call_t)native_call_id_idx) { case OPCODE_NATIVE_CALL_LED_TOGGLE: case OPCODE_NATIVE_CALL_LED_ON: case OPCODE_NATIVE_CALL_LED_OFF: case OPCODE_NATIVE_CALL_LED_ONCE: case OPCODE_NATIVE_CALL_WAIT: { JERRY_UNIMPLEMENTED ("Device operations are not implemented."); } case OPCODE_NATIVE_CALL_PRINT: { for (ecma_length_t arg_index = 0; ecma_is_completion_value_empty (ret_value) && arg_index < args_read; arg_index++) { ECMA_TRY_CATCH (str_value, ecma_op_to_string (arg_values[arg_index]), ret_value); ecma_string_t *str_p = ecma_get_string_from_value (str_value); lit_utf8_size_t bytes = ecma_string_get_size (str_p); ssize_t utf8_str_size = (ssize_t) (bytes + 1); lit_utf8_byte_t *utf8_str_p = (lit_utf8_byte_t*) mem_heap_alloc_block ((size_t) utf8_str_size, MEM_HEAP_ALLOC_SHORT_TERM); if (utf8_str_p == NULL) { jerry_fatal (ERR_OUT_OF_MEMORY); } ecma_string_to_utf8_string (str_p, utf8_str_p, utf8_str_size); utf8_str_p[utf8_str_size - 1] = 0; FIXME ("Support unicode in printf."); if (arg_index < args_read - 1) { printf ("%s ", (char*) utf8_str_p); } else { printf ("%s", (char*) utf8_str_p); } mem_heap_free_block (utf8_str_p); ret_value = set_variable_value (int_data, lit_oc, dst_var_idx, ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED)); ECMA_FINALIZE (str_value); } printf ("\n"); break; } case OPCODE_NATIVE_CALL__COUNT: { JERRY_UNREACHABLE (); } } } else { JERRY_ASSERT (!ecma_is_completion_value_normal (get_arg_completion)); ret_value = get_arg_completion; } for (ecma_length_t arg_index = 0; arg_index < args_read; arg_index++) { ecma_free_value (arg_values[arg_index], true); } MEM_FINALIZE_LOCAL_ARRAY (arg_values); return ret_value; } /* opfunc_native_call */
/** * Run interpreter loop using specified context * * Note: * The interpreter loop stops upon receiving completion value that is normal completion value. * * @return If the received completion value is not meta completion value (ECMA_COMPLETION_TYPE_META), then * the completion value is returned as is; * Otherwise - the completion value is discarded and normal empty completion value is returned. */ ecma_completion_value_t vm_loop (vm_frame_ctx_t *frame_ctx_p, /**< interpreter context */ vm_run_scope_t *run_scope_p) /**< current run scope, * or NULL - if there is no active run scope */ { ecma_completion_value_t completion; #ifdef MEM_STATS mem_heap_stats_t heap_stats_before; mem_pools_stats_t pools_stats_before; memset (&heap_stats_before, 0, sizeof (heap_stats_before)); memset (&pools_stats_before, 0, sizeof (pools_stats_before)); #endif /* MEM_STATS */ while (true) { do { JERRY_ASSERT (run_scope_p == NULL || (run_scope_p->start_oc <= frame_ctx_p->pos && frame_ctx_p->pos <= run_scope_p->end_oc)); const vm_instr_t *curr = &frame_ctx_p->instrs_p[frame_ctx_p->pos]; #ifdef MEM_STATS const vm_instr_counter_t instr_pos = frame_ctx_p->pos; interp_mem_stats_opcode_enter (frame_ctx_p->instrs_p, instr_pos, &heap_stats_before, &pools_stats_before); #endif /* MEM_STATS */ completion = __opfuncs[curr->op_idx] (*curr, frame_ctx_p); #ifdef CONFIG_VM_RUN_GC_AFTER_EACH_OPCODE ecma_gc_run (); #endif /* CONFIG_VM_RUN_GC_AFTER_EACH_OPCODE */ #ifdef MEM_STATS interp_mem_stats_opcode_exit (frame_ctx_p, instr_pos, &heap_stats_before, &pools_stats_before); #endif /* MEM_STATS */ JERRY_ASSERT (!ecma_is_completion_value_normal (completion) || ecma_is_completion_value_empty (completion)); } while (ecma_is_completion_value_normal (completion)); if (ecma_is_completion_value_jump (completion)) { vm_instr_counter_t target = ecma_get_jump_target_from_completion_value (completion); /* * TODO: * Implement instantiation of run scopes for global scope, functions and eval scope. * Currently, correctness of jumps without run scope set is guaranteed through byte-code semantics. */ if (run_scope_p == NULL /* if no run scope set */ || (target >= run_scope_p->start_oc /* or target is within the current run scope */ && target <= run_scope_p->end_oc)) { frame_ctx_p->pos = target; continue; } } if (ecma_is_completion_value_meta (completion)) { completion = ecma_make_empty_completion_value (); } return completion; } } /* vm_loop */
/** * [[DefaultValue]] ecma general object's operation * * See also: * ECMA-262 v5, 8.6.2; ECMA-262 v5, Table 8 * ECMA-262 v5, 8.12.8 * * @return completion value * Returned value must be freed with ecma_free_completion_value */ ecma_completion_value_t ecma_op_general_object_default_value (ecma_object_t *obj_p, /**< the object */ ecma_preferred_type_hint_t hint) /**< hint on preferred result type */ { JERRY_ASSERT (obj_p != NULL && !ecma_is_lexical_environment (obj_p)); if (hint == ECMA_PREFERRED_TYPE_NO) { if (ecma_object_get_class_name (obj_p) == LIT_MAGIC_STRING_DATE_UL) { hint = ECMA_PREFERRED_TYPE_STRING; } else { hint = ECMA_PREFERRED_TYPE_NUMBER; } } for (uint32_t i = 1; i <= 2; i++) { lit_magic_string_id_t function_name_magic_string_id; if ((i == 1 && hint == ECMA_PREFERRED_TYPE_STRING) || (i == 2 && hint == ECMA_PREFERRED_TYPE_NUMBER)) { function_name_magic_string_id = LIT_MAGIC_STRING_TO_STRING_UL; } else { function_name_magic_string_id = LIT_MAGIC_STRING_VALUE_OF_UL; } ecma_string_t *function_name_p = ecma_get_magic_string (function_name_magic_string_id); ecma_completion_value_t function_value_get_completion = ecma_op_object_get (obj_p, function_name_p); ecma_deref_ecma_string (function_name_p); if (!ecma_is_completion_value_normal (function_value_get_completion)) { return function_value_get_completion; } ecma_completion_value_t call_completion = ecma_make_empty_completion_value (); if (ecma_op_is_callable (ecma_get_completion_value_value (function_value_get_completion))) { ecma_object_t *func_obj_p = ecma_get_object_from_completion_value (function_value_get_completion); call_completion = ecma_op_function_call (func_obj_p, ecma_make_object_value (obj_p), NULL); } ecma_free_completion_value (function_value_get_completion); if (!ecma_is_completion_value_normal (call_completion)) { return call_completion; } if (!ecma_is_completion_value_empty (call_completion) && !ecma_is_value_object (ecma_get_completion_value_value (call_completion))) { return call_completion; } ecma_free_completion_value (call_completion); } return ecma_make_throw_obj_completion_value (ecma_new_standard_error (ECMA_ERROR_TYPE)); } /* ecma_op_general_object_default_value */
/** * [[DefineOwnProperty]] ecma array object's operation * * See also: * ECMA-262 v5, 8.6.2; ECMA-262 v5, Table 8 * ECMA-262 v5, 15.4.5.1 * * @return completion value * Returned value must be freed with ecma_free_completion_value */ ecma_completion_value_t ecma_op_array_object_define_own_property (ecma_object_t *obj_p, /**< the array object */ ecma_string_t *property_name_p, /**< property name */ const ecma_property_descriptor_t* property_desc_p, /**< property descriptor */ bool is_throw) /**< flag that controls failure handling */ { JERRY_ASSERT (ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_ARRAY); // 1. ecma_string_t* magic_string_length_p = ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH); ecma_property_t *len_prop_p = ecma_op_object_get_own_property (obj_p, magic_string_length_p); JERRY_ASSERT (len_prop_p != NULL && len_prop_p->type == ECMA_PROPERTY_NAMEDDATA); // 2. ecma_value_t old_len_value = ecma_get_named_data_property_value (len_prop_p); ecma_number_t *num_p = ecma_get_number_from_value (old_len_value); uint32_t old_len_uint32 = ecma_number_to_uint32 (*num_p); // 3. bool is_property_name_equal_length = ecma_compare_ecma_strings (property_name_p, magic_string_length_p); ecma_deref_ecma_string (magic_string_length_p); if (is_property_name_equal_length) { // a. if (!property_desc_p->is_value_defined) { // i. return ecma_op_general_object_define_own_property (obj_p, property_name_p, property_desc_p, is_throw); } ecma_number_t new_len_num; // c. ecma_completion_value_t completion = ecma_op_to_number (property_desc_p->value); if (ecma_is_completion_value_throw (completion)) { return completion; } JERRY_ASSERT (ecma_is_completion_value_normal (completion) && ecma_is_value_number (ecma_get_completion_value_value (completion))); new_len_num = *ecma_get_number_from_completion_value (completion); ecma_free_completion_value (completion); uint32_t new_len_uint32 = ecma_number_to_uint32 (new_len_num); // d. if (ecma_uint32_to_number (new_len_uint32) != new_len_num) { return ecma_make_throw_obj_completion_value (ecma_new_standard_error (ECMA_ERROR_RANGE)); } else { // b., e. ecma_number_t *new_len_num_p = ecma_alloc_number (); *new_len_num_p = new_len_num; ecma_property_descriptor_t new_len_property_desc = *property_desc_p; new_len_property_desc.value = ecma_make_number_value (new_len_num_p); ecma_completion_value_t ret_value = ecma_make_empty_completion_value (); // f. if (new_len_uint32 >= old_len_uint32) { // i. magic_string_length_p = ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH); ret_value = ecma_op_general_object_define_own_property (obj_p, magic_string_length_p, &new_len_property_desc, is_throw); ecma_deref_ecma_string (magic_string_length_p); } else { // g. if (!ecma_is_property_writable (len_prop_p)) { ret_value = ecma_reject (is_throw); } else { // h. bool new_writable; if (!new_len_property_desc.is_writable_defined || new_len_property_desc.is_writable) { new_writable = true; } else { // ii. new_writable = false; // iii. new_len_property_desc.is_writable_defined = true; new_len_property_desc.is_writable = true; } // j. magic_string_length_p = ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH); ecma_completion_value_t succeeded = ecma_op_general_object_define_own_property (obj_p, magic_string_length_p, &new_len_property_desc, is_throw); ecma_deref_ecma_string (magic_string_length_p); /* Handling normal false and throw values */ if (!ecma_is_completion_value_normal_true (succeeded)) { JERRY_ASSERT (ecma_is_completion_value_normal_false (succeeded) || ecma_is_completion_value_throw (succeeded)); // k. ret_value = succeeded; } else { // l JERRY_ASSERT (new_len_uint32 < old_len_uint32); bool reduce_succeeded = true; while (new_len_uint32 < old_len_uint32) { // i old_len_uint32--; // ii ecma_string_t *old_length_string_p = ecma_new_ecma_string_from_uint32 (old_len_uint32); ecma_completion_value_t delete_succeeded = ecma_op_object_delete (obj_p, old_length_string_p, false); ecma_deref_ecma_string (old_length_string_p); // iii if (ecma_is_completion_value_normal_false (delete_succeeded)) { JERRY_ASSERT (ecma_is_value_number (new_len_property_desc.value)); ecma_number_t *new_len_num_p = ecma_get_number_from_value (new_len_property_desc.value); // 1. *new_len_num_p = ecma_uint32_to_number (old_len_uint32 + 1); // 2. if (!new_writable) { new_len_property_desc.is_writable_defined = true; new_len_property_desc.is_writable = false; } // 3. ecma_string_t *magic_string_length_p = ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH); ecma_completion_value_t completion = ecma_op_general_object_define_own_property (obj_p, magic_string_length_p, &new_len_property_desc, false); ecma_deref_ecma_string (magic_string_length_p); JERRY_ASSERT (ecma_is_completion_value_normal_true (completion) || ecma_is_completion_value_normal_false (completion)); reduce_succeeded = false; break; } } if (!reduce_succeeded) { ret_value = ecma_reject (is_throw); } else { // m. if (!new_writable) { ecma_property_descriptor_t prop_desc_not_writable = ecma_make_empty_property_descriptor (); prop_desc_not_writable.is_writable_defined = true; prop_desc_not_writable.is_writable = false; ecma_completion_value_t completion_set_not_writable; magic_string_length_p = ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH); completion_set_not_writable = ecma_op_general_object_define_own_property (obj_p, magic_string_length_p, &prop_desc_not_writable, false); ecma_deref_ecma_string (magic_string_length_p); JERRY_ASSERT (ecma_is_completion_value_normal_true (completion_set_not_writable)); } ret_value = ecma_make_simple_completion_value (ECMA_SIMPLE_VALUE_TRUE); } } } } ecma_dealloc_number (new_len_num_p); return ret_value; } JERRY_UNREACHABLE (); } else { // 4.a. uint32_t index; if (!ecma_string_get_array_index (property_name_p, &index)) { // 5. return ecma_op_general_object_define_own_property (obj_p, property_name_p, property_desc_p, is_throw); } // 4. // b. if (index >= old_len_uint32 && !ecma_is_property_writable (len_prop_p)) { return ecma_reject (is_throw); } // c. ecma_completion_value_t succeeded = ecma_op_general_object_define_own_property (obj_p, property_name_p, property_desc_p, false); // d. JERRY_ASSERT (ecma_is_completion_value_normal_true (succeeded) || ecma_is_completion_value_normal_false (succeeded)); if (ecma_is_completion_value_normal_false (succeeded)) { return ecma_reject (is_throw); } // e. if (index >= old_len_uint32) { // i., ii. ecma_number_t *num_p = ecma_alloc_number (); *num_p = ecma_number_add (ecma_uint32_to_number (index), ECMA_NUMBER_ONE); ecma_named_data_property_assign_value (obj_p, len_prop_p, ecma_make_number_value (num_p)); ecma_dealloc_number (num_p); } // f. return ecma_make_simple_completion_value (ECMA_SIMPLE_VALUE_TRUE); } JERRY_UNREACHABLE (); } /* ecma_op_array_object_define_own_property */
/** * The Error.prototype object's 'toString' routine * * See also: * ECMA-262 v5, 15.11.4.4 * * @return completion value * Returned value must be freed with ecma_free_completion_value. */ static ecma_completion_value_t ecma_builtin_error_prototype_object_to_string (ecma_value_t this_arg) /**< this argument */ { ecma_completion_value_t ret_value = ecma_make_empty_completion_value (); // 2. if (!ecma_is_value_object (this_arg)) { ret_value = ecma_make_throw_obj_completion_value (ecma_new_standard_error (ECMA_ERROR_TYPE)); } else { ecma_object_t *obj_p = ecma_get_object_from_value (this_arg); ecma_string_t *name_magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_NAME); ECMA_TRY_CATCH (name_get_ret_value, ecma_op_object_get (obj_p, name_magic_string_p), ret_value); ecma_completion_value_t name_to_str_completion; if (ecma_is_value_undefined (name_get_ret_value)) { ecma_string_t *error_magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_ERROR_UL); name_to_str_completion = ecma_make_normal_completion_value (ecma_make_string_value (error_magic_string_p)); } else { name_to_str_completion = ecma_op_to_string (name_get_ret_value); } if (unlikely (!ecma_is_completion_value_normal (name_to_str_completion))) { ret_value = ecma_copy_completion_value (name_to_str_completion); } else { ecma_string_t *message_magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_MESSAGE); ECMA_TRY_CATCH (msg_get_ret_value, ecma_op_object_get (obj_p, message_magic_string_p), ret_value); ecma_completion_value_t msg_to_str_completion; if (ecma_is_value_undefined (msg_get_ret_value)) { ecma_string_t *empty_magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING__EMPTY); msg_to_str_completion = ecma_make_normal_completion_value (ecma_make_string_value (empty_magic_string_p)); } else { msg_to_str_completion = ecma_op_to_string (msg_get_ret_value); } if (unlikely (!ecma_is_completion_value_normal (msg_to_str_completion))) { ret_value = ecma_copy_completion_value (msg_to_str_completion); } else { ecma_string_t *name_string_p = ecma_get_string_from_completion_value (name_to_str_completion); ecma_string_t *msg_string_p = ecma_get_string_from_completion_value (msg_to_str_completion); ecma_string_t *ret_str_p; if (ecma_string_get_length (name_string_p) == 0) { ret_str_p = ecma_copy_or_ref_ecma_string (msg_string_p); } else if (ecma_string_get_length (msg_string_p) == 0) { ret_str_p = ecma_copy_or_ref_ecma_string (name_string_p); } else { const lit_utf8_size_t size = (ecma_string_get_size (name_string_p) + ecma_string_get_size (msg_string_p) + lit_get_magic_string_size (LIT_MAGIC_STRING_COLON_CHAR) + lit_get_magic_string_size (LIT_MAGIC_STRING_SPACE_CHAR)); const ssize_t buffer_size = (ssize_t) size; ssize_t buffer_size_left = buffer_size; MEM_DEFINE_LOCAL_ARRAY (ret_str_buffer, buffer_size, lit_utf8_byte_t); lit_utf8_byte_t *ret_str_buffer_p = ret_str_buffer; ssize_t bytes = ecma_string_to_utf8_string (name_string_p, ret_str_buffer_p, buffer_size_left); JERRY_ASSERT (bytes >= 0 && buffer_size_left - bytes >= 0); buffer_size_left -= bytes; ret_str_buffer_p = ret_str_buffer + buffer_size - buffer_size_left; ret_str_buffer_p = lit_copy_magic_string_to_buffer (LIT_MAGIC_STRING_COLON_CHAR, ret_str_buffer_p, buffer_size_left); buffer_size_left = buffer_size - (ret_str_buffer_p - ret_str_buffer); JERRY_ASSERT (buffer_size_left >= 0); ret_str_buffer_p = lit_copy_magic_string_to_buffer (LIT_MAGIC_STRING_SPACE_CHAR, ret_str_buffer_p, buffer_size_left); buffer_size_left = buffer_size - (ret_str_buffer_p - ret_str_buffer); JERRY_ASSERT (buffer_size_left >= 0); bytes = ecma_string_to_utf8_string (msg_string_p, ret_str_buffer_p, buffer_size_left); JERRY_ASSERT (bytes >= 0 && buffer_size_left - bytes >= 0); buffer_size_left -= bytes; JERRY_ASSERT (buffer_size_left >= 0); ret_str_p = ecma_new_ecma_string_from_utf8 (ret_str_buffer, (jerry_api_size_t) (buffer_size - buffer_size_left)); MEM_FINALIZE_LOCAL_ARRAY (ret_str_buffer); } ret_value = ecma_make_normal_completion_value (ecma_make_string_value (ret_str_p)); } ecma_free_completion_value (msg_to_str_completion); ECMA_FINALIZE (msg_get_ret_value); ecma_deref_ecma_string (message_magic_string_p); } ecma_free_completion_value (name_to_str_completion); ECMA_FINALIZE (name_get_ret_value); ecma_deref_ecma_string (name_magic_string_p); } return ret_value; } /* ecma_builtin_error_prototype_object_to_string */
/** * The Function.prototype object's 'bind' routine * * See also: * ECMA-262 v5, 15.3.4.5 * * @return completion value * Returned value must be freed with ecma_free_completion_value. */ static ecma_completion_value_t ecma_builtin_function_prototype_object_bind (ecma_value_t this_arg, /**< this argument */ const ecma_value_t* arguments_list_p, /**< list of arguments */ ecma_length_t arguments_number) /**< number of arguments */ { ecma_completion_value_t ret_value = ecma_make_empty_completion_value (); /* 2. */ if (!ecma_op_is_callable (this_arg)) { ret_value = ecma_make_throw_obj_completion_value (ecma_new_standard_error (ECMA_ERROR_TYPE)); } else { /* 4. 11. 18. */ ecma_object_t *prototype_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE); ecma_object_t *function_p = ecma_create_object (prototype_obj_p, true, ECMA_OBJECT_TYPE_BOUND_FUNCTION); ecma_deref_object (prototype_obj_p); /* 7. */ ecma_property_t *target_function_prop_p; target_function_prop_p = ecma_create_internal_property (function_p, ECMA_INTERNAL_PROPERTY_BOUND_FUNCTION_TARGET_FUNCTION); ecma_object_t *this_arg_obj_p = ecma_get_object_from_value (this_arg); ECMA_SET_NON_NULL_POINTER (target_function_prop_p->u.internal_property.value, this_arg_obj_p); /* 8. */ ecma_property_t *bound_this_prop_p; bound_this_prop_p = ecma_create_internal_property (function_p, ECMA_INTERNAL_PROPERTY_BOUND_FUNCTION_BOUND_THIS); const ecma_length_t arg_count = arguments_number; if (arg_count > 0) { bound_this_prop_p->u.internal_property.value = ecma_copy_value (arguments_list_p[0], false); } else { bound_this_prop_p->u.internal_property.value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED); } if (arg_count > 1) { ecma_collection_header_t *bound_args_collection_p; bound_args_collection_p = ecma_new_values_collection (&arguments_list_p[1], arg_count - 1, false); ecma_property_t *bound_args_prop_p; bound_args_prop_p = ecma_create_internal_property (function_p, ECMA_INTERNAL_PROPERTY_BOUND_FUNCTION_BOUND_ARGS); ECMA_SET_NON_NULL_POINTER (bound_args_prop_p->u.internal_property.value, bound_args_collection_p); } /* * [[Class]] property is not stored explicitly for objects of ECMA_OBJECT_TYPE_FUNCTION type. * * See also: ecma_object_get_class_name */ ecma_number_t *length_p = ecma_alloc_number (); ecma_string_t *magic_string_length_p = ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH); /* 15. */ if (ecma_object_get_class_name (this_arg_obj_p) == LIT_MAGIC_STRING_FUNCTION_UL) { ecma_completion_value_t get_len_completion = ecma_op_object_get (this_arg_obj_p, magic_string_length_p); JERRY_ASSERT (ecma_is_completion_value_normal (get_len_completion)); ecma_value_t len_value = ecma_get_completion_value_value (get_len_completion); JERRY_ASSERT (ecma_is_value_number (len_value)); const ecma_length_t bound_arg_count = arg_count > 1 ? arg_count - 1 : 0; /* 15.a */ *length_p = *ecma_get_number_from_value (len_value) - ecma_uint32_to_number (bound_arg_count); ecma_free_completion_value (get_len_completion); /* 15.b */ if (ecma_number_is_negative (*length_p)) { *length_p = ECMA_NUMBER_ZERO; } } else { /* 16. */ *length_p = ECMA_NUMBER_ZERO; } /* 17. */ ecma_completion_value_t completion = ecma_builtin_helper_def_prop (function_p, magic_string_length_p, ecma_make_number_value (length_p), false, /* Writable */ false, /* Enumerable */ false, /* Configurable */ false); /* Failure handling */ JERRY_ASSERT (ecma_is_completion_value_normal_true (completion) || ecma_is_completion_value_normal_false (completion)); ecma_deref_ecma_string (magic_string_length_p); ecma_dealloc_number (length_p); /* 19-21. */ ecma_object_t *thrower_p = ecma_builtin_get (ECMA_BUILTIN_ID_TYPE_ERROR_THROWER); ecma_property_descriptor_t prop_desc = ecma_make_empty_property_descriptor (); { prop_desc.is_enumerable_defined = true; prop_desc.is_enumerable = false; prop_desc.is_configurable_defined = true; prop_desc.is_configurable = false; prop_desc.is_get_defined = true; prop_desc.get_p = thrower_p; prop_desc.is_set_defined = true; prop_desc.set_p = thrower_p; } ecma_string_t *magic_string_caller_p = ecma_get_magic_string (LIT_MAGIC_STRING_CALLER); completion = ecma_op_object_define_own_property (function_p, magic_string_caller_p, &prop_desc, false); JERRY_ASSERT (ecma_is_completion_value_normal_true (completion) || ecma_is_completion_value_normal_false (completion)); ecma_deref_ecma_string (magic_string_caller_p); ecma_string_t *magic_string_arguments_p = ecma_get_magic_string (LIT_MAGIC_STRING_ARGUMENTS); completion = ecma_op_object_define_own_property (function_p, magic_string_arguments_p, &prop_desc, false); JERRY_ASSERT (ecma_is_completion_value_normal_true (completion) || ecma_is_completion_value_normal_false (completion)); ecma_deref_ecma_string (magic_string_arguments_p); ecma_deref_object (thrower_p); /* 22. */ ret_value = ecma_make_normal_completion_value (ecma_make_object_value (function_p)); } return ret_value; } /* ecma_builtin_function_prototype_object_bind */
/** * [[Call]] implementation for Function objects, * created through 13.2 (ECMA_OBJECT_TYPE_FUNCTION) * or 15.3.4.5 (ECMA_OBJECT_TYPE_BOUND_FUNCTION), * and for built-in Function objects * from section 15 (ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION). * * @return completion value * Returned value must be freed with ecma_free_completion_value */ ecma_completion_value_t ecma_op_function_call (ecma_object_t *func_obj_p, /**< Function object */ ecma_value_t this_arg_value, /**< 'this' argument's value */ const ecma_value_t* arguments_list_p, /**< arguments list */ ecma_length_t arguments_list_len) /**< length of arguments list */ { JERRY_ASSERT (func_obj_p != NULL && !ecma_is_lexical_environment (func_obj_p)); JERRY_ASSERT (ecma_op_is_callable (ecma_make_object_value (func_obj_p))); JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); ecma_completion_value_t ret_value = ecma_make_empty_completion_value (); if (ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_FUNCTION) { if (unlikely (ecma_get_object_is_builtin (func_obj_p))) { ret_value = ecma_builtin_dispatch_call (func_obj_p, this_arg_value, arguments_list_p, arguments_list_len); } else { /* Entering Function Code (ECMA-262 v5, 10.4.3) */ ecma_property_t *scope_prop_p = ecma_get_internal_property (func_obj_p, ECMA_INTERNAL_PROPERTY_SCOPE); ecma_property_t *bytecode_prop_p = ecma_get_internal_property (func_obj_p, ECMA_INTERNAL_PROPERTY_CODE_BYTECODE); ecma_property_t *code_prop_p = ecma_get_internal_property (func_obj_p, ECMA_INTERNAL_PROPERTY_CODE_FLAGS_AND_OFFSET); ecma_object_t *scope_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, scope_prop_p->u.internal_property.value); uint32_t code_prop_value = code_prop_p->u.internal_property.value; // 8. bool is_strict; bool do_instantiate_args_obj; const vm_instr_t *instrs_p = MEM_CP_GET_POINTER (const vm_instr_t, bytecode_prop_p->u.internal_property.value); vm_instr_counter_t code_first_instr_pos = ecma_unpack_code_internal_property_value (code_prop_value, &is_strict, &do_instantiate_args_obj); ecma_value_t this_binding; // 1. if (is_strict) { this_binding = ecma_copy_value (this_arg_value, true); } else if (ecma_is_value_undefined (this_arg_value) || ecma_is_value_null (this_arg_value)) { // 2. this_binding = ecma_make_object_value (ecma_builtin_get (ECMA_BUILTIN_ID_GLOBAL)); } else { // 3., 4. ecma_completion_value_t completion = ecma_op_to_object (this_arg_value); JERRY_ASSERT (ecma_is_completion_value_normal (completion)); this_binding = ecma_get_completion_value_value (completion); } // 5. ecma_object_t *local_env_p = ecma_create_decl_lex_env (scope_p); // 9. ECMA_TRY_CATCH (args_var_declaration_ret, ecma_function_call_setup_args_variables (func_obj_p, local_env_p, arguments_list_p, arguments_list_len, is_strict, do_instantiate_args_obj), ret_value); ecma_completion_value_t completion = vm_run_from_pos (instrs_p, code_first_instr_pos, this_binding, local_env_p, is_strict, false); if (ecma_is_completion_value_return (completion)) { ret_value = ecma_make_normal_completion_value (ecma_get_completion_value_value (completion)); } else { ret_value = completion; } ECMA_FINALIZE (args_var_declaration_ret); ecma_deref_object (local_env_p); ecma_free_value (this_binding, true); } } else if (ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION)