mirror of
https://github.com/Samsung/escargot.git
synced 2026-06-22 10:01:50 +00:00
Allow to save Int32 convertible double value as double in Value for performance
Signed-off-by: Seonghyun Kim <sh8281.kim@samsung.com>
This commit is contained in:
parent
3631ae6097
commit
9e667ccdd2
6 changed files with 73 additions and 25 deletions
|
|
@ -64,13 +64,13 @@ Value builtinArrayConstructor(ExecutionState& state, Value thisValue, size_t arg
|
|||
ArrayObject* array = new ArrayObject(state, proto, size);
|
||||
|
||||
if (interpretArgumentsAsElements) {
|
||||
Value val = argv[0];
|
||||
if (argc > 1 || !val.isNumber()) {
|
||||
if (argc > 1 || !argv[0].isNumber()) {
|
||||
if (array->isFastModeArray()) {
|
||||
for (size_t idx = 0; idx < argc; idx++) {
|
||||
array->m_fastModeData[idx] = argv[idx];
|
||||
}
|
||||
} else {
|
||||
Value val = argv[0];
|
||||
for (size_t idx = 0; idx < argc; idx++) {
|
||||
array->defineOwnProperty(state, ObjectPropertyName(state, idx), ObjectPropertyDescriptor(val, ObjectPropertyDescriptor::AllPresent));
|
||||
val = argv[idx + 1];
|
||||
|
|
|
|||
|
|
@ -258,7 +258,8 @@ Value ByteCodeInterpreter::interpret(ExecutionState* state, ByteCodeBlock* byteC
|
|||
ret = Value(Value::EncodeAsDouble, (double)a + (double)b);
|
||||
}
|
||||
} else if (v0.isNumber() && v1.isNumber()) {
|
||||
ret = Value(v0.asNumber() + v1.asNumber());
|
||||
// most cases are double
|
||||
ret = Value(Value::EncodeAsDouble, v0.asNumber() + v1.asNumber());
|
||||
} else {
|
||||
ret = plusSlowCase(*state, v0, v1);
|
||||
}
|
||||
|
|
@ -284,7 +285,8 @@ Value ByteCodeInterpreter::interpret(ExecutionState* state, ByteCodeBlock* byteC
|
|||
ret = Value(Value::EncodeAsDouble, (double)a - (double)b);
|
||||
}
|
||||
} else if (LIKELY(left.isNumber() && right.isNumber())) {
|
||||
ret = Value(left.asNumber() - right.asNumber());
|
||||
// most cases are double
|
||||
ret = Value(Value::EncodeAsDouble, left.asNumber() - right.asNumber());
|
||||
} else {
|
||||
ret = minusSlowCase(*state, left, right);
|
||||
}
|
||||
|
|
@ -314,7 +316,8 @@ Value ByteCodeInterpreter::interpret(ExecutionState* state, ByteCodeBlock* byteC
|
|||
}
|
||||
}
|
||||
} else if (LIKELY(left.isNumber() && right.isNumber())) {
|
||||
ret = Value(left.asNumber() * right.asNumber());
|
||||
// most cases are double
|
||||
ret = Value(Value::EncodeAsDouble, left.asNumber() * right.asNumber());
|
||||
} else {
|
||||
ret = multiplySlowCase(*state, left, right);
|
||||
}
|
||||
|
|
@ -330,7 +333,8 @@ Value ByteCodeInterpreter::interpret(ExecutionState* state, ByteCodeBlock* byteC
|
|||
const Value& right = registerFile[code->m_srcIndex1];
|
||||
Value& ret = registerFile[code->m_dstIndex];
|
||||
if (LIKELY(left.isNumber() && right.isNumber())) {
|
||||
ret = Value(left.asNumber() / right.asNumber());
|
||||
// most cases are double
|
||||
ret = Value(Value::EncodeAsDouble, left.asNumber() / right.asNumber());
|
||||
} else {
|
||||
ret = divisionSlowCase(*state, left, right);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -335,7 +335,7 @@ void ArgumentsObject::setIndexedPropertyValueQuickly(ExecutionState& state, size
|
|||
ASSERT(m_targetRecord != nullptr);
|
||||
ArgumentsObjectNativeSetter(state, this, value, m_targetRecord, m_sourceFunctionObject->interpretedCodeBlock(), m_parameterMap[index].second);
|
||||
} else {
|
||||
return m_parameterMap[index].first = value;
|
||||
m_parameterMap[index].first = value;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -91,6 +91,26 @@ Context::Context(VMInstance* instance)
|
|||
ExecutionState stateForInit(this);
|
||||
m_globalObjectProxy = m_globalObject = new GlobalObject(stateForInit);
|
||||
m_globalObject->initializeBuiltins(stateForInit);
|
||||
|
||||
#if !defined(NDEBUG)
|
||||
// Int32 convertible double value test
|
||||
Value v(Value::EncodeAsDouble, 2.0);
|
||||
ASSERT(v.isDouble());
|
||||
ASSERT(v.isNumber());
|
||||
ASSERT(v.isInteger(stateForInit));
|
||||
ASSERT(v.toIndex(stateForInit) == 2);
|
||||
ASSERT(v.toIndex32(stateForInit) == 2);
|
||||
ASSERT(v.toInt32(stateForInit) == 2);
|
||||
ASSERT(v.toInteger(stateForInit) == 2);
|
||||
ASSERT(v.toLength(stateForInit) == 2);
|
||||
ASSERT(v.toNumber(stateForInit) == 2);
|
||||
ASSERT(v.toNumeric(stateForInit).first.asDouble() == 2);
|
||||
ASSERT(v.toPropertyKey(stateForInit).toIndex(stateForInit) == 2);
|
||||
ASSERT(v.tryToUseAsIndex(stateForInit) == 2);
|
||||
ASSERT(v.tryToUseAsIndex32(stateForInit) == 2);
|
||||
ASSERT(v.equalsTo(stateForInit, Value(2)));
|
||||
ASSERT(v.abstractEqualsTo(stateForInit, Value(2)));
|
||||
#endif
|
||||
}
|
||||
|
||||
void Context::throwException(ExecutionState& state, const Value& exception)
|
||||
|
|
|
|||
|
|
@ -326,10 +326,11 @@ public:
|
|||
return operator Escargot::Value().toUint32(state);
|
||||
}
|
||||
|
||||
void operator=(PointerValue* from)
|
||||
const EncodedValue& operator=(PointerValue* from)
|
||||
{
|
||||
ASSERT(from);
|
||||
m_data.payload = (intptr_t)from;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool operator==(const EncodedValue& other) const
|
||||
|
|
@ -337,35 +338,39 @@ public:
|
|||
return m_data.payload == other.payload();
|
||||
}
|
||||
|
||||
ALWAYS_INLINE void operator=(const Value& from)
|
||||
ALWAYS_INLINE const EncodedValue& operator=(const Value& from)
|
||||
{
|
||||
if (from.isPointerValue()) {
|
||||
#ifdef ESCARGOT_32
|
||||
ASSERT(!from.isEmpty());
|
||||
#endif
|
||||
m_data.payload = (intptr_t)from.asPointerValue();
|
||||
return;
|
||||
return *this;
|
||||
}
|
||||
|
||||
int32_t i32;
|
||||
if (from.isInt32() && EncodedValueImpl::PlatformSmiTagging::IsValidSmi(i32 = from.asInt32())) {
|
||||
m_data.payload = EncodedValueImpl::PlatformSmiTagging::IntToSmi(i32);
|
||||
return;
|
||||
return *this;
|
||||
}
|
||||
|
||||
if (from.isNumber()) {
|
||||
Value mutableFrom(from);
|
||||
if (UNLIKELY(Value::isInt32ConvertibleDouble(mutableFrom.asNumber(), i32))) {
|
||||
mutableFrom = Value(i32);
|
||||
}
|
||||
intptr_t payload = m_data.payload;
|
||||
|
||||
if (!HAS_SMI_TAG(payload) && ((size_t)payload > (size_t)ValueLast)) {
|
||||
void* v = (void*)payload;
|
||||
if (readPointerIsNumberEncodedValue(v)) {
|
||||
((NumberInEncodedValue*)m_data.payload)->setValue(from);
|
||||
return;
|
||||
((NumberInEncodedValue*)m_data.payload)->setValue(mutableFrom);
|
||||
return *this;
|
||||
}
|
||||
}
|
||||
m_data.payload = reinterpret_cast<intptr_t>(new NumberInEncodedValue(from));
|
||||
m_data.payload = reinterpret_cast<intptr_t>(new NumberInEncodedValue(mutableFrom));
|
||||
ASSERT(readPointerIsNumberEncodedValue((void*)m_data.payload));
|
||||
return;
|
||||
return *this;
|
||||
}
|
||||
|
||||
#ifdef ESCARGOT_32
|
||||
|
|
@ -373,6 +378,7 @@ public:
|
|||
#else
|
||||
m_data.payload = from.payload();
|
||||
#endif
|
||||
return *this;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
|
@ -394,7 +400,11 @@ protected:
|
|||
if (from.isInt32() && EncodedValueImpl::PlatformSmiTagging::IsValidSmi(i32 = from.asInt32())) {
|
||||
m_data.payload = EncodedValueImpl::PlatformSmiTagging::IntToSmi(i32);
|
||||
} else if (from.isNumber()) {
|
||||
m_data.payload = reinterpret_cast<intptr_t>(new NumberInEncodedValue(from));
|
||||
if (UNLIKELY(Value::isInt32ConvertibleDouble(from.asNumber(), i32) && EncodedValueImpl::PlatformSmiTagging::IsValidSmi(i32))) {
|
||||
m_data.payload = EncodedValueImpl::PlatformSmiTagging::IntToSmi(i32);
|
||||
} else {
|
||||
m_data.payload = reinterpret_cast<intptr_t>(new NumberInEncodedValue(from));
|
||||
}
|
||||
} else {
|
||||
#ifdef ESCARGOT_32
|
||||
m_data.payload = ~from.tag();
|
||||
|
|
@ -439,7 +449,11 @@ public:
|
|||
if (from.isInt32() && EncodedValueImpl::PlatformSmiTagging::IsValidSmi(i32 = from.asInt32())) {
|
||||
setPayload(EncodedValueImpl::PlatformSmiTagging::IntToSmi(i32));
|
||||
} else if (from.isNumber()) {
|
||||
setPayload(reinterpret_cast<intptr_t>(new NumberInEncodedValue(from)));
|
||||
if (UNLIKELY(Value::isInt32ConvertibleDouble(from.asNumber(), i32) && EncodedValueImpl::PlatformSmiTagging::IsValidSmi(i32))) {
|
||||
setPayload(EncodedValueImpl::PlatformSmiTagging::IntToSmi(i32));
|
||||
} else {
|
||||
setPayload(reinterpret_cast<intptr_t>(new NumberInEncodedValue(from)));
|
||||
}
|
||||
} else {
|
||||
setPayload(from.payload());
|
||||
}
|
||||
|
|
@ -518,38 +532,44 @@ public:
|
|||
return payload() == other.payload();
|
||||
}
|
||||
|
||||
ALWAYS_INLINE void operator=(const EncodedValue& from)
|
||||
ALWAYS_INLINE const EncodedSmallValue& operator=(const EncodedValue& from)
|
||||
{
|
||||
setPayload(from.payload());
|
||||
return *this;
|
||||
}
|
||||
|
||||
ALWAYS_INLINE void operator=(const Value& from)
|
||||
ALWAYS_INLINE const EncodedSmallValue& operator=(const Value& from)
|
||||
{
|
||||
if (from.isPointerValue()) {
|
||||
setPayload(reinterpret_cast<intptr_t>(from.asPointerValue()));
|
||||
return;
|
||||
return *this;
|
||||
}
|
||||
|
||||
int32_t i32;
|
||||
if (from.isInt32() && EncodedValueImpl::PlatformSmiTagging::IsValidSmi(i32 = from.asInt32())) {
|
||||
setPayload(EncodedValueImpl::PlatformSmiTagging::IntToSmi(i32));
|
||||
return;
|
||||
return *this;
|
||||
}
|
||||
|
||||
if (from.isNumber()) {
|
||||
Value mutableFrom(from);
|
||||
if (UNLIKELY(Value::isInt32ConvertibleDouble(mutableFrom.asNumber(), i32))) {
|
||||
mutableFrom = Value(i32);
|
||||
}
|
||||
auto pl = payload();
|
||||
if (!isSMI() && ((size_t)pl > (size_t)ValueLast)) {
|
||||
void* v = reinterpret_cast<void*>(pl);
|
||||
if (EncodedValue::readPointerIsNumberEncodedValue(v)) {
|
||||
reinterpret_cast<NumberInEncodedValue*>(v)->setValue(from);
|
||||
return;
|
||||
reinterpret_cast<NumberInEncodedValue*>(v)->setValue(mutableFrom);
|
||||
return *this;
|
||||
}
|
||||
}
|
||||
setPayload(reinterpret_cast<intptr_t>(new NumberInEncodedValue(from)));
|
||||
setPayload(reinterpret_cast<intptr_t>(new NumberInEncodedValue(mutableFrom)));
|
||||
ASSERT(EncodedValue::readPointerIsNumberEncodedValue((void*)payload()));
|
||||
return;
|
||||
return *this;
|
||||
}
|
||||
setPayload(from.payload());
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -89,6 +89,10 @@ inline ToType bitwise_cast(FromType from)
|
|||
#define CellPayloadOffset PayloadOffset
|
||||
#endif
|
||||
|
||||
// basic class for representing ECMAScript Value
|
||||
// Int32 convertible double value can exist rarely(for interpreter performance)
|
||||
// but Int32 convertible double case is not exist with EncodedValue
|
||||
// so, public API users should not care the case
|
||||
class Value {
|
||||
public:
|
||||
static constexpr const double MinusZeroIndex = std::numeric_limits<double>::min();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue