Skip to content

Introducing chunked lists (list of nodes that exactly fit the heap chunk size) #69

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 15, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions jerry-core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ project (JerryCore CXX C ASM)
# Include directories
set(INCLUDE_CORE
${CMAKE_SOURCE_DIR}/jerry-core
${CMAKE_SOURCE_DIR}/jerry-core/rcs
${CMAKE_SOURCE_DIR}/jerry-core/mem
${CMAKE_SOURCE_DIR}/jerry-core/vm
${CMAKE_SOURCE_DIR}/jerry-core/ecma/builtin-objects
Expand All @@ -109,6 +110,7 @@ project (JerryCore CXX C ASM)
# Sources
# Jerry core
file(GLOB SOURCE_CORE_API *.cpp)
file(GLOB SOURCE_CORE_RCS rcs/*.cpp)
file(GLOB SOURCE_CORE_MEM mem/*.cpp)
file(GLOB SOURCE_CORE_VM vm/*.cpp)
file(GLOB SOURCE_CORE_ECMA_BUILTINS ecma/builtin-objects/*.cpp)
Expand All @@ -121,6 +123,7 @@ project (JerryCore CXX C ASM)
set(SOURCE_CORE
jerry.cpp
${SOURCE_CORE_API}
${SOURCE_CORE_RCS}
${SOURCE_CORE_MEM}
${SOURCE_CORE_VM}
${SOURCE_CORE_ECMA_BUILTINS}
Expand Down
334 changes: 334 additions & 0 deletions jerry-core/rcs/rcs-chunked-list.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,334 @@
/* Copyright 2015 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#include "rcs-chunked-list.h"

/**
* Constructor
*/
void
rcs_chunked_list_t::init (void)
{
head_p = NULL;
tail_p = NULL;
} /* rcs_chunked_list_t::init */

/**
* Destructor
*/
void
rcs_chunked_list_t::free (void)
{
JERRY_ASSERT (head_p == NULL);
JERRY_ASSERT (tail_p == NULL);
} /* rcs_chunked_list_t::free */

/**
* Get first node of the list
*
* @return pointer to the first node
*/
rcs_chunked_list_t::node_t*
rcs_chunked_list_t::get_first (void)
const
{
return head_p;
} /* rcs_chunked_list_t::get_first */

/**
* Get last node of the list
*
* @return pointer to the last node
*/
rcs_chunked_list_t::node_t*
rcs_chunked_list_t::get_last (void)
const
{
return tail_p;
} /* rcs_chunked_list_t::get_last */

/**
* Get node, previous to specified
*
* @return pointer to previous node
*/
rcs_chunked_list_t::node_t*
rcs_chunked_list_t::get_prev (rcs_chunked_list_t::node_t *node_p) /**< node to get previous for */
const
{
JERRY_ASSERT (node_p != NULL);

return MEM_CP_GET_POINTER (node_t, node_p->prev_cp);
} /* rcs_chunked_list_t::get_prev */

/**
* Get node, next to specified
*
* @return pointer to next node
*/
rcs_chunked_list_t::node_t*
rcs_chunked_list_t::get_next (rcs_chunked_list_t::node_t *node_p) /**< node to get next for */
const
{
JERRY_ASSERT (node_p != NULL);

return MEM_CP_GET_POINTER (node_t, node_p->next_cp);
} /* rcs_chunked_list_t::get_next */

/**
* Append new node to end of the list
*
* @return pointer to the new node
*/
rcs_chunked_list_t::node_t*
rcs_chunked_list_t::append_new (void)
{
assert_list_is_correct ();

node_t *node_p = (node_t*) mem_heap_alloc_chunked_block (MEM_HEAP_ALLOC_LONG_TERM);

set_prev (node_p, tail_p);
set_next (node_p, NULL);

if (head_p == NULL)
{
JERRY_ASSERT (tail_p == NULL);

head_p = node_p;
tail_p = node_p;
}
else
{
JERRY_ASSERT (tail_p != NULL);

set_next (tail_p, node_p);

tail_p = node_p;
}

assert_node_is_correct (node_p);

return node_p;
} /* rcs_chunked_list_t::append_new */

/**
* Insert new node after the specified node
*
* @return pointer to the new node
*/
rcs_chunked_list_t::node_t*
rcs_chunked_list_t::insert_new (rcs_chunked_list_t::node_t* after_p) /**< the node to insert the new node after */
{
assert_list_is_correct ();

node_t *node_p = (node_t*) mem_heap_alloc_chunked_block (MEM_HEAP_ALLOC_LONG_TERM);

JERRY_ASSERT (head_p != NULL);
JERRY_ASSERT (tail_p != NULL);
assert_node_is_correct (after_p);

set_next (after_p, node_p);
if (tail_p == after_p)
{
tail_p = node_p;
}

set_prev (node_p, after_p);
set_next (node_p, NULL);

assert_node_is_correct (node_p);

return node_p;
} /* rcs_chunked_list_t::insert_new */

/**
* Remove specified node
*/
void
rcs_chunked_list_t::remove (rcs_chunked_list_t::node_t* node_p) /**< node to remove */
{
JERRY_ASSERT (head_p != NULL);
JERRY_ASSERT (tail_p != NULL);

assert_node_is_correct (node_p);

node_t *prev_node_p, *next_node_p;
prev_node_p = get_prev (node_p);
next_node_p = get_next (node_p);

if (prev_node_p == NULL)
{
JERRY_ASSERT (head_p == node_p);
head_p = next_node_p;
}
else
{
set_next (prev_node_p, next_node_p);
}

if (next_node_p == NULL)
{
JERRY_ASSERT (tail_p == node_p);
tail_p = prev_node_p;
}
else
{
set_prev (next_node_p, prev_node_p);
}

mem_heap_free_block (node_p);

assert_list_is_correct ();
} /* rcs_chunked_list_t::remove */

/**
* Find node containing space, pointed by specified pointer
*
* @return pointer to the node that contains the pointed area
*/
rcs_chunked_list_t::node_t*
rcs_chunked_list_t::get_node_from_pointer (void* ptr) /**< the pointer value */
const
{
node_t *node_p = (node_t*) mem_heap_get_chunked_block_start (ptr);

assert_node_is_correct (node_p);

return node_p;
} /* rcs_chunked_list_t::get_node_from_pointer */

/**
* Get the node's data space
*
* @return pointer to beginning of the node's data space
*/
uint8_t*
rcs_chunked_list_t::get_data_space (rcs_chunked_list_t::node_t* node_p) /**< the node */
const
{
assert_node_is_correct (node_p);

return (uint8_t*) (node_p + 1);
} /* rcs_chunked_list_t::get_data_space */

/**
* Get size of a node's data space
*
* @return size
*/
size_t
rcs_chunked_list_t::get_data_space_size (void)
{
return rcs_chunked_list_t::get_node_size () - sizeof (node_t);
} /* rcs_chunked_list_t::get_data_space_size */

/**
* Set previous node for the specified node
*/
void
rcs_chunked_list_t::set_prev (rcs_chunked_list_t::node_t *node_p, /**< node to set previous for */
rcs_chunked_list_t::node_t *prev_node_p) /**< the previous node */
{
JERRY_ASSERT (node_p != NULL);

MEM_CP_SET_POINTER (node_p->prev_cp, prev_node_p);
} /* rcs_chunked_list_t::set_prev */

/**
* Set next node for the specified node
*/
void
rcs_chunked_list_t::set_next (rcs_chunked_list_t::node_t *node_p, /**< node to set next for */
rcs_chunked_list_t::node_t *next_node_p) /**< the next node */
{
JERRY_ASSERT (node_p != NULL);

MEM_CP_SET_POINTER (node_p->next_cp, next_node_p);
} /* rcs_chunked_list_t::set_next */

/**
* Get size of the node
*
* @return size of node, including header and data space
*/
size_t
rcs_chunked_list_t::get_node_size (void)
{
size_t size = mem_heap_recommend_allocation_size (sizeof (node_t) + 1u);

JERRY_ASSERT (size != 0 && size >= sizeof (node_t));

return size;
} /* rcs_chunked_list_t::get_node_size */

/**
* Assert that the list state is correct
*/
void
rcs_chunked_list_t::assert_list_is_correct (void)
const
{
#ifndef JERRY_NDEBUG
for (node_t *node_iter_p = get_first ();
node_iter_p != NULL;
node_iter_p = get_next (node_iter_p))
{
node_t *prev_node_p = get_prev (node_iter_p);
node_t *next_node_p = get_next (node_iter_p);

JERRY_ASSERT ((node_iter_p == head_p
&& prev_node_p == NULL)
|| (node_iter_p != head_p
&& prev_node_p != NULL
&& get_next (prev_node_p) == node_iter_p));
JERRY_ASSERT ((node_iter_p == tail_p
&& next_node_p == NULL)
|| (node_iter_p != tail_p
&& next_node_p != NULL
&& get_prev (next_node_p) == node_iter_p));
}
#endif /* !JERRY_NDEBUG */
} /* rcs_chunked_list_t::assert_list_is_correct */

/**
* Assert that state of specified node is correct
*/
void
rcs_chunked_list_t::assert_node_is_correct (const rcs_chunked_list_t::node_t* node_p) /**< the node */
const
{
#ifndef JERRY_NDEBUG
JERRY_ASSERT (node_p != NULL);

assert_list_is_correct ();

bool is_in_list = false;
for (node_t *node_iter_p = get_first ();
node_iter_p != NULL;
node_iter_p = get_next (node_iter_p))
{
if (node_iter_p == node_p)
{
is_in_list = true;

break;
}
}

JERRY_ASSERT (is_in_list);
#else /* JERRY_NDEBUG */
(void) node_p;
#endif /* JERRY_NDEBUG */
} /* rcs_chunked_list_t::assert_node_is_correct */
Loading