예제 #1
0
/**
 * Dump scope to current scope
 *
 * NOTE:
 *   This function is used for processing of function expressions as they should not be hoisted.
 *   After parsing a function expression, it is immediately dumped to current scope via call of this function.
 */
void
serializer_dump_subscope (scopes_tree tree) /**< scope to dump */
{
  JERRY_ASSERT (tree != NULL);
  vm_instr_counter_t instr_pos;
  bool header = true;
  for (instr_pos = 0; instr_pos < tree->instrs_count; instr_pos++)
  {
    op_meta *om_p = (op_meta *) linked_list_element (tree->instrs, instr_pos);
    if (om_p->op.op_idx != VM_OP_VAR_DECL
        && om_p->op.op_idx != VM_OP_META && !header)
    {
      break;
    }
    if (om_p->op.op_idx == VM_OP_REG_VAR_DECL)
    {
      header = false;
    }
    scopes_tree_add_op_meta (current_scope, *om_p);
  }
  for (vm_instr_counter_t var_decl_pos = 0; var_decl_pos < tree->var_decls_cout; var_decl_pos++)
  {
    op_meta *om_p = (op_meta *) linked_list_element (tree->var_decls, var_decl_pos);
    scopes_tree_add_op_meta (current_scope, *om_p);
  }
  for (uint8_t child_id = 0; child_id < tree->t.children_num; child_id++)
  {
    serializer_dump_subscope (*(scopes_tree *) linked_list_element (tree->t.children, child_id));
  }
  for (; instr_pos < tree->instrs_count; instr_pos++)
  {
    op_meta *om_p = (op_meta *) linked_list_element (tree->instrs, instr_pos);
    scopes_tree_add_op_meta (current_scope, *om_p);
  }
} /* serializer_dump_subscope */
예제 #2
0
/**
 * Initialize a scope
 *
 * @return initialized scope
 */
scopes_tree
scopes_tree_init (scopes_tree parent) /**< parent scope */
{
  scopes_tree tree = (scopes_tree) jsp_mm_alloc (sizeof (scopes_tree_int));
  memset (tree, 0, sizeof (scopes_tree_int));
  tree->t.parent = (tree_header *) parent;
  tree->t.children = null_list;
  tree->t.children_num = 0;
  if (parent != NULL)
  {
    if (parent->t.children_num == 0)
    {
      parent->t.children = linked_list_init (sizeof (scopes_tree));
    }
    linked_list_set_element (parent->t.children, parent->t.children_num, &tree);
    void *added = linked_list_element (parent->t.children, parent->t.children_num);
    JERRY_ASSERT (*(scopes_tree *) added == tree);
    parent->t.children_num++;
  }
  tree->instrs_count = 0;
  tree->strict_mode = false;
  tree->ref_eval = false;
  tree->ref_arguments = false;
  tree->instrs = linked_list_init (sizeof (op_meta));
  tree->var_decls_cout = 0;
  tree->var_decls = linked_list_init (sizeof (op_meta));
  return tree;
} /* scopes_tree_init */
예제 #3
0
op_meta
scopes_tree_op_meta (scopes_tree tree, vm_instr_counter_t oc)
{
  assert_tree (tree);
  JERRY_ASSERT (oc < tree->instrs_count);
  return *(op_meta *) linked_list_element (tree->instrs, oc);
}
예제 #4
0
/**
 * Get variable declaration for the specified scope
 *
 * @return instruction, declaring a variable
 */
op_meta
scopes_tree_var_decl (scopes_tree tree, /**< scope, from which variable declaration is retrieved */
                      vm_instr_counter_t oc) /**< number of variable declaration in the scope */
{
  assert_tree (tree);
  JERRY_ASSERT (oc < tree->var_decls_cout);
  return *(op_meta *) linked_list_element (tree->var_decls, oc);
} /* scopes_tree_var_decl */
예제 #5
0
vm_instr_counter_t
scopes_tree_count_instructions (scopes_tree t)
{
  assert_tree (t);
  vm_instr_counter_t res = (vm_instr_counter_t) (t->instrs_count + t->var_decls_cout);
  for (uint8_t i = 0; i < t->t.children_num; i++)
  {
    res = (vm_instr_counter_t) (
      res + scopes_tree_count_instructions (
        *(scopes_tree *) linked_list_element (t->t.children, i)));
  }
  return res;
}
예제 #6
0
/**
 * Count slots needed for a scope's hash table
 *
 * Before filling literal indexes 'hash' table we shall initiate it with number of neccesary literal indexes.
 * Since bytecode is divided into blocks and id of the block is a part of hash key, we shall divide bytecode
 *  into blocks and count unique literal indexes used in each block.
 *
 * @return total number of literals in scope
 */
