1425bb815Sopenharmony_ci/* Copyright JS Foundation and other contributors, http://js.foundation
2425bb815Sopenharmony_ci *
3425bb815Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4425bb815Sopenharmony_ci * you may not use this file except in compliance with the License.
5425bb815Sopenharmony_ci * You may obtain a copy of the License at
6425bb815Sopenharmony_ci *
7425bb815Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8425bb815Sopenharmony_ci *
9425bb815Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10425bb815Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS
11425bb815Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12425bb815Sopenharmony_ci * See the License for the specific language governing permissions and
13425bb815Sopenharmony_ci * limitations under the License.
14425bb815Sopenharmony_ci */
15425bb815Sopenharmony_ci
16425bb815Sopenharmony_ci#include "ecma-alloc.h"
17425bb815Sopenharmony_ci#include "ecma-gc.h"
18425bb815Sopenharmony_ci#include "ecma-helpers.h"
19425bb815Sopenharmony_ci#include "vm-defines.h"
20425bb815Sopenharmony_ci#include "vm-stack.h"
21425bb815Sopenharmony_ci#include "ecma-iterator-object.h"
22425bb815Sopenharmony_ci
23425bb815Sopenharmony_ci/** \addtogroup vm Virtual machine
24425bb815Sopenharmony_ci * @{
25425bb815Sopenharmony_ci *
26425bb815Sopenharmony_ci * \addtogroup stack VM stack
27425bb815Sopenharmony_ci * @{
28425bb815Sopenharmony_ci */
29425bb815Sopenharmony_ci
30425bb815Sopenharmony_ciJERRY_STATIC_ASSERT (PARSER_WITH_CONTEXT_STACK_ALLOCATION == PARSER_BLOCK_CONTEXT_STACK_ALLOCATION,
31425bb815Sopenharmony_ci                     parser_with_context_stack_allocation_must_be_equal_to_parser_block_context_stack_allocation);
32425bb815Sopenharmony_ci
33425bb815Sopenharmony_ci/**
34425bb815Sopenharmony_ci * Abort (finalize) the current stack context, and remove it.
35425bb815Sopenharmony_ci *
36425bb815Sopenharmony_ci * @return new stack top
37425bb815Sopenharmony_ci */
38425bb815Sopenharmony_ciecma_value_t *
39425bb815Sopenharmony_civm_stack_context_abort (vm_frame_ctx_t *frame_ctx_p, /**< frame context */
40425bb815Sopenharmony_ci                        ecma_value_t *vm_stack_top_p) /**< current stack top */
41425bb815Sopenharmony_ci{
42425bb815Sopenharmony_ci  ecma_value_t context_info = vm_stack_top_p[-1];
43425bb815Sopenharmony_ci
44425bb815Sopenharmony_ci  if (context_info & VM_CONTEXT_HAS_LEX_ENV)
45425bb815Sopenharmony_ci  {
46425bb815Sopenharmony_ci    ecma_object_t *lex_env_p = frame_ctx_p->lex_env_p;
47425bb815Sopenharmony_ci    JERRY_ASSERT (lex_env_p->u2.outer_reference_cp != JMEM_CP_NULL);
48425bb815Sopenharmony_ci    frame_ctx_p->lex_env_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, lex_env_p->u2.outer_reference_cp);
49425bb815Sopenharmony_ci    ecma_deref_object (lex_env_p);
50425bb815Sopenharmony_ci  }
51425bb815Sopenharmony_ci
52425bb815Sopenharmony_ci  switch (VM_GET_CONTEXT_TYPE (context_info))
53425bb815Sopenharmony_ci  {
54425bb815Sopenharmony_ci    case VM_CONTEXT_FINALLY_THROW:
55425bb815Sopenharmony_ci    case VM_CONTEXT_FINALLY_RETURN:
56425bb815Sopenharmony_ci    {
57425bb815Sopenharmony_ci      ecma_free_value (vm_stack_top_p[-2]);
58425bb815Sopenharmony_ci      /* FALLTHRU */
59425bb815Sopenharmony_ci    }
60425bb815Sopenharmony_ci    case VM_CONTEXT_FINALLY_JUMP:
61425bb815Sopenharmony_ci    case VM_CONTEXT_TRY:
62425bb815Sopenharmony_ci    case VM_CONTEXT_CATCH:
63425bb815Sopenharmony_ci    {
64425bb815Sopenharmony_ci      VM_MINUS_EQUAL_U16 (frame_ctx_p->context_depth, PARSER_TRY_CONTEXT_STACK_ALLOCATION);
65425bb815Sopenharmony_ci      vm_stack_top_p -= PARSER_TRY_CONTEXT_STACK_ALLOCATION;
66425bb815Sopenharmony_ci      break;
67425bb815Sopenharmony_ci    }
68425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
69425bb815Sopenharmony_ci    case VM_CONTEXT_BLOCK:
70425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
71425bb815Sopenharmony_ci    case VM_CONTEXT_WITH:
72425bb815Sopenharmony_ci    {
73425bb815Sopenharmony_ci      VM_MINUS_EQUAL_U16 (frame_ctx_p->context_depth, PARSER_WITH_CONTEXT_STACK_ALLOCATION);
74425bb815Sopenharmony_ci      vm_stack_top_p -= PARSER_WITH_CONTEXT_STACK_ALLOCATION;
75425bb815Sopenharmony_ci      break;
76425bb815Sopenharmony_ci    }
77425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
78425bb815Sopenharmony_ci    case VM_CONTEXT_FOR_OF:
79425bb815Sopenharmony_ci    {
80425bb815Sopenharmony_ci      ecma_value_t iterator = vm_stack_top_p[-3];
81425bb815Sopenharmony_ci
82425bb815Sopenharmony_ci      if (context_info & VM_CONTEXT_CLOSE_ITERATOR)
83425bb815Sopenharmony_ci      {
84425bb815Sopenharmony_ci        ecma_op_iterator_close (iterator);
85425bb815Sopenharmony_ci      }
86425bb815Sopenharmony_ci      ecma_free_value (iterator);
87425bb815Sopenharmony_ci
88425bb815Sopenharmony_ci      ecma_free_value (vm_stack_top_p[-2]);
89425bb815Sopenharmony_ci      VM_MINUS_EQUAL_U16 (frame_ctx_p->context_depth, PARSER_FOR_OF_CONTEXT_STACK_ALLOCATION);
90425bb815Sopenharmony_ci      vm_stack_top_p -= PARSER_FOR_OF_CONTEXT_STACK_ALLOCATION;
91425bb815Sopenharmony_ci      break;
92425bb815Sopenharmony_ci    }
93425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
94425bb815Sopenharmony_ci    default:
95425bb815Sopenharmony_ci    {
96425bb815Sopenharmony_ci      JERRY_ASSERT (VM_GET_CONTEXT_TYPE (vm_stack_top_p[-1]) == VM_CONTEXT_FOR_IN);
97425bb815Sopenharmony_ci
98425bb815Sopenharmony_ci      ecma_collection_t *collection_p;
99425bb815Sopenharmony_ci      collection_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_collection_t, vm_stack_top_p[-2]);
100425bb815Sopenharmony_ci
101425bb815Sopenharmony_ci      ecma_value_t *buffer_p = collection_p->buffer_p;
102425bb815Sopenharmony_ci
103425bb815Sopenharmony_ci      for (uint32_t index = vm_stack_top_p[-3]; index < collection_p->item_count; index++)
104425bb815Sopenharmony_ci      {
105425bb815Sopenharmony_ci        ecma_free_value (buffer_p[index]);
106425bb815Sopenharmony_ci      }
107425bb815Sopenharmony_ci
108425bb815Sopenharmony_ci      ecma_collection_destroy (collection_p);
109425bb815Sopenharmony_ci
110425bb815Sopenharmony_ci      ecma_free_value (vm_stack_top_p[-4]);
111425bb815Sopenharmony_ci
112425bb815Sopenharmony_ci      VM_MINUS_EQUAL_U16 (frame_ctx_p->context_depth, PARSER_FOR_IN_CONTEXT_STACK_ALLOCATION);
113425bb815Sopenharmony_ci      vm_stack_top_p -= PARSER_FOR_IN_CONTEXT_STACK_ALLOCATION;
114425bb815Sopenharmony_ci      break;
115425bb815Sopenharmony_ci    }
116425bb815Sopenharmony_ci  }
117425bb815Sopenharmony_ci
118425bb815Sopenharmony_ci  return vm_stack_top_p;
119425bb815Sopenharmony_ci} /* vm_stack_context_abort */
120425bb815Sopenharmony_ci
121425bb815Sopenharmony_ci/**
122425bb815Sopenharmony_ci * Decode branch offset.
123425bb815Sopenharmony_ci *
124425bb815Sopenharmony_ci * @return branch offset
125425bb815Sopenharmony_ci */
126425bb815Sopenharmony_cistatic uint32_t
127425bb815Sopenharmony_civm_decode_branch_offset (const uint8_t *branch_offset_p, /**< start offset of byte code */
128425bb815Sopenharmony_ci                         uint32_t length) /**< length of the branch */
129425bb815Sopenharmony_ci{
130425bb815Sopenharmony_ci  uint32_t branch_offset = *branch_offset_p;
131425bb815Sopenharmony_ci
132425bb815Sopenharmony_ci  JERRY_ASSERT (length >= 1 && length <= 3);
133425bb815Sopenharmony_ci
134425bb815Sopenharmony_ci  switch (length)
135425bb815Sopenharmony_ci  {
136425bb815Sopenharmony_ci    case 3:
137425bb815Sopenharmony_ci    {
138425bb815Sopenharmony_ci      branch_offset <<= 8;
139425bb815Sopenharmony_ci      branch_offset |= *(++branch_offset_p);
140425bb815Sopenharmony_ci      /* FALLTHRU */
141425bb815Sopenharmony_ci    }
142425bb815Sopenharmony_ci    case 2:
143425bb815Sopenharmony_ci    {
144425bb815Sopenharmony_ci      branch_offset <<= 8;
145425bb815Sopenharmony_ci      branch_offset |= *(++branch_offset_p);
146425bb815Sopenharmony_ci      break;
147425bb815Sopenharmony_ci    }
148425bb815Sopenharmony_ci  }
149425bb815Sopenharmony_ci
150425bb815Sopenharmony_ci  return branch_offset;
151425bb815Sopenharmony_ci} /* vm_decode_branch_offset */
152425bb815Sopenharmony_ci
153425bb815Sopenharmony_ci/**
154425bb815Sopenharmony_ci * Find a finally up to the end position.
155425bb815Sopenharmony_ci *
156425bb815Sopenharmony_ci * @return true - if 'finally' found,
157425bb815Sopenharmony_ci *         false - otherwise
158425bb815Sopenharmony_ci */
159425bb815Sopenharmony_cibool
160425bb815Sopenharmony_civm_stack_find_finally (vm_frame_ctx_t *frame_ctx_p, /**< frame context */
161425bb815Sopenharmony_ci                       ecma_value_t **vm_stack_top_ref_p, /**< current stack top */
162425bb815Sopenharmony_ci                       vm_stack_context_type_t finally_type, /**< searching this finally */
163425bb815Sopenharmony_ci                       uint32_t search_limit) /**< search up-to this byte code */
164425bb815Sopenharmony_ci{
165425bb815Sopenharmony_ci  ecma_value_t *vm_stack_top_p = *vm_stack_top_ref_p;
166425bb815Sopenharmony_ci
167425bb815Sopenharmony_ci  JERRY_ASSERT (finally_type <= VM_CONTEXT_FINALLY_RETURN);
168425bb815Sopenharmony_ci
169425bb815Sopenharmony_ci  if (finally_type != VM_CONTEXT_FINALLY_JUMP)
170425bb815Sopenharmony_ci  {
171425bb815Sopenharmony_ci    search_limit = 0xffffffffu;
172425bb815Sopenharmony_ci  }
173425bb815Sopenharmony_ci
174425bb815Sopenharmony_ci  while (frame_ctx_p->context_depth > 0)
175425bb815Sopenharmony_ci  {
176425bb815Sopenharmony_ci    vm_stack_context_type_t context_type;
177425bb815Sopenharmony_ci    uint32_t context_end = VM_GET_CONTEXT_END (vm_stack_top_p[-1]);
178425bb815Sopenharmony_ci
179425bb815Sopenharmony_ci    if (search_limit < context_end)
180425bb815Sopenharmony_ci    {
181425bb815Sopenharmony_ci      *vm_stack_top_ref_p = vm_stack_top_p;
182425bb815Sopenharmony_ci      return false;
183425bb815Sopenharmony_ci    }
184425bb815Sopenharmony_ci
185425bb815Sopenharmony_ci    context_type = VM_GET_CONTEXT_TYPE (vm_stack_top_p[-1]);
186425bb815Sopenharmony_ci    if (context_type == VM_CONTEXT_TRY || context_type == VM_CONTEXT_CATCH)
187425bb815Sopenharmony_ci    {
188425bb815Sopenharmony_ci      const uint8_t *byte_code_p;
189425bb815Sopenharmony_ci      uint32_t branch_offset_length;
190425bb815Sopenharmony_ci      uint32_t branch_offset;
191425bb815Sopenharmony_ci
192425bb815Sopenharmony_ci      if (search_limit == context_end)
193425bb815Sopenharmony_ci      {
194425bb815Sopenharmony_ci        *vm_stack_top_ref_p = vm_stack_top_p;
195425bb815Sopenharmony_ci        return false;
196425bb815Sopenharmony_ci      }
197425bb815Sopenharmony_ci
198425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
199425bb815Sopenharmony_ci      if (vm_stack_top_p[-1] & VM_CONTEXT_HAS_LEX_ENV)
200425bb815Sopenharmony_ci      {
201425bb815Sopenharmony_ci        ecma_object_t *lex_env_p = frame_ctx_p->lex_env_p;
202425bb815Sopenharmony_ci        JERRY_ASSERT (lex_env_p->u2.outer_reference_cp != JMEM_CP_NULL);
203425bb815Sopenharmony_ci        frame_ctx_p->lex_env_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, lex_env_p->u2.outer_reference_cp);
204425bb815Sopenharmony_ci        ecma_deref_object (lex_env_p);
205425bb815Sopenharmony_ci      }
206425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
207425bb815Sopenharmony_ci
208425bb815Sopenharmony_ci      byte_code_p = frame_ctx_p->byte_code_start_p + context_end;
209425bb815Sopenharmony_ci
210425bb815Sopenharmony_ci      if (context_type == VM_CONTEXT_TRY)
211425bb815Sopenharmony_ci      {
212425bb815Sopenharmony_ci        JERRY_ASSERT (byte_code_p[0] == CBC_EXT_OPCODE);
213425bb815Sopenharmony_ci
214425bb815Sopenharmony_ci        if (byte_code_p[1] >= CBC_EXT_CATCH
215425bb815Sopenharmony_ci            && byte_code_p[1] <= CBC_EXT_CATCH_3)
216425bb815Sopenharmony_ci        {
217425bb815Sopenharmony_ci          branch_offset_length = CBC_BRANCH_OFFSET_LENGTH (byte_code_p[1]);
218425bb815Sopenharmony_ci          branch_offset = vm_decode_branch_offset (byte_code_p + 2,
219425bb815Sopenharmony_ci                                                   branch_offset_length);
220425bb815Sopenharmony_ci
221425bb815Sopenharmony_ci          if (finally_type == VM_CONTEXT_FINALLY_THROW)
222425bb815Sopenharmony_ci          {
223425bb815Sopenharmony_ci            branch_offset += (uint32_t) (byte_code_p - frame_ctx_p->byte_code_start_p);
224425bb815Sopenharmony_ci
225425bb815Sopenharmony_ci            vm_stack_top_p[-1] = VM_CREATE_CONTEXT (VM_CONTEXT_CATCH, branch_offset);
226425bb815Sopenharmony_ci
227425bb815Sopenharmony_ci            byte_code_p += 2 + branch_offset_length;
228425bb815Sopenharmony_ci            frame_ctx_p->byte_code_p = byte_code_p;
229425bb815Sopenharmony_ci
230425bb815Sopenharmony_ci            *vm_stack_top_ref_p = vm_stack_top_p;
231425bb815Sopenharmony_ci            return true;
232425bb815Sopenharmony_ci          }
233425bb815Sopenharmony_ci
234425bb815Sopenharmony_ci          byte_code_p += branch_offset;
235425bb815Sopenharmony_ci
236425bb815Sopenharmony_ci          if (*byte_code_p == CBC_CONTEXT_END)
237425bb815Sopenharmony_ci          {
238425bb815Sopenharmony_ci            VM_MINUS_EQUAL_U16 (frame_ctx_p->context_depth, PARSER_TRY_CONTEXT_STACK_ALLOCATION);
239425bb815Sopenharmony_ci            vm_stack_top_p -= PARSER_TRY_CONTEXT_STACK_ALLOCATION;
240425bb815Sopenharmony_ci            continue;
241425bb815Sopenharmony_ci          }
242425bb815Sopenharmony_ci        }
243425bb815Sopenharmony_ci      }
244425bb815Sopenharmony_ci      else
245425bb815Sopenharmony_ci      {
246425bb815Sopenharmony_ci#if !ENABLED (JERRY_ES2015)
247425bb815Sopenharmony_ci        if (vm_stack_top_p[-1] & VM_CONTEXT_HAS_LEX_ENV)
248425bb815Sopenharmony_ci        {
249425bb815Sopenharmony_ci          ecma_object_t *lex_env_p = frame_ctx_p->lex_env_p;
250425bb815Sopenharmony_ci          JERRY_ASSERT (lex_env_p->u2.outer_reference_cp != JMEM_CP_NULL);
251425bb815Sopenharmony_ci          frame_ctx_p->lex_env_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, lex_env_p->u2.outer_reference_cp);
252425bb815Sopenharmony_ci          ecma_deref_object (lex_env_p);
253425bb815Sopenharmony_ci        }
254425bb815Sopenharmony_ci#endif /* !ENABLED (JERRY_ES2015) */
255425bb815Sopenharmony_ci
256425bb815Sopenharmony_ci        if (byte_code_p[0] == CBC_CONTEXT_END)
257425bb815Sopenharmony_ci        {
258425bb815Sopenharmony_ci          VM_MINUS_EQUAL_U16 (frame_ctx_p->context_depth, PARSER_TRY_CONTEXT_STACK_ALLOCATION);
259425bb815Sopenharmony_ci          vm_stack_top_p -= PARSER_TRY_CONTEXT_STACK_ALLOCATION;
260425bb815Sopenharmony_ci          continue;
261425bb815Sopenharmony_ci        }
262425bb815Sopenharmony_ci      }
263425bb815Sopenharmony_ci
264425bb815Sopenharmony_ci      JERRY_ASSERT (byte_code_p[0] == CBC_EXT_OPCODE);
265425bb815Sopenharmony_ci      JERRY_ASSERT (byte_code_p[1] >= CBC_EXT_FINALLY
266425bb815Sopenharmony_ci                    && byte_code_p[1] <= CBC_EXT_FINALLY_3);
267425bb815Sopenharmony_ci
268425bb815Sopenharmony_ci      branch_offset_length = CBC_BRANCH_OFFSET_LENGTH (byte_code_p[1]);
269425bb815Sopenharmony_ci      branch_offset = vm_decode_branch_offset (byte_code_p + 2,
270425bb815Sopenharmony_ci                                               branch_offset_length);
271425bb815Sopenharmony_ci
272425bb815Sopenharmony_ci      branch_offset += (uint32_t) (byte_code_p - frame_ctx_p->byte_code_start_p);
273425bb815Sopenharmony_ci
274425bb815Sopenharmony_ci      vm_stack_top_p[-1] = VM_CREATE_CONTEXT ((uint32_t) finally_type, branch_offset);
275425bb815Sopenharmony_ci
276425bb815Sopenharmony_ci      byte_code_p += 2 + branch_offset_length;
277425bb815Sopenharmony_ci      frame_ctx_p->byte_code_p = byte_code_p;
278425bb815Sopenharmony_ci
279425bb815Sopenharmony_ci      *vm_stack_top_ref_p = vm_stack_top_p;
280425bb815Sopenharmony_ci      return true;
281425bb815Sopenharmony_ci    }
282425bb815Sopenharmony_ci
283425bb815Sopenharmony_ci    vm_stack_top_p = vm_stack_context_abort (frame_ctx_p, vm_stack_top_p);
284425bb815Sopenharmony_ci  }
285425bb815Sopenharmony_ci
286425bb815Sopenharmony_ci  *vm_stack_top_ref_p = vm_stack_top_p;
287425bb815Sopenharmony_ci  return false;
288425bb815Sopenharmony_ci} /* vm_stack_find_finally */
289425bb815Sopenharmony_ci
290425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
291425bb815Sopenharmony_ci
292425bb815Sopenharmony_ci/**
293425bb815Sopenharmony_ci * Get the offsets of ecma values from the specified item of a context.
294425bb815Sopenharmony_ci *
295425bb815Sopenharmony_ci * @return array of offsets, last item represents the size of the context item
296425bb815Sopenharmony_ci */
297425bb815Sopenharmony_ciuint32_t
298425bb815Sopenharmony_civm_get_context_value_offsets (ecma_value_t *context_item_p) /**< any item of a context */
299425bb815Sopenharmony_ci{
300425bb815Sopenharmony_ci  switch (VM_GET_CONTEXT_TYPE (context_item_p[-1]))
301425bb815Sopenharmony_ci  {
302425bb815Sopenharmony_ci    case VM_CONTEXT_FINALLY_THROW:
303425bb815Sopenharmony_ci    case VM_CONTEXT_FINALLY_RETURN:
304425bb815Sopenharmony_ci    {
305425bb815Sopenharmony_ci      return (2 << (VM_CONTEXT_OFFSET_SHIFT)) | PARSER_TRY_CONTEXT_STACK_ALLOCATION;
306425bb815Sopenharmony_ci    }
307425bb815Sopenharmony_ci    case VM_CONTEXT_FINALLY_JUMP:
308425bb815Sopenharmony_ci    case VM_CONTEXT_TRY:
309425bb815Sopenharmony_ci    case VM_CONTEXT_CATCH:
310425bb815Sopenharmony_ci    {
311425bb815Sopenharmony_ci      return PARSER_TRY_CONTEXT_STACK_ALLOCATION;
312425bb815Sopenharmony_ci    }
313425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
314425bb815Sopenharmony_ci    case VM_CONTEXT_BLOCK:
315425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
316425bb815Sopenharmony_ci    case VM_CONTEXT_WITH:
317425bb815Sopenharmony_ci    {
318425bb815Sopenharmony_ci      return PARSER_WITH_CONTEXT_STACK_ALLOCATION;
319425bb815Sopenharmony_ci    }
320425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
321425bb815Sopenharmony_ci    case VM_CONTEXT_FOR_OF:
322425bb815Sopenharmony_ci    {
323425bb815Sopenharmony_ci      return ((3 << (VM_CONTEXT_OFFSET_SHIFT * 2))
324425bb815Sopenharmony_ci              | (2 << (VM_CONTEXT_OFFSET_SHIFT))
325425bb815Sopenharmony_ci              | PARSER_FOR_OF_CONTEXT_STACK_ALLOCATION);
326425bb815Sopenharmony_ci    }
327425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
328425bb815Sopenharmony_ci    default:
329425bb815Sopenharmony_ci    {
330425bb815Sopenharmony_ci      return (4 << (VM_CONTEXT_OFFSET_SHIFT)) | PARSER_FOR_IN_CONTEXT_STACK_ALLOCATION;
331425bb815Sopenharmony_ci    }
332425bb815Sopenharmony_ci  }
333425bb815Sopenharmony_ci} /* vm_get_context_value_offsets */
334425bb815Sopenharmony_ci
335425bb815Sopenharmony_ci/**
336425bb815Sopenharmony_ci * Ref / deref lexical environments in the chain using the current context.
337425bb815Sopenharmony_ci */
338425bb815Sopenharmony_civoid
339425bb815Sopenharmony_civm_ref_lex_env_chain (ecma_object_t *lex_env_p, /**< top of lexical environment */
340425bb815Sopenharmony_ci                      uint16_t context_depth, /**< depth of function context */
341425bb815Sopenharmony_ci                      ecma_value_t *context_end_p, /**< end of function context */
342425bb815Sopenharmony_ci                      bool do_ref) /**< ref or deref lexical environments */
343425bb815Sopenharmony_ci{
344425bb815Sopenharmony_ci  ecma_value_t *context_top_p = context_end_p + context_depth;
345425bb815Sopenharmony_ci  JERRY_ASSERT (context_top_p > context_end_p);
346425bb815Sopenharmony_ci
347425bb815Sopenharmony_ci  do
348425bb815Sopenharmony_ci  {
349425bb815Sopenharmony_ci    if (context_top_p[-1] & VM_CONTEXT_HAS_LEX_ENV)
350425bb815Sopenharmony_ci    {
351425bb815Sopenharmony_ci      JERRY_ASSERT (lex_env_p->u2.outer_reference_cp != JMEM_CP_NULL);
352425bb815Sopenharmony_ci      ecma_object_t *next_lex_env_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, lex_env_p->u2.outer_reference_cp);
353425bb815Sopenharmony_ci
354425bb815Sopenharmony_ci      if (do_ref)
355425bb815Sopenharmony_ci      {
356425bb815Sopenharmony_ci        ecma_ref_object (lex_env_p);
357425bb815Sopenharmony_ci      }
358425bb815Sopenharmony_ci      else
359425bb815Sopenharmony_ci      {
360425bb815Sopenharmony_ci        ecma_deref_object (lex_env_p);
361425bb815Sopenharmony_ci      }
362425bb815Sopenharmony_ci
363425bb815Sopenharmony_ci      lex_env_p = next_lex_env_p;
364425bb815Sopenharmony_ci    }
365425bb815Sopenharmony_ci
366425bb815Sopenharmony_ci    uint32_t offsets = vm_get_context_value_offsets (context_top_p);
367425bb815Sopenharmony_ci
368425bb815Sopenharmony_ci    while (VM_CONTEXT_HAS_NEXT_OFFSET (offsets))
369425bb815Sopenharmony_ci    {
370425bb815Sopenharmony_ci      int32_t offset = VM_CONTEXT_GET_NEXT_OFFSET (offsets);
371425bb815Sopenharmony_ci
372425bb815Sopenharmony_ci      if (do_ref)
373425bb815Sopenharmony_ci      {
374425bb815Sopenharmony_ci        ecma_ref_if_object (context_top_p[offset]);
375425bb815Sopenharmony_ci      }
376425bb815Sopenharmony_ci      else
377425bb815Sopenharmony_ci      {
378425bb815Sopenharmony_ci        ecma_deref_if_object (context_top_p[offset]);
379425bb815Sopenharmony_ci      }
380425bb815Sopenharmony_ci
381425bb815Sopenharmony_ci      offsets >>= VM_CONTEXT_OFFSET_SHIFT;
382425bb815Sopenharmony_ci    }
383425bb815Sopenharmony_ci
384425bb815Sopenharmony_ci    JERRY_ASSERT (context_top_p >= context_end_p + offsets);
385425bb815Sopenharmony_ci    context_top_p -= offsets;
386425bb815Sopenharmony_ci  }
387425bb815Sopenharmony_ci  while (context_top_p > context_end_p);
388425bb815Sopenharmony_ci} /* vm_ref_lex_env_chain */
389425bb815Sopenharmony_ci
390425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
391425bb815Sopenharmony_ci
392425bb815Sopenharmony_ci/**
393425bb815Sopenharmony_ci * @}
394425bb815Sopenharmony_ci * @}
395425bb815Sopenharmony_ci */
396