Skip to content

Commit

Permalink
Merge pull request #456 from ArkScript-lang/optimize/vm
Browse files Browse the repository at this point in the history
Optimize/vm
  • Loading branch information
SuperFola authored Apr 20, 2024
2 parents 0b03c45 + 002d567 commit 6aa6d35
Show file tree
Hide file tree
Showing 14 changed files with 107 additions and 533 deletions.
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ repos:
rev: '336fdd7c3cab698ead0b1c95157b9e74d3906b62'
hooks:
- id: cppcheck
args: [ "--platform=unix64", "--inline-suppr", "--suppressions-list=cppcheck-suppressions.txt" ]
args: [ "--platform=unix64", "--language=c++", "--inline-suppr", "--suppressions-list=cppcheck-suppressions.txt" ]
- repo: https://github.com/compilerla/conventional-pre-commit
rev: 'v3.2.0'
hooks:
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
- `Utils::digPlaces` and `Utils::decPlaces` got removed as they were no longer needed
- removed deprecated code (`list:removeAt`, `ark` executable now replaced by `arkscript`)
- removed `VM::getUserPointer` and `VM::setUserPointer`
- removed `ARK_PROFILER_COUNT` define

## [3.5.0] - 2023-02-19
### Added
Expand Down
5 changes: 0 additions & 5 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -145,18 +145,13 @@ target_compile_definitions(ArkReactor PRIVATE ARK_EXPORT)

option(ARK_BUILD_EXE "Build a standalone arkscript executable" Off)
option(ARK_ENABLE_SYSTEM "Enable sys:exec" On) # enable use of (sys:exec "command here")
option(ARK_PROFILER_COUNT "Enable creations/copies/moves counting on the Value" Off)
option(ARK_PROFILER_MIPS "Enable MIPS calculation" Off)
option(ARK_NO_STDLIB "Do not install the standard library with the Ark library" Off)
option(ARK_BUILD_MODULES "Build the std library modules or not" Off)
option(ARK_SANITIZERS "Enable ASAN and UBSAN" Off)
option(ARK_TESTS "Build ArkScript unit tests" Off)
option(ARK_BENCHMARKS "Build ArkScript benchmarks" Off)

if (ARK_PROFILER_COUNT)
target_compile_definitions(ArkReactor PRIVATE -DARK_PROFILER_COUNT)
endif ()

if (ARK_ENABLE_SYSTEM)
target_compile_definitions(ArkReactor PRIVATE -DARK_ENABLE_SYSTEM)
endif ()
Expand Down
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,6 @@ Different CMake switches are available to customize the build:

* `-DARK_BUILD_EXE` to generate an executable, defaults to Off, building a shared library only
* `-DARK_ENABLE_SYSTEM` to enable `sys:exec` (execute shell commands without restrictions), defaults to On
* `-DARK_PROFILER_COUNT` to count every creation/copy/move of the internal value type, defaults to Off
* `-DARK_PROFILER_MIPS` to enable the MIPS counting, defaults to Off
* `-DARK_NO_STDLIB` to avoid the installation of the ArkScript standard library
* `-DARK_BUILD_MODULES` to trigger the modules build
Expand Down
241 changes: 41 additions & 200 deletions include/Ark/VM/Value.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@
* @file Value.hpp
* @author Default value type handled by the virtual machine
* @brief
* @version 0.3
* @date 2020-10-27
* @version 1.0
* @date 2024-04-20
*
* @copyright Copyright (c) 2020-2021
* @copyright Copyright (c) 2020-2024
*
*/

Expand All @@ -14,7 +14,7 @@

#include <vector>
#include <variant>
#include <string> // for conversions
#include <string>
#include <cinttypes>
#include <iostream>
#include <memory>
Expand All @@ -30,10 +30,10 @@ namespace Ark
{
class VM;

// Note from the creator: we can have at most 0b01111111 (127) different types
// because type index is stored on the 7 right most bits of a uint8_t in the class Value.
// Order is also important because we are doing some optimizations to check ranges
// of types based on their integer values.
// Note: we can have at most 0x7f (127) different types
// because type index is stored on the 7 right most bits of a uint8_t in the class Value.
// Order is also important because we are doing some optimizations to check ranges
// of types based on their integer values.
enum class ValueType
{
List = 0,
Expand All @@ -51,7 +51,7 @@ namespace Ark
Reference = 11,
InstPtr = 12,

Any = 99
Any = 99 ///< Used only for typechecking
};

const std::array<std::string, 13> types_to_str = {
Expand All @@ -61,15 +61,10 @@ namespace Ark
"InstPtr"
};

// for debugging purposes only
#ifdef ARK_PROFILER_COUNT
extern unsigned value_creations, value_copies, value_moves;
#endif

class ARK_API Value
{
public:
using ProcType = Value (*)(std::vector<Value>&, VM*); // std::function<Value (std::vector<Value>&, VM*)>
using ProcType = Value (*)(std::vector<Value>&, VM*);
using Iterator = std::vector<Value>::iterator;
using ConstIterator = std::vector<Value>::const_iterator;

Expand Down Expand Up @@ -110,162 +105,37 @@ namespace Ark
template <typename T>
Value(ValueType type, T&& value) noexcept :
m_const_type(static_cast<uint8_t>(type)),
m_value(std::move(value))
m_value(value)
{}

#ifdef ARK_PROFILER_COUNT
Value(const Value& val) noexcept;
Value(Value&& other) noexcept;
Value& operator=(const Value& other) noexcept;
#endif

/**
* @brief Construct a new Value object as a Number
*
* @param value
*/
explicit Value(int value) noexcept;

/**
* @brief Construct a new Value object as a Number
*
* @param value
*/
explicit Value(float value) noexcept;

/**
* @brief Construct a new Value object as a Number
*
* @param value
*/
explicit Value(double value) noexcept;

/**
* @brief Construct a new Value object as a String
*
* @param value
*/
explicit Value(const std::string& value) noexcept;

/**
* @brief Construct a new Value object as a String
*
* @param value
*/
explicit Value(const char* value) noexcept;

/**
* @brief Construct a new Value object as a Function
*
* @param value
*/
explicit Value(internal::PageAddr_t value) noexcept;

/**
* @brief Construct a new Value object from a C++ function
*
* @param value
*/
explicit Value(Value::ProcType value) noexcept;

/**
* @brief Construct a new Value object as a List
*
* @param value
*/
explicit Value(std::vector<Value>&& value) noexcept;

/**
* @brief Construct a new Value object as a Closure
*
* @param value
*/
explicit Value(internal::Closure&& value) noexcept;

/**
* @brief Construct a new Value object as a UserType
*
* @param value
*/
explicit Value(UserType&& value) noexcept;

/**
* @brief Construct a new Value object as a reference to an internal object
*
* @param ref
*/
explicit Value(Value* ref) noexcept;

/**
* @brief Return the value type
*
* @return ValueType
*/
inline ValueType valueType() const noexcept;

/**
* @brief Check if a function is held
*
* @return true on success
* @return false on failure
*/
inline bool isFunction() const noexcept;

/**
* @brief Return the stored number
*
* @return double
*/
inline double number() const;

/**
* @brief Return the stored string
*
* @return const std::string&
*/
inline const std::string& string() const;

/**
* @brief Return the stored list
*
* @return const std::vector<Value>&
*/
inline const std::vector<Value>& constList() const;

/**
* @brief Return the stored user type
*
* @return const UserType&
*/
inline const UserType& usertype() const;

/**
* @brief Return the stored list as a reference
*
* @return std::vector<Value>&
*/
std::vector<Value>& list();

/**
* @brief Return the stored string as a reference
*
* @return std::string&
*/
std::string& stringRef();

/**
* @brief Return the stored user type as a reference
*
* @return UserType&
*/
UserType& usertypeRef();
[[nodiscard]] inline ValueType valueType() const noexcept { return static_cast<ValueType>(type_num()); }
[[nodiscard]] inline bool isFunction() const noexcept
{
auto type = valueType();
return type == ValueType::PageAddr || type == ValueType::Closure || type == ValueType::CProc ||
(type == ValueType::Reference && reference()->isFunction());
}

/**
* @brief Return the stored internal object reference
*
* @return Value*
*/
Value* reference() const;
[[nodiscard]] inline double number() const { return std::get<double>(m_value); }
[[nodiscard]] inline const std::string& string() const { return std::get<std::string>(m_value); }
[[nodiscard]] inline const std::vector<Value>& constList() const { return std::get<std::vector<Value>>(m_value); }
[[nodiscard]] inline const UserType& usertype() const { return std::get<UserType>(m_value); }
[[nodiscard]] inline std::vector<Value>& list() { return std::get<std::vector<Value>>(m_value); }
[[nodiscard]] inline std::string& stringRef() { return std::get<std::string>(m_value); }
[[nodiscard]] inline UserType& usertypeRef() { return std::get<UserType>(m_value); }
[[nodiscard]] inline Value* reference() const { return std::get<Value*>(m_value); }

/**
* @brief Add an element to the list held by the value (if the value type is set to list)
Expand Down Expand Up @@ -293,50 +163,21 @@ namespace Ark
uint8_t m_const_type; ///< First bit if for constness, right most bits are for type
Value_t m_value;

// private getters only for the virtual machine

/**
* @brief Return the page address held by the value
*
* @return internal::PageAddr_t
*/
inline internal::PageAddr_t pageAddr() const;

/**
* @brief Return the C Function held by the value
*
* @return const ProcType&
*/
inline const ProcType& proc() const;

/**
* @brief Return the closure held by the value
*
* @return const internal::Closure&
*/
inline const internal::Closure& closure() const;

/**
* @brief Return a reference to the closure held by the value
*
* @return internal::Closure&
*/
internal::Closure& refClosure();

/**
* @brief Check if the value is const or not
*
* @return true
* @return false
*/
inline bool isConst() const noexcept;

/**
* @brief Set the Const object
*
* @param value
*/
inline void setConst(bool value) noexcept;
[[nodiscard]] inline constexpr uint8_t type_num() const noexcept { return m_const_type & 0x7f; }

[[nodiscard]] inline internal::PageAddr_t pageAddr() const { return std::get<internal::PageAddr_t>(m_value); }
[[nodiscard]] inline const ProcType& proc() const { return std::get<Value::ProcType>(m_value); }
[[nodiscard]] inline const internal::Closure& closure() const { return std::get<internal::Closure>(m_value); }
[[nodiscard]] inline internal::Closure& refClosure() { return std::get<internal::Closure>(m_value); }

[[nodiscard]] inline bool isConst() const noexcept { return m_const_type & (1 << 7); }
inline void setConst(bool value) noexcept
{
if (value)
m_const_type |= 1 << 7;
else
m_const_type = type_num();
}
};

#include "inline/Value.inl"
Expand Down
Loading

0 comments on commit 6aa6d35

Please sign in to comment.