size_t
scopes_tree_count_literals_in_blocks (scopes_tree tree) /**< scope */
{
  assert_tree (tree);
  size_t result = 0;

  if (lit_id_to_uid != null_hash)
  {
    hash_table_free (lit_id_to_uid);
    lit_id_to_uid = null_hash;
  }
  next_uid = 0;
  global_oc = 0;

  assert_tree (tree);
  vm_instr_counter_t instr_pos;
  bool header = true;
  for (instr_pos = 0; instr_pos < tree->instrs_count; instr_pos++)
  {
    op_meta *om_p = extract_op_meta (tree->instrs, instr_pos);
    if (om_p->op.op_idx != VM_OP_META && !header)
    {
      break;
    }
    if (om_p->op.op_idx == VM_OP_REG_VAR_DECL)
    {
      header = false;
    }
    result += count_new_literals_in_instr (om_p);
  }

  for (vm_instr_counter_t var_decl_pos = 0; var_decl_pos < tree->var_decls_cout; var_decl_pos++)
  {
    op_meta *om_p = extract_op_meta (tree->var_decls, var_decl_pos);
    result += count_new_literals_in_instr (om_p);
  }

  for (uint8_t child_id = 0; child_id < tree->t.children_num; child_id++)
  {
    result += scopes_tree_count_literals_in_blocks (*(scopes_tree *) linked_list_element (tree->t.children, child_id));
  }

  for (; instr_pos < tree->instrs_count; instr_pos++)
  {
    op_meta *om_p = extract_op_meta (tree->instrs, instr_pos);
    result += count_new_literals_in_instr (om_p);
  }

  return result;
} /* scopes_tree_count_literals_in_blocks */
예제 #7
0
void
scopes_tree_free (scopes_tree tree)
{
  assert_tree (tree);
  if (tree->t.children_num != 0)
  {
    for (uint8_t i = 0; i < tree->t.children_num; ++i)
    {
      scopes_tree_free (*(scopes_tree *) linked_list_element (tree->t.children, i));
    }
    linked_list_free (tree->t.children);
  }
  linked_list_free (tree->instrs);
  linked_list_free (tree->var_decls);
  jsp_mm_free (tree);
}
예제 #8
0
/*
 * This function performs functions hoisting.
 *
 *  Each scope consists of four parts:
 *  1) Header with 'use strict' marker and reg_var_decl opcode
 *  2) Variable declarations, dumped by the preparser
 *  3) Function declarations
 *  4) Computational code
 *
 *  Header and var_decls are dumped first,
 *  then we shall recursively dump function declaration,
 *  and finally, other instructions.
 *
 *  For each instructions block (size of block is defined in bytecode-data.h)
 *  literal indexes 'hash' table is filled.
 */
static void
merge_subscopes (scopes_tree tree, /**< scopes tree to merge */
                 vm_instr_t *data_p, /**< instruction array, where the scopes are merged to */
                 lit_id_hash_table *lit_ids_p) /**< literal indexes 'hash' table */
{
  assert_tree (tree);
  JERRY_ASSERT (data_p);
  vm_instr_counter_t instr_pos;
  bool header = true;
  for (instr_pos = 0; instr_pos < tree->instrs_count; instr_pos++)
  {
    op_meta *om_p = extract_op_meta (tree->instrs, instr_pos);
    if (om_p->op.op_idx != VM_OP_VAR_DECL
        && om_p->op.op_idx != VM_OP_META && !header)
    {
      break;
    }
    if (om_p->op.op_idx == VM_OP_REG_VAR_DECL)
    {
      header = false;
    }
    data_p[global_oc] = generate_instr (tree->instrs, instr_pos, lit_ids_p);
    global_oc++;
  }

  for (vm_instr_counter_t var_decl_pos = 0; var_decl_pos < tree->var_decls_cout; var_decl_pos++)
  {
    data_p[global_oc] = generate_instr (tree->var_decls, var_decl_pos, lit_ids_p);
    global_oc++;
  }

  for (uint8_t child_id = 0; child_id < tree->t.children_num; child_id++)
  {
    merge_subscopes (*(scopes_tree *) linked_list_element (tree->t.children, child_id),
                     data_p, lit_ids_p);
  }

  for (; instr_pos < tree->instrs_count; instr_pos++)
  {
    data_p[global_oc] = generate_instr (tree->instrs, instr_pos, lit_ids_p);
    global_oc++;
  }
} /* merge_subscopes */
예제 #9
0
void *
linked_list_element (linked_list list, size_t element_num)
{
  ASSERT_LIST (list);
  linked_list_header *header = (linked_list_header *) list;
  size_t block_size = linked_list_block_size (header->element_size);
  linked_list raw = list + sizeof (linked_list_header);
  if (block_size < header->element_size * (element_num + 1))
  {
    if (header->next)
    {
      return linked_list_element ((linked_list) header->next,
                                  element_num - (block_size / header->element_size));
    }
    else
    {
      return NULL;
    }
  }
  raw += header->element_size * element_num;
  return raw;
}
예제 #10
0
/**
 * Get instruction from instruction list
 *
 * @return instruction at specified position
 */
static op_meta *
extract_op_meta (linked_list instr_list, /**< instruction list */
                 vm_instr_counter_t instr_pos) /**< position inside the list */
{
  return (op_meta *) linked_list_element (instr_list, instr_pos);
} /* extract_op_meta */