Storing values in ecma_value_t in unpacked form (type + simple value / pointer to the heap).

This commit is contained in:
Ruben Ayrapetyan
2015-02-03 14:52:37 +03:00
parent f37a5085f6
commit 55caaf7a88
2 changed files with 222 additions and 83 deletions
+5 -14
View File
@@ -31,10 +31,7 @@ JERRY_STATIC_ASSERT (sizeof (ecma_value_packed_t) * JERRY_BITSINBYTE == ECMA_VAL
ecma_number_t* __attribute_pure__ ecma_number_t* __attribute_pure__
ecma_get_number_from_value (const ecma_value_t& value) /**< ecma-value */ ecma_get_number_from_value (const ecma_value_t& value) /**< ecma-value */
{ {
JERRY_ASSERT (ecma_get_value_type_field (value) == ECMA_TYPE_NUMBER); return value.get_number ();
return ECMA_GET_NON_NULL_POINTER (ecma_number_t,
ecma_get_value_value_field (value));
} /* ecma_get_number_from_value */ } /* ecma_get_number_from_value */
/** /**
@@ -45,10 +42,7 @@ ecma_get_number_from_value (const ecma_value_t& value) /**< ecma-value */
ecma_string_t* __attribute_pure__ ecma_string_t* __attribute_pure__
ecma_get_string_from_value (const ecma_value_t& value) /**< ecma-value */ ecma_get_string_from_value (const ecma_value_t& value) /**< ecma-value */
{ {
JERRY_ASSERT (ecma_get_value_type_field (value) == ECMA_TYPE_STRING); return value.get_string ();
return ECMA_GET_NON_NULL_POINTER (ecma_string_t,
ecma_get_value_value_field (value));
} /* ecma_get_string_from_value */ } /* ecma_get_string_from_value */
/** /**
@@ -59,10 +53,7 @@ ecma_get_string_from_value (const ecma_value_t& value) /**< ecma-value */
ecma_object_t* __attribute_pure__ ecma_object_t* __attribute_pure__
ecma_get_object_from_value (const ecma_value_t& value) /**< ecma-value */ ecma_get_object_from_value (const ecma_value_t& value) /**< ecma-value */
{ {
JERRY_ASSERT (ecma_get_value_type_field (value) == ECMA_TYPE_OBJECT); return value.get_object ();
return ECMA_GET_NON_NULL_POINTER (ecma_object_t,
ecma_get_value_value_field (value));
} /* ecma_get_object_from_value */ } /* ecma_get_object_from_value */
/** /**
@@ -243,9 +234,9 @@ ecma_free_completion_value (ecma_completion_value_t& completion_value) /**< comp
} }
case ECMA_COMPLETION_TYPE_EXIT: case ECMA_COMPLETION_TYPE_EXIT:
{ {
ecma_value_t v ((ecma_value_packed_t) completion_value); const ecma_value_t& v = completion_value;
JERRY_ASSERT(ecma_get_value_type_field (v) == ECMA_TYPE_SIMPLE); JERRY_ASSERT (v.is_simple ());
break; break;
} }
+217 -69
View File
@@ -27,6 +27,32 @@
* @{ * @{
*/ */
/**
* Get type field of ecma-value
*
* @return type field
*/
inline ecma_type_t __attribute_pure__ __attribute_always_inline__
ecma_get_value_type_field (ecma_value_packed_t packed_value) /**< packed ecma-value */
{
return (ecma_type_t) jrt_extract_bit_field (packed_value,
ECMA_VALUE_TYPE_POS,
ECMA_VALUE_TYPE_WIDTH);
} /* ecma_get_value_type_field */
/**
* Get value field of ecma-value
*
* @return value field
*/
inline uintptr_t __attribute_pure__ __attribute_always_inline__
ecma_get_value_value_field (ecma_value_packed_t packed_value) /**< packed ecma-value */
{
return (uintptr_t) jrt_extract_bit_field (packed_value,
ECMA_VALUE_VALUE_POS,
ECMA_VALUE_VALUE_WIDTH);
} /* ecma_get_value_value_field */
/** /**
* Description of ecma-value on-stack storage * Description of ecma-value on-stack storage
*/ */
@@ -34,17 +60,9 @@ class ecma_value_t
{ {
public: public:
/* Constructors */ /* Constructors */
__attribute_always_inline__
ecma_value_t (ecma_type_t type, /**< ecma-value type */
uintptr_t value) /**< compressed pointer
* or simple value */
{
_packed = pack (type, value);
} /* ecma_value_t */
__attribute_always_inline__ __attribute_always_inline__
ecma_value_t (ecma_simple_value_t simple_value) ecma_value_t (ecma_simple_value_t simple_value)
: ecma_value_t (ECMA_TYPE_SIMPLE, simple_value) { } : _type (ECMA_TYPE_SIMPLE), _simple_value (simple_value) { }
__attribute_always_inline__ __attribute_always_inline__
ecma_value_t () : ecma_value_t (ECMA_SIMPLE_VALUE_EMPTY) { } ecma_value_t () : ecma_value_t (ECMA_SIMPLE_VALUE_EMPTY) { }
@@ -80,74 +98,209 @@ class ecma_value_t
ecma_value_t& operator = (ecma_value_t &&) = delete; ecma_value_t& operator = (ecma_value_t &&) = delete;
/* Extraction of packed representation */ /* Extraction of packed representation */
__attribute_always_inline__ explicit operator ecma_value_packed_t () const
explicit operator ecma_value_packed_t () const { return _packed; } {
uintptr_t value;
if (_type == ECMA_TYPE_SIMPLE)
{
value = _simple_value;
}
else
{
JERRY_ASSERT (_type == ECMA_TYPE_NUMBER
|| _type == ECMA_TYPE_STRING
|| _type == ECMA_TYPE_OBJECT);
ECMA_SET_NON_NULL_POINTER (value, _value_p);
}
return pack (_type, value);
}
/* Assignment operators */ /* Assignment operators */
__attribute_always_inline__ __attribute_always_inline__
ecma_value_t& operator = (ecma_simple_value_t v) ecma_value_t& operator = (ecma_simple_value_t v)
{ {
_packed = pack (ECMA_TYPE_SIMPLE, v); _type = ECMA_TYPE_SIMPLE;
_simple_value = v;
return *this; return *this;
} }
__attribute_always_inline__
ecma_value_t& operator = (ecma_number_t* num_p) ecma_value_t& operator = (ecma_number_t* num_p)
{ {
JERRY_ASSERT(num_p != NULL); JERRY_ASSERT(num_p != NULL);
uint16_t num_cp; _type = ECMA_TYPE_NUMBER;
ECMA_SET_NON_NULL_POINTER (num_cp, num_p); _value_p = num_p;
_packed = pack (ECMA_TYPE_NUMBER, num_cp);
return *this; return *this;
} }
__attribute_always_inline__
ecma_value_t& operator = (ecma_string_t* str_p) ecma_value_t& operator = (ecma_string_t* str_p)
{ {
JERRY_ASSERT(str_p != NULL); JERRY_ASSERT(str_p != NULL);
uint16_t str_cp; _type = ECMA_TYPE_STRING;
ECMA_SET_NON_NULL_POINTER (str_cp, str_p); _value_p = str_p;
_packed = pack (ECMA_TYPE_STRING, str_cp);
return *this; return *this;
} }
__attribute_always_inline__
ecma_value_t& operator = (ecma_object_t *obj_p) ecma_value_t& operator = (ecma_object_t *obj_p)
{ {
JERRY_ASSERT(obj_p != NULL); JERRY_ASSERT(obj_p != NULL);
uint16_t obj_cp; _type = ECMA_TYPE_OBJECT;
ECMA_SET_NON_NULL_POINTER (obj_cp, obj_p); _value_p = obj_p;
_packed = pack (ECMA_TYPE_OBJECT, obj_cp);
return *this; return *this;
} }
__attribute_always_inline__
ecma_value_t& operator = (ecma_value_packed_t packed) ecma_value_t& operator = (ecma_value_packed_t packed)
{ {
_packed = packed; _type = ecma_get_value_type_field (packed);
uintptr_t value = ecma_get_value_value_field (packed);
if (_type == ECMA_TYPE_SIMPLE)
{
_simple_value = (ecma_simple_value_t) value;
}
else
{
JERRY_ASSERT (_type == ECMA_TYPE_NUMBER
|| _type == ECMA_TYPE_STRING
|| _type == ECMA_TYPE_OBJECT);
_value_p = ECMA_GET_NON_NULL_POINTER (void, value);
}
return *this; return *this;
} }
__attribute_always_inline__
ecma_value_t& operator = (const ecma_value_t &v) ecma_value_t& operator = (const ecma_value_t &v)
{ {
this->_packed = v._packed; _type = v._type;
if (_type == ECMA_TYPE_SIMPLE)
{
_simple_value = v._simple_value;
}
else
{
JERRY_ASSERT (_type == ECMA_TYPE_NUMBER
|| _type == ECMA_TYPE_STRING
|| _type == ECMA_TYPE_OBJECT);
_value_p = v._value_p;
}
return *this; return *this;
} }
private:
/* Getters */
__attribute_always_inline__
ecma_type_t get_type (void) const
{
return _type;
}
__attribute_always_inline__
bool is_simple (void) const
{
return (_type == ECMA_TYPE_SIMPLE);
}
__attribute_always_inline__
bool is_simple (ecma_simple_value_t simple_value) const
{
return (is_simple () && _simple_value == simple_value);
}
__attribute_always_inline__
bool is_empty () const
{
return is_simple (ECMA_SIMPLE_VALUE_EMPTY);
}
__attribute_always_inline__
bool is_undefined () const
{
return is_simple (ECMA_SIMPLE_VALUE_UNDEFINED);
}
__attribute_always_inline__
bool is_null () const
{
return is_simple (ECMA_SIMPLE_VALUE_NULL);
}
__attribute_always_inline__
bool is_boolean () const
{
return (is_simple (ECMA_SIMPLE_VALUE_TRUE) || is_simple (ECMA_SIMPLE_VALUE_FALSE));
}
__attribute_always_inline__
bool is_true () const
{
return is_simple (ECMA_SIMPLE_VALUE_TRUE);
}
__attribute_always_inline__
bool is_number () const
{
return (_type == ECMA_TYPE_NUMBER);
}
__attribute_always_inline__
bool is_string () const
{
return (_type == ECMA_TYPE_STRING);
}
__attribute_always_inline__
bool is_object () const
{
return (_type == ECMA_TYPE_OBJECT);
}
__attribute_always_inline__
ecma_number_t* get_number () const
{
JERRY_ASSERT (_type == ECMA_TYPE_NUMBER);
return static_cast<ecma_number_t*> (_value_p);
}
__attribute_always_inline__
ecma_string_t* get_string () const
{
JERRY_ASSERT (_type == ECMA_TYPE_STRING);
return static_cast<ecma_string_t*> (_value_p);
}
__attribute_always_inline__
ecma_object_t* get_object () const
{
JERRY_ASSERT (_type == ECMA_TYPE_OBJECT);
return static_cast<ecma_object_t*> (_value_p);
}
private:
/** /**
* Combining type and value fields to packed representation * Combining type and value fields to packed representation
* *
* @return packed ecma-value representation * @return packed ecma-value representation
*/ */
__attribute_always_inline__ static __attribute_always_inline__
ecma_value_packed_t pack (ecma_type_t type, ecma_value_packed_t pack (ecma_type_t type,
uintptr_t value) uintptr_t value)
{ {
@@ -166,7 +319,13 @@ class ecma_value_t
return packed; return packed;
} }
ecma_value_packed_t _packed; /**< packed value representation */ ecma_type_t _type;
union
{
ecma_simple_value_t _simple_value;
void* _value_p;
};
}; };
/** /**
@@ -178,16 +337,19 @@ class ecma_completion_value_t : public ecma_value_t
{ {
public: public:
/* Constructors */ /* Constructors */
__attribute_always_inline__
ecma_completion_value_t () ecma_completion_value_t ()
: ecma_value_t (), : ecma_value_t (),
_type (ECMA_COMPLETION_TYPE_NORMAL) { } _type (ECMA_COMPLETION_TYPE_NORMAL) { }
__attribute_always_inline__
ecma_completion_value_t (ecma_completion_type_t type, ecma_completion_value_t (ecma_completion_type_t type,
const ecma_value_t &value) const ecma_value_t &value)
: ecma_value_t ((ecma_value_packed_t) value), :
_type (type) { } _type (type) { *this = value; }
/* Assignment operators */ /* Assignment operators */
__attribute_always_inline__
ecma_completion_value_t & operator = (ecma_completion_type_t type) ecma_completion_value_t & operator = (ecma_completion_type_t type)
{ {
_type = type; _type = type;
@@ -195,19 +357,28 @@ class ecma_completion_value_t : public ecma_value_t
return *this; return *this;
} }
__attribute_always_inline__
ecma_completion_value_t & operator = (const ecma_value_t& value) ecma_completion_value_t & operator = (const ecma_value_t& value)
{ {
*static_cast<ecma_value_t*> (this) = (ecma_value_packed_t) value; *static_cast<ecma_value_t*> (this) = value;
return *this; return *this;
} }
/* Completion type extraction */ /* Completion type extraction */
__attribute_always_inline__
explicit operator ecma_completion_type_t () const explicit operator ecma_completion_type_t () const
{ {
return _type; return _type;
} }
__attribute_always_inline__
ecma_completion_value_t& operator = (const ecma_completion_value_t &) = default;
ecma_completion_value_t (const ecma_completion_value_t&) = delete;
ecma_completion_value_t (ecma_completion_value_t&) = delete;
ecma_completion_value_t (ecma_completion_value_t&&) = delete;
ecma_completion_value_t& operator = (ecma_completion_value_t &&) = delete;
private: private:
ecma_completion_type_t _type; /**< completion type */ ecma_completion_type_t _type; /**< completion type */
}; };
@@ -220,24 +391,9 @@ class ecma_completion_value_t : public ecma_value_t
inline ecma_type_t __attribute_pure__ __attribute_always_inline__ inline ecma_type_t __attribute_pure__ __attribute_always_inline__
ecma_get_value_type_field (const ecma_value_t& value) /**< ecma-value */ ecma_get_value_type_field (const ecma_value_t& value) /**< ecma-value */
{ {
return (ecma_type_t) jrt_extract_bit_field ((ecma_value_packed_t) value, return value.get_type ();
ECMA_VALUE_TYPE_POS,
ECMA_VALUE_TYPE_WIDTH);
} /* ecma_get_value_type_field */ } /* ecma_get_value_type_field */
/**
* Get value field of ecma-value
*
* @return value field
*/
inline uintptr_t __attribute_pure__ __attribute_always_inline__
ecma_get_value_value_field (const ecma_value_t& value) /**< ecma-value */
{
return (uintptr_t) jrt_extract_bit_field ((ecma_value_packed_t) value,
ECMA_VALUE_VALUE_POS,
ECMA_VALUE_VALUE_WIDTH);
} /* ecma_get_value_value_field */
/** /**
* Check if the value is empty. * Check if the value is empty.
* *
@@ -247,8 +403,7 @@ ecma_get_value_value_field (const ecma_value_t& value) /**< ecma-value */
inline bool __attribute_pure__ __attribute_always_inline__ inline bool __attribute_pure__ __attribute_always_inline__
ecma_is_value_empty (const ecma_value_t& value) /**< ecma-value */ ecma_is_value_empty (const ecma_value_t& value) /**< ecma-value */
{ {
return (ecma_get_value_type_field (value) == ECMA_TYPE_SIMPLE return value.is_empty ();
&& ecma_get_value_value_field (value) == ECMA_SIMPLE_VALUE_EMPTY);
} /* ecma_is_value_empty */ } /* ecma_is_value_empty */
/** /**
@@ -260,8 +415,7 @@ ecma_is_value_empty (const ecma_value_t& value) /**< ecma-value */
inline bool __attribute_pure__ __attribute_always_inline__ inline bool __attribute_pure__ __attribute_always_inline__
ecma_is_value_undefined (const ecma_value_t& value) /**< ecma-value */ ecma_is_value_undefined (const ecma_value_t& value) /**< ecma-value */
{ {
return (ecma_get_value_type_field (value) == ECMA_TYPE_SIMPLE return value.is_undefined ();
&& ecma_get_value_value_field (value) == ECMA_SIMPLE_VALUE_UNDEFINED);
} /* ecma_is_value_undefined */ } /* ecma_is_value_undefined */
/** /**
@@ -273,8 +427,7 @@ ecma_is_value_undefined (const ecma_value_t& value) /**< ecma-value */
inline bool __attribute_pure__ __attribute_always_inline__ inline bool __attribute_pure__ __attribute_always_inline__
ecma_is_value_null (const ecma_value_t& value) /**< ecma-value */ ecma_is_value_null (const ecma_value_t& value) /**< ecma-value */
{ {
return (ecma_get_value_type_field (value) == ECMA_TYPE_SIMPLE return value.is_null ();
&& ecma_get_value_value_field (value) == ECMA_SIMPLE_VALUE_NULL);
} /* ecma_is_value_null */ } /* ecma_is_value_null */
/** /**
@@ -286,9 +439,7 @@ ecma_is_value_null (const ecma_value_t& value) /**< ecma-value */
inline bool __attribute_pure__ __attribute_always_inline__ inline bool __attribute_pure__ __attribute_always_inline__
ecma_is_value_boolean (const ecma_value_t& value) /**< ecma-value */ ecma_is_value_boolean (const ecma_value_t& value) /**< ecma-value */
{ {
return (ecma_get_value_type_field (value) == ECMA_TYPE_SIMPLE return value.is_boolean ();
&& (ecma_get_value_value_field (value) == ECMA_SIMPLE_VALUE_TRUE
|| ecma_get_value_value_field (value) == ECMA_SIMPLE_VALUE_FALSE));
} /* ecma_is_value_boolean */ } /* ecma_is_value_boolean */
/** /**
@@ -303,8 +454,7 @@ ecma_is_value_boolean (const ecma_value_t& value) /**< ecma-value */
inline bool __attribute_pure__ __attribute_always_inline__ inline bool __attribute_pure__ __attribute_always_inline__
ecma_is_value_true (const ecma_value_t& value) /**< ecma-value */ ecma_is_value_true (const ecma_value_t& value) /**< ecma-value */
{ {
return (ecma_get_value_type_field (value) == ECMA_TYPE_SIMPLE return value.is_true ();
&& ecma_get_value_value_field (value) == ECMA_SIMPLE_VALUE_TRUE);
} /* ecma_is_value_true */ } /* ecma_is_value_true */
/** /**
@@ -316,7 +466,7 @@ ecma_is_value_true (const ecma_value_t& value) /**< ecma-value */
inline bool __attribute_pure__ __attribute_always_inline__ inline bool __attribute_pure__ __attribute_always_inline__
ecma_is_value_number (const ecma_value_t& value) /**< ecma-value */ ecma_is_value_number (const ecma_value_t& value) /**< ecma-value */
{ {
return (ecma_get_value_type_field (value) == ECMA_TYPE_NUMBER); return value.is_number ();
} /* ecma_is_value_number */ } /* ecma_is_value_number */
/** /**
@@ -328,7 +478,7 @@ ecma_is_value_number (const ecma_value_t& value) /**< ecma-value */
inline bool __attribute_pure__ __attribute_always_inline__ inline bool __attribute_pure__ __attribute_always_inline__
ecma_is_value_string (const ecma_value_t& value) /**< ecma-value */ ecma_is_value_string (const ecma_value_t& value) /**< ecma-value */
{ {
return (ecma_get_value_type_field (value) == ECMA_TYPE_STRING); return value.is_string ();
} /* ecma_is_value_string */ } /* ecma_is_value_string */
/** /**
@@ -340,7 +490,7 @@ ecma_is_value_string (const ecma_value_t& value) /**< ecma-value */
inline bool __attribute_pure__ __attribute_always_inline__ inline bool __attribute_pure__ __attribute_always_inline__
ecma_is_value_object (const ecma_value_t& value) /**< ecma-value */ ecma_is_value_object (const ecma_value_t& value) /**< ecma-value */
{ {
return (ecma_get_value_type_field (value) == ECMA_TYPE_OBJECT); return value.is_object ();
} /* ecma_is_value_object */ } /* ecma_is_value_object */
extern ecma_number_t* __attribute_pure__ ecma_get_number_from_value (const ecma_value_t& value); extern ecma_number_t* __attribute_pure__ ecma_get_number_from_value (const ecma_value_t& value);
@@ -500,7 +650,7 @@ ecma_get_completion_value_value (ecma_value_t &ret, /**< out: ecma-value */
JERRY_ASSERT (is_type_ok); JERRY_ASSERT (is_type_ok);
ret = (ecma_value_packed_t) completion_value; ret = completion_value;
} /* ecma_get_completion_value_value */ } /* ecma_get_completion_value_value */
extern void ecma_copy_completion_value (ecma_completion_value_t& ret_value, const ecma_completion_value_t& value); extern void ecma_copy_completion_value (ecma_completion_value_t& ret_value, const ecma_completion_value_t& value);
@@ -560,7 +710,7 @@ ecma_is_completion_value_exit (const ecma_completion_value_t& value) /**< comple
if ((ecma_completion_type_t) value == ECMA_COMPLETION_TYPE_EXIT) if ((ecma_completion_type_t) value == ECMA_COMPLETION_TYPE_EXIT)
{ {
#ifndef JERRY_NDEBUG #ifndef JERRY_NDEBUG
ecma_value_t v ((ecma_value_packed_t) value); const ecma_value_t& v = value;
JERRY_ASSERT (ecma_is_value_boolean (v)); JERRY_ASSERT (ecma_is_value_boolean (v));
#endif /* !JERRY_NDEBUG */ #endif /* !JERRY_NDEBUG */
@@ -585,7 +735,7 @@ ecma_is_completion_value_meta (const ecma_completion_value_t& value) /**< comple
if ((ecma_completion_type_t) value == ECMA_COMPLETION_TYPE_META) if ((ecma_completion_type_t) value == ECMA_COMPLETION_TYPE_META)
{ {
#ifndef JERRY_NDEBUG #ifndef JERRY_NDEBUG
ecma_value_t v ((ecma_value_packed_t) value); const ecma_value_t& v = value;
JERRY_ASSERT (ecma_is_value_empty (v)); JERRY_ASSERT (ecma_is_value_empty (v));
#endif /* !JERRY_NDEBUG */ #endif /* !JERRY_NDEBUG */
@@ -610,9 +760,7 @@ ecma_is_completion_value_normal_simple_value (const ecma_completion_value_t& val
ecma_simple_value_t simple_value) /**< simple value to check ecma_simple_value_t simple_value) /**< simple value to check
for equality with */ for equality with */
{ {
return (ecma_is_completion_value_normal (value) return (ecma_is_completion_value_normal (value) && value.is_simple (simple_value));
&& ecma_get_value_type_field (value) == ECMA_TYPE_SIMPLE
&& ecma_get_value_value_field (value) == simple_value);
} /* ecma_is_completion_value_normal_simple_value */ } /* ecma_is_completion_value_normal_simple_value */
/** /**
@@ -653,7 +801,7 @@ ecma_is_completion_value_empty (const ecma_completion_value_t& value) /**< compl
{ {
if (ecma_is_completion_value_normal (value)) if (ecma_is_completion_value_normal (value))
{ {
ecma_value_t v ((ecma_value_packed_t) value); const ecma_value_t& v = value;
return ecma_is_value_empty (v); return ecma_is_value_empty (v);
} }