From 09315e771204d612f6b02d915d97d67d8ce665fc Mon Sep 17 00:00:00 2001 From: Ryan Macnak Date: Sat, 9 Nov 2024 11:08:14 -0800 Subject: [PATCH] Perform Smi operations without untagging and retagging. --- vm/interpreter.cc | 65 +++++++++++++++----------- vm/object.h | 13 ++++++ vm/primitives.cc | 116 ++++++++++++++++------------------------------ 3 files changed, 91 insertions(+), 103 deletions(-) diff --git a/vm/interpreter.cc b/vm/interpreter.cc index c78a462..f511e7f 100644 --- a/vm/interpreter.cc +++ b/vm/interpreter.cc @@ -1204,12 +1204,12 @@ void Interpreter::Interpret() { // + Object left = Stack(1); Object right = Stack(0); - if (left->IsSmallInteger() && right->IsSmallInteger()) { - intptr_t raw_left = static_cast(left)->value(); - intptr_t raw_right = static_cast(right)->value(); - intptr_t raw_result = raw_left + raw_right; - if (SmallInteger::IsSmiValue(raw_result)) { - PopNAndPush(2, SmallInteger::New(raw_result)); + if (Object::BothSmallIntegers(left, right)) { + intptr_t raw_left = static_cast(left); + intptr_t raw_right = static_cast(right); + intptr_t raw_result; + if (!Math::AddHasOverflow(raw_left, raw_right, &raw_result)) { + PopNAndPush(2, static_cast(raw_result)); break; } } @@ -1219,12 +1219,12 @@ void Interpreter::Interpret() { // - Object left = Stack(1); Object right = Stack(0); - if (left->IsSmallInteger() && right->IsSmallInteger()) { - intptr_t raw_left = static_cast(left)->value(); - intptr_t raw_right = static_cast(right)->value(); - intptr_t raw_result = raw_left - raw_right; - if (SmallInteger::IsSmiValue(raw_result)) { - PopNAndPush(2, SmallInteger::New(raw_result)); + if (Object::BothSmallIntegers(left, right)) { + intptr_t raw_left = static_cast(left); + intptr_t raw_right = static_cast(right); + intptr_t raw_result; + if (!Math::SubtractHasOverflow(raw_left, raw_right, &raw_result)) { + PopNAndPush(2, static_cast(raw_result)); break; } } @@ -1232,6 +1232,17 @@ void Interpreter::Interpret() { } case 178: { // * + Object left = Stack(1); + Object right = Stack(0); + if (Object::BothSmallIntegers(left, right)) { + intptr_t raw_left = static_cast(left); + intptr_t raw_right = static_cast(right) >> kSmiTagShift; + intptr_t raw_result; + if (!Math::MultiplyHasOverflow(raw_left, raw_right, &raw_result)) { + PopNAndPush(2, static_cast(raw_result)); + break; + } + } goto CommonSendDispatch; } case 179: { @@ -1242,7 +1253,7 @@ void Interpreter::Interpret() { /* \\ */ Object left = Stack(1); Object right = Stack(0); - if (left->IsSmallInteger() && right->IsSmallInteger()) { + if (Object::BothSmallIntegers(left, right)) { intptr_t raw_left = static_cast(left)->value(); intptr_t raw_right = static_cast(right)->value(); if (raw_right != 0) { @@ -1266,9 +1277,9 @@ void Interpreter::Interpret() { // & Object left = Stack(1); Object right = Stack(0); - if (left->IsSmallInteger() && right->IsSmallInteger()) { - PopNAndPush(2, static_cast( - static_cast(left) & static_cast(right))); + if (Object::BothSmallIntegers(left, right)) { + PopNAndPush(2, static_cast(static_cast(left) & + static_cast(right))); break; } goto CommonSendDispatch; @@ -1277,9 +1288,9 @@ void Interpreter::Interpret() { // | Object left = Stack(1); Object right = Stack(0); - if (left->IsSmallInteger() && right->IsSmallInteger()) { - PopNAndPush(2, static_cast( - static_cast(left) | static_cast(right))); + if (Object::BothSmallIntegers(left, right)) { + PopNAndPush(2, static_cast(static_cast(left) | + static_cast(right))); break; } goto CommonSendDispatch; @@ -1288,7 +1299,7 @@ void Interpreter::Interpret() { // < Object left = Stack(1); Object right = Stack(0); - if (left->IsSmallInteger() && right->IsSmallInteger()) { + if (Object::BothSmallIntegers(left, right)) { if (static_cast(left) < static_cast(right)) { PopNAndPush(2, true_); } else { @@ -1302,7 +1313,7 @@ void Interpreter::Interpret() { // > Object left = Stack(1); Object right = Stack(0); - if (left->IsSmallInteger() && right->IsSmallInteger()) { + if (Object::BothSmallIntegers(left, right)) { if (static_cast(left) > static_cast(right)) { PopNAndPush(2, true_); } else { @@ -1316,7 +1327,7 @@ void Interpreter::Interpret() { // <= Object left = Stack(1); Object right = Stack(0); - if (left->IsSmallInteger() && right->IsSmallInteger()) { + if (Object::BothSmallIntegers(left, right)) { if (static_cast(left) <= static_cast(right)) { PopNAndPush(2, true_); } else { @@ -1330,7 +1341,7 @@ void Interpreter::Interpret() { // >= Object left = Stack(1); Object right = Stack(0); - if (left->IsSmallInteger() && right->IsSmallInteger()) { + if (Object::BothSmallIntegers(left, right)) { if (static_cast(left) >= static_cast(right)) { PopNAndPush(2, true_); } else { @@ -1344,7 +1355,7 @@ void Interpreter::Interpret() { // = Object left = Stack(1); Object right = Stack(0); - if (left->IsSmallInteger() && right->IsSmallInteger()) { + if (Object::BothSmallIntegers(left, right)) { if (static_cast(left) == static_cast(right)) { PopNAndPush(2, true_); } else { @@ -1404,9 +1415,9 @@ void Interpreter::Interpret() { SmallInteger value = static_cast(Stack(0)); if ((raw_index >= 0) && (raw_index < static_cast(array)->Size()) && - static_cast(value) <= 255) { - static_cast(array)->set_element(raw_index, - value->value()); + SmallInteger::IsByte(value)) { + static_cast(array)->set_element( + raw_index, SmallInteger::Byte(value)); PopNAndPush(3, value); break; } diff --git a/vm/object.h b/vm/object.h index f975517..2786a9f 100644 --- a/vm/object.h +++ b/vm/object.h @@ -151,6 +151,10 @@ class Object { bool IsSmallInteger() const { return (tagged_pointer_ & kSmiTagMask) == kSmiTag; } + static bool BothSmallIntegers(Object a, Object b) { + return ((static_cast(a) | static_cast(b)) + & kSmiTagMask) == kSmiTag; + } bool IsOldObject() const { return (tagged_pointer_ & kObjectAlignmentMask) == kOldObjectBits; } @@ -348,6 +352,15 @@ class SmallInteger : public Object { intptr_t untagged = tagged >> kSmiTagShift; return untagged == value; } + + static bool IsByte(Object obj) { + return static_cast(obj) <= + static_cast(255 << kSmiTagShift); + } + static uint8_t Byte(Object obj) { + ASSERT(IsByte(obj)); + return static_cast(obj) >> kSmiTagShift; + } }; class MediumInteger : public HeapObject { diff --git a/vm/primitives.cc b/vm/primitives.cc index 309cabf..7b9bffd 100644 --- a/vm/primitives.cc +++ b/vm/primitives.cc @@ -282,7 +282,7 @@ const bool kFailure = false; static bool primitive##name(intptr_t num_args, Heap* H, Interpreter* I) #define IS_SMI_OP(left, right) \ - (left->IsSmallInteger() && right->IsSmallInteger()) + (Object::BothSmallIntegers(left, right)) #define IS_MINT_OP(left, right) \ ((left->IsSmallInteger() || left->IsMediumInteger()) && \ @@ -405,10 +405,12 @@ DEFINE_PRIMITIVE(Number_add) { Object left = I->Stack(1); Object right = I->Stack(0); if (IS_SMI_OP(left, right)) { - intptr_t raw_left = SMI_VALUE(left); - intptr_t raw_right = SMI_VALUE(right); - intptr_t raw_result = raw_left + raw_right; // Cannot overflow. - RETURN_MINT(raw_result); + intptr_t raw_left = static_cast(left); + intptr_t raw_right = static_cast(right); + intptr_t raw_result; + if (!Math::AddHasOverflow(raw_left, raw_right, &raw_result)) { + RETURN(static_cast(raw_result)); + } } if (IS_MINT_OP(left, right)) { @@ -443,10 +445,12 @@ DEFINE_PRIMITIVE(Number_subtract) { Object left = I->Stack(1); Object right = I->Stack(0); if (IS_SMI_OP(left, right)) { - intptr_t raw_left = SMI_VALUE(left); - intptr_t raw_right = SMI_VALUE(right); - intptr_t raw_result = raw_left - raw_right; // Cannot overflow. - RETURN_MINT(raw_result); + intptr_t raw_left = static_cast(left); + intptr_t raw_right = static_cast(right); + intptr_t raw_result; + if (!Math::SubtractHasOverflow(raw_left, raw_right, &raw_result)) { + RETURN(static_cast(raw_result)); + } } if (IS_MINT_OP(left, right)) { @@ -482,23 +486,12 @@ DEFINE_PRIMITIVE(Number_multiply) { Object left = I->Stack(1); Object right = I->Stack(0); if (IS_SMI_OP(left, right)) { -#if defined(ARCH_IS_32_BIT) - int64_t raw_left = SMI_VALUE(left); - int64_t raw_right = SMI_VALUE(right); - int64_t raw_result = raw_left * raw_right; // Cannot overflow. - RETURN_MINT(raw_result); -#elif defined(ARCH_IS_64_BIT) - intptr_t raw_left = SMI_VALUE(left); - intptr_t raw_right = SMI_VALUE(right); + intptr_t raw_left = static_cast(left); + intptr_t raw_right = static_cast(right) >> kSmiTagShift; intptr_t raw_result; - if (Math::MultiplyHasOverflow(raw_left, raw_right, &raw_result)) { - // Fall through to large integer operation. - } else { - RETURN_MINT(raw_result); + if (!Math::MultiplyHasOverflow(raw_left, raw_right, &raw_result)) { + RETURN(static_cast(raw_result)); } -#else -#error Unimplemented -#endif } if (IS_MINT_OP(left, right)) { @@ -773,9 +766,7 @@ DEFINE_PRIMITIVE(Number_equal) { Object left = I->Stack(1); Object right = I->Stack(0); if (IS_SMI_OP(left, right)) { - intptr_t raw_left = SMI_VALUE(left); - intptr_t raw_right = SMI_VALUE(right); - RETURN_BOOL(raw_left == raw_right); + RETURN_BOOL(static_cast(left) == static_cast(right)); } if (IS_MINT_OP(left, right)) { @@ -803,9 +794,7 @@ DEFINE_PRIMITIVE(Number_less) { Object left = I->Stack(1); Object right = I->Stack(0); if (IS_SMI_OP(left, right)) { - intptr_t raw_left = SMI_VALUE(left); - intptr_t raw_right = SMI_VALUE(right); - RETURN_BOOL(raw_left < raw_right); + RETURN_BOOL(static_cast(left) < static_cast(right)); } if (IS_MINT_OP(left, right)) { @@ -833,9 +822,7 @@ DEFINE_PRIMITIVE(Number_greater) { Object left = I->Stack(1); Object right = I->Stack(0); if (IS_SMI_OP(left, right)) { - intptr_t raw_left = SMI_VALUE(left); - intptr_t raw_right = SMI_VALUE(right); - RETURN_BOOL(raw_left > raw_right); + RETURN_BOOL(static_cast(left) > static_cast(right)); } if (IS_MINT_OP(left, right)) { @@ -863,9 +850,7 @@ DEFINE_PRIMITIVE(Number_lessOrEqual) { Object left = I->Stack(1); Object right = I->Stack(0); if (IS_SMI_OP(left, right)) { - intptr_t raw_left = SMI_VALUE(left); - intptr_t raw_right = SMI_VALUE(right); - RETURN_BOOL(raw_left <= raw_right); + RETURN_BOOL(static_cast(left) <= static_cast(right)); } if (IS_MINT_OP(left, right)) { @@ -893,9 +878,7 @@ DEFINE_PRIMITIVE(Number_greaterOrEqual) { Object left = I->Stack(1); Object right = I->Stack(0); if (IS_SMI_OP(left, right)) { - intptr_t raw_left = SMI_VALUE(left); - intptr_t raw_right = SMI_VALUE(right); - RETURN_BOOL(raw_left >= raw_right); + RETURN_BOOL(static_cast(left) >= static_cast(right)); } if (IS_MINT_OP(left, right)) { @@ -957,10 +940,8 @@ DEFINE_PRIMITIVE(Integer_bitAnd) { Object left = I->Stack(1); Object right = I->Stack(0); if (IS_SMI_OP(left, right)) { - intptr_t raw_left = SMI_VALUE(left); - intptr_t raw_right = SMI_VALUE(right); - intptr_t raw_result = raw_left & raw_right; - RETURN_SMI(raw_result); + RETURN(static_cast(static_cast(left) & + static_cast(right))); } if (IS_MINT_OP(left, right)) { @@ -983,10 +964,8 @@ DEFINE_PRIMITIVE(Integer_bitOr) { Object left = I->Stack(1); Object right = I->Stack(0); if (IS_SMI_OP(left, right)) { - intptr_t raw_left = SMI_VALUE(left); - intptr_t raw_right = SMI_VALUE(right); - intptr_t raw_result = raw_left | raw_right; - RETURN_SMI(raw_result); + RETURN(static_cast(static_cast(left) | + static_cast(right))); } if (IS_MINT_OP(left, right)) { @@ -1009,10 +988,9 @@ DEFINE_PRIMITIVE(Integer_bitXor) { Object left = I->Stack(1); Object right = I->Stack(0); if (IS_SMI_OP(left, right)) { - intptr_t raw_left = SMI_VALUE(left); - intptr_t raw_right = SMI_VALUE(right); - intptr_t raw_result = raw_left ^ raw_right; - RETURN_SMI(raw_result); + RETURN(static_cast(static_cast(left) ^ + static_cast(right) ^ + kSmiTag)); } if (IS_MINT_OP(left, right)) { @@ -1464,12 +1442,12 @@ DEFINE_PRIMITIVE(ByteArray_atPut) { if ((index < 0) || (index >= array->Size())) { return kFailure; } - SMI_ARGUMENT(value, 0); - if ((value < 0) || (value > 255)) { + Object value = I->Stack(0); + if (!SmallInteger::IsByte(value)) { return kFailure; } - array->set_element(index, value); - RETURN_SMI(value); + array->set_element(index, SmallInteger::Byte(value)); + RETURN(value); } DEFINE_PRIMITIVE(ByteArray_size) { @@ -2699,12 +2677,12 @@ DEFINE_PRIMITIVE(Bytes_copyStringFromTo) { DEFINE_PRIMITIVE(String_class_with) { ASSERT(num_args == 1); - SMI_ARGUMENT(byte, 0); - if ((byte < 0) || (byte > 255)) { + Object byte = I->Stack(0); + if (!SmallInteger::IsByte(byte)) { return kFailure; } String result = H->AllocateString(1); // SAFEPOINT - result->set_element(0, byte); + result->set_element(0, SmallInteger::Byte(byte)); RETURN(result); } @@ -2725,12 +2703,7 @@ DEFINE_PRIMITIVE(String_class_withAll) { intptr_t length = bytes->Size(); for (intptr_t i = 0; i < length; i++) { - SmallInteger byte = static_cast(bytes->element(i)); - if (!byte->IsSmallInteger()) { - return kFailure; - } - intptr_t raw_byte = byte->value(); - if ((raw_byte < 0) || (raw_byte > 255)) { + if (!SmallInteger::IsByte(bytes->element(i))) { return kFailure; } } @@ -2739,9 +2712,7 @@ DEFINE_PRIMITIVE(String_class_withAll) { bytes = static_cast(I->Stack(0)); for (intptr_t i = 0; i < length; i++) { - SmallInteger byte = static_cast(bytes->element(i)); - intptr_t raw_byte = byte->value(); - result->set_element(i, raw_byte); + result->set_element(i, SmallInteger::Byte(bytes->element(i))); } RETURN(result); @@ -2766,12 +2737,7 @@ DEFINE_PRIMITIVE(ByteArray_class_withAll) { intptr_t length = bytes->Size(); for (intptr_t i = 0; i < length; i++) { - SmallInteger byte = static_cast(bytes->element(i)); - if (!byte->IsSmallInteger()) { - return kFailure; - } - intptr_t raw_byte = byte->value(); - if ((raw_byte < 0) || (raw_byte > 255)) { + if (!SmallInteger::IsByte(bytes->element(i))) { return kFailure; } } @@ -2780,9 +2746,7 @@ DEFINE_PRIMITIVE(ByteArray_class_withAll) { bytes = static_cast(I->Stack(0)); for (intptr_t i = 0; i < length; i++) { - SmallInteger byte = static_cast(bytes->element(i)); - intptr_t raw_byte = byte->value(); - result->set_element(i, raw_byte); + result->set_element(i, SmallInteger::Byte(bytes->element(i))); } RETURN(result);