[vm/dbc] Support UnboxedWidthExtender on DBC
Change-Id: If6446665f65c0b39dc3a0496c85f367b7738d79a Cq-Include-Trybots: luci.dart.try:vm-kernel-linux-debug-simdbc64-try, vm-kernel-linux-release-simdbc64-try, vm-kernel-mac-debug-simdbc64-try, vm-kernel-mac-release-simdbc64-try, vm-kernel-reload-mac-debug-simdbc64-try, vm-kernel-reload-mac-release-simdbc64-try, vm-kernel-linux-debug-ia32-try, vm-dartkb-linux-debug-simarm64-try Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/100541 Auto-Submit: Daco Harkes <dacoharkes@google.com> Reviewed-by: Samir Jindel <sjindel@google.com> Commit-Queue: Daco Harkes <dacoharkes@google.com>
This commit is contained in:
committed by
commit-bot@chromium.org
parent
ed8e4255a4
commit
a23def41f9
@@ -6,6 +6,7 @@
|
||||
#if defined(TARGET_ARCH_DBC)
|
||||
|
||||
#include "vm/compiler/assembler/assembler.h"
|
||||
#include "vm/compiler/backend/locations.h"
|
||||
#include "vm/compiler/compiler_state.h"
|
||||
#include "vm/stack_frame.h"
|
||||
#include "vm/symbols.h"
|
||||
@@ -2479,6 +2480,97 @@ ASSEMBLER_TEST_RUN(WriteIntoMint, test) {
|
||||
EXPECT_EQ(kMaxInt64, Mint::Cast(obj).value());
|
||||
}
|
||||
|
||||
// - UnboxedWidthExtender rA rB C
|
||||
//
|
||||
// Sign- or zero-extends an unboxed integer in FP[rB] into an unboxed
|
||||
// integer in FP[rA]. C contains SmallRepresentation which determines how
|
||||
// the integer is extended.
|
||||
ASSEMBLER_TEST_GENERATE(UnboxedWidthExtenderInt8Positive, assembler) {
|
||||
__ Frame(3);
|
||||
__ LoadConstant(0, Integer::Handle(Integer::New(kMaxInt8 + 0xFFFFFF00)));
|
||||
__ UnboxInt64(1, 0);
|
||||
// The lower bits contain 0x7F, overwrite the upper bits with 0.
|
||||
__ UnboxedWidthExtender(2, 1, kSmallUnboxedInt8);
|
||||
__ Return(2);
|
||||
}
|
||||
|
||||
ASSEMBLER_TEST_RUN(UnboxedWidthExtenderInt8Positive, test) {
|
||||
EXPECT_EQ(kMaxInt8,
|
||||
kMaxUint32 & EXECUTE_TEST_CODE_INTPTR_UNBOXED(test->code()));
|
||||
}
|
||||
|
||||
ASSEMBLER_TEST_GENERATE(UnboxedWidthExtenderInt8Negative, assembler) {
|
||||
__ Frame(3);
|
||||
__ LoadConstant(0, Integer::Handle(Integer::New(kMaxInt32)));
|
||||
__ UnboxInt64(1, 0);
|
||||
// The lower bits contain 0xFF, overwrite the upper bits with 1.
|
||||
__ UnboxedWidthExtender(2, 1, kSmallUnboxedInt8);
|
||||
__ Return(2);
|
||||
}
|
||||
|
||||
ASSEMBLER_TEST_RUN(UnboxedWidthExtenderInt8Negative, test) {
|
||||
// least significant 32 bits set to 1.
|
||||
EXPECT_EQ(kMaxUint32,
|
||||
kMaxUint32 & EXECUTE_TEST_CODE_INTPTR_UNBOXED(test->code()));
|
||||
}
|
||||
|
||||
ASSEMBLER_TEST_GENERATE(UnboxedWidthExtenderUint8, assembler) {
|
||||
__ Frame(3);
|
||||
__ LoadConstant(0, Integer::Handle(Integer::New(kMaxUint32)));
|
||||
__ UnboxInt64(1, 0);
|
||||
// The lower bits contain 0xFF, overwrite the upper bits with 0.
|
||||
__ UnboxedWidthExtender(2, 1, kSmallUnboxedUint8);
|
||||
__ Return(2);
|
||||
}
|
||||
|
||||
ASSEMBLER_TEST_RUN(UnboxedWidthExtenderUint8, test) {
|
||||
EXPECT_EQ(kMaxUint8,
|
||||
kMaxUint32 & EXECUTE_TEST_CODE_INTPTR_UNBOXED(test->code()));
|
||||
}
|
||||
|
||||
ASSEMBLER_TEST_GENERATE(UnboxedWidthExtenderInt16Positive, assembler) {
|
||||
__ Frame(3);
|
||||
__ LoadConstant(0, Integer::Handle(Integer::New(kMaxInt16 + 0xFFFF0000)));
|
||||
__ UnboxInt64(1, 0);
|
||||
// The lower bits contain 0x7FFF, overwrite the upper bits with 0.
|
||||
__ UnboxedWidthExtender(2, 1, kSmallUnboxedInt16);
|
||||
__ Return(2);
|
||||
}
|
||||
|
||||
ASSEMBLER_TEST_RUN(UnboxedWidthExtenderInt16Positive, test) {
|
||||
EXPECT_EQ(kMaxInt16,
|
||||
kMaxUint32 & EXECUTE_TEST_CODE_INTPTR_UNBOXED(test->code()));
|
||||
}
|
||||
|
||||
ASSEMBLER_TEST_GENERATE(UnboxedWidthExtenderInt16Negative, assembler) {
|
||||
__ Frame(3);
|
||||
__ LoadConstant(0, Integer::Handle(Integer::New(kMaxInt32)));
|
||||
__ UnboxInt64(1, 0);
|
||||
// The lower bits contain 0xFFFF, overwrite the upper bits with 1.
|
||||
__ UnboxedWidthExtender(2, 1, kSmallUnboxedInt16);
|
||||
__ Return(2);
|
||||
}
|
||||
|
||||
ASSEMBLER_TEST_RUN(UnboxedWidthExtenderInt16Negative, test) {
|
||||
// least significant 32 bits set to 1.
|
||||
EXPECT_EQ(kMaxUint32,
|
||||
kMaxUint32 & EXECUTE_TEST_CODE_INTPTR_UNBOXED(test->code()));
|
||||
}
|
||||
|
||||
ASSEMBLER_TEST_GENERATE(UnboxedWidthExtenderUint16, assembler) {
|
||||
__ Frame(3);
|
||||
__ LoadConstant(0, Integer::Handle(Integer::New(kMaxUint32)));
|
||||
__ UnboxInt64(1, 0);
|
||||
// The lower bits contain 0xFFFF, overwrite the upper bits with 0.
|
||||
__ UnboxedWidthExtender(2, 1, kSmallUnboxedUint16);
|
||||
__ Return(2);
|
||||
}
|
||||
|
||||
ASSEMBLER_TEST_RUN(UnboxedWidthExtenderUint16, test) {
|
||||
EXPECT_EQ(kMaxUint16,
|
||||
kMaxUint32 & EXECUTE_TEST_CODE_INTPTR_UNBOXED(test->code()));
|
||||
}
|
||||
|
||||
#if defined(ARCH_IS_64_BIT)
|
||||
// - UnboxDouble rA, rD
|
||||
//
|
||||
|
||||
@@ -7715,12 +7715,14 @@ class UnboxedWidthExtenderInstr : public TemplateDefinition<1, NoThrow, Pure> {
|
||||
public:
|
||||
UnboxedWidthExtenderInstr(Value* value,
|
||||
Representation rep,
|
||||
intptr_t from_width_bytes)
|
||||
SmallRepresentation from_rep)
|
||||
: TemplateDefinition(DeoptId::kNone),
|
||||
representation_(rep),
|
||||
from_width_bytes_(from_width_bytes) {
|
||||
ASSERT(from_width_bytes == 1 || from_width_bytes == 2);
|
||||
ASSERT(rep == kUnboxedInt32 || rep == kUnboxedUint32);
|
||||
from_representation_(from_rep) {
|
||||
ASSERT(rep == kUnboxedInt32 && (from_rep == kSmallUnboxedInt8 ||
|
||||
from_rep == kSmallUnboxedInt16) ||
|
||||
rep == kUnboxedUint32 && (from_rep == kSmallUnboxedUint8 ||
|
||||
from_rep == kSmallUnboxedUint16));
|
||||
SetInputAt(0, value);
|
||||
}
|
||||
|
||||
@@ -7728,6 +7730,10 @@ class UnboxedWidthExtenderInstr : public TemplateDefinition<1, NoThrow, Pure> {
|
||||
|
||||
Representation representation() const { return representation_; }
|
||||
|
||||
SmallRepresentation from_representation() const {
|
||||
return from_representation_;
|
||||
}
|
||||
|
||||
bool ComputeCanDeoptimize() const { return false; }
|
||||
|
||||
virtual Representation RequiredInputRepresentation(intptr_t idx) const {
|
||||
@@ -7739,7 +7745,7 @@ class UnboxedWidthExtenderInstr : public TemplateDefinition<1, NoThrow, Pure> {
|
||||
ASSERT(other->IsUnboxedWidthExtender());
|
||||
const UnboxedWidthExtenderInstr* ext = other->AsUnboxedWidthExtender();
|
||||
return ext->representation() == representation() &&
|
||||
ext->from_width_bytes_ == from_width_bytes_;
|
||||
ext->from_representation_ == from_representation_;
|
||||
}
|
||||
|
||||
virtual CompileType ComputeType() const { return CompileType::Int(); }
|
||||
@@ -7749,8 +7755,18 @@ class UnboxedWidthExtenderInstr : public TemplateDefinition<1, NoThrow, Pure> {
|
||||
PRINT_OPERANDS_TO_SUPPORT
|
||||
|
||||
private:
|
||||
intptr_t from_width_bytes() const {
|
||||
if (from_representation_ == kSmallUnboxedInt8 ||
|
||||
from_representation_ == kSmallUnboxedUint8) {
|
||||
return 1;
|
||||
}
|
||||
ASSERT(from_representation_ == kSmallUnboxedInt16 ||
|
||||
from_representation_ == kSmallUnboxedUint16);
|
||||
return 2;
|
||||
}
|
||||
|
||||
const Representation representation_;
|
||||
const intptr_t from_width_bytes_;
|
||||
const SmallRepresentation from_representation_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(UnboxedWidthExtenderInstr);
|
||||
};
|
||||
|
||||
@@ -6712,7 +6712,7 @@ void UnboxedWidthExtenderInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
Register reg = locs()->in(0).reg();
|
||||
// There are no builtin sign- or zero-extension instructions, so we'll have to
|
||||
// use shifts instead.
|
||||
const intptr_t shift_length = (kWordSize - from_width_bytes_) * kBitsPerByte;
|
||||
const intptr_t shift_length = (kWordSize - from_width_bytes()) * kBitsPerByte;
|
||||
__ Lsl(reg, reg, Operand(shift_length));
|
||||
switch (representation_) {
|
||||
case kUnboxedInt32: // Sign extend operand.
|
||||
|
||||
@@ -5928,30 +5928,18 @@ LocationSummary* UnboxedWidthExtenderInstr::MakeLocationSummary(
|
||||
|
||||
void UnboxedWidthExtenderInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
Register reg = locs()->in(0).reg();
|
||||
switch (representation_) {
|
||||
case kUnboxedInt32: // Sign extend operand.
|
||||
switch (from_width_bytes_) {
|
||||
case 1:
|
||||
__ sxtb(reg, reg);
|
||||
break;
|
||||
case 2:
|
||||
__ sxth(reg, reg);
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
switch (from_representation()) {
|
||||
case kSmallUnboxedInt8: // Sign extend operand.
|
||||
__ sxtb(reg, reg);
|
||||
break;
|
||||
case kUnboxedUint32: // Zero extend operand.
|
||||
switch (from_width_bytes_) {
|
||||
case 1:
|
||||
__ uxtb(reg, reg);
|
||||
break;
|
||||
case 2:
|
||||
__ uxth(reg, reg);
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
case kSmallUnboxedInt16:
|
||||
__ sxth(reg, reg);
|
||||
break;
|
||||
case kSmallUnboxedUint8: // Zero extend operand.
|
||||
__ uxtb(reg, reg);
|
||||
break;
|
||||
case kSmallUnboxedUint16:
|
||||
__ uxth(reg, reg);
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
|
||||
@@ -45,8 +45,7 @@ DECLARE_FLAG(int, optimization_counter_threshold);
|
||||
M(SpeculativeShiftUint32Op) \
|
||||
M(TruncDivMod) \
|
||||
M(UnaryUint32Op) \
|
||||
M(IntConverter) \
|
||||
M(UnboxedWidthExtender)
|
||||
M(IntConverter)
|
||||
|
||||
// List of instructions that are not used by DBC.
|
||||
// Things we aren't planning to implement for DBC:
|
||||
@@ -1797,6 +1796,12 @@ void UnboxInstr::EmitLoadInt64FromBoxOrSmi(FlowGraphCompiler* compiler) {
|
||||
#endif // defined(ARCH_IS_64_BIT)
|
||||
}
|
||||
|
||||
EMIT_NATIVE_CODE(UnboxedWidthExtender, 1, Location::RequiresRegister()) {
|
||||
const Register out = locs()->out(0).reg();
|
||||
const Register value = locs()->in(0).reg();
|
||||
__ UnboxedWidthExtender(out, value, from_representation());
|
||||
}
|
||||
|
||||
EMIT_NATIVE_CODE(DoubleToSmi, 1, Location::RequiresRegister()) {
|
||||
const Register value = locs()->in(0).reg();
|
||||
const Register result = locs()->out(0).reg();
|
||||
|
||||
@@ -6064,30 +6064,18 @@ LocationSummary* UnboxedWidthExtenderInstr::MakeLocationSummary(
|
||||
}
|
||||
|
||||
void UnboxedWidthExtenderInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
switch (representation_) {
|
||||
case kUnboxedInt32: // Sign-extend operand.
|
||||
switch (from_width_bytes_) {
|
||||
case 1:
|
||||
__ movsxb(EAX, AL);
|
||||
break;
|
||||
case 2:
|
||||
__ movsxw(EAX, EAX);
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
switch (from_representation()) {
|
||||
case kSmallUnboxedInt8: // Sign extend operand.
|
||||
__ movsxb(EAX, AL);
|
||||
break;
|
||||
case kUnboxedUint32: // Zero-extend operand.
|
||||
switch (from_width_bytes_) {
|
||||
case 1:
|
||||
__ movzxb(EAX, AL);
|
||||
break;
|
||||
case 2:
|
||||
__ movzxw(EAX, EAX);
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
case kSmallUnboxedInt16:
|
||||
__ movsxw(EAX, EAX);
|
||||
break;
|
||||
case kSmallUnboxedUint8: // Zero extend operand.
|
||||
__ movzxb(EAX, AL);
|
||||
break;
|
||||
case kSmallUnboxedUint16:
|
||||
__ movzxw(EAX, EAX);
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
|
||||
@@ -1001,7 +1001,7 @@ void IntConverterInstr::PrintOperandsTo(BufferFormatter* f) const {
|
||||
}
|
||||
|
||||
void UnboxedWidthExtenderInstr::PrintOperandsTo(BufferFormatter* f) const {
|
||||
f->Print("%" Pd " -> 4 (%s), ", from_width_bytes_,
|
||||
f->Print("%" Pd " -> 4 (%s), ", from_width_bytes(),
|
||||
RepresentationToCString(representation()));
|
||||
Definition::PrintOperandsTo(f);
|
||||
}
|
||||
|
||||
@@ -6211,30 +6211,18 @@ LocationSummary* UnboxedWidthExtenderInstr::MakeLocationSummary(
|
||||
}
|
||||
|
||||
void UnboxedWidthExtenderInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
switch (representation_) {
|
||||
case kUnboxedInt32: // Sign extend operand.
|
||||
switch (from_width_bytes_) {
|
||||
case 1:
|
||||
__ movsxb(RAX, RAX);
|
||||
break;
|
||||
case 2:
|
||||
__ movsxw(RAX, RAX);
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
switch (from_representation()) {
|
||||
case kSmallUnboxedInt8: // Sign extend operand.
|
||||
__ movsxb(RAX, RAX);
|
||||
break;
|
||||
case kUnboxedUint32: // Zero extend operand.
|
||||
switch (from_width_bytes_) {
|
||||
case 1:
|
||||
__ movzxb(RAX, RAX);
|
||||
break;
|
||||
case 2:
|
||||
__ movzxw(RAX, RAX);
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
case kSmallUnboxedInt16:
|
||||
__ movsxw(RAX, RAX);
|
||||
break;
|
||||
case kSmallUnboxedUint8: // Zero extend operand.
|
||||
__ movzxb(RAX, RAX);
|
||||
break;
|
||||
case kSmallUnboxedUint16:
|
||||
__ movzxw(RAX, RAX);
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
|
||||
@@ -38,6 +38,16 @@ enum Representation {
|
||||
kNumRepresentations
|
||||
};
|
||||
|
||||
// The representation of 8 and 16 bit integers in 32 bit. SmallRepresentation
|
||||
// tracks the real representation of these small integers.
|
||||
enum SmallRepresentation {
|
||||
kNoSmallRepresentation,
|
||||
kSmallUnboxedInt8,
|
||||
kSmallUnboxedUint8,
|
||||
kSmallUnboxedInt16,
|
||||
kSmallUnboxedUint16,
|
||||
};
|
||||
|
||||
// 'UnboxedFfiIntPtr' should be able to hold a pointer of the target word-size.
|
||||
// On a 32-bit platform, it's an unsigned 32-bit int because it should be
|
||||
// zero-extended to 64-bits, not sign-extended (pointers are inherently
|
||||
|
||||
+21
-10
@@ -3,7 +3,9 @@
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
#include "vm/compiler/ffi.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "platform/globals.h"
|
||||
#include "vm/compiler/runtime_api.h"
|
||||
|
||||
@@ -13,8 +15,6 @@ namespace compiler {
|
||||
|
||||
namespace ffi {
|
||||
|
||||
#if !defined(TARGET_ARCH_DBC)
|
||||
|
||||
static const size_t kSizeUnknown = 0;
|
||||
|
||||
static const intptr_t kNumElementSizes = kFfiVoidCid - kFfiPointerCid + 1;
|
||||
@@ -73,6 +73,23 @@ Representation TypeRepresentation(const AbstractType& result_type) {
|
||||
}
|
||||
}
|
||||
|
||||
SmallRepresentation TypeSmallRepresentation(const AbstractType& ffi_type) {
|
||||
switch (ffi_type.type_class_id()) {
|
||||
case kFfiInt8Cid:
|
||||
return kSmallUnboxedInt8;
|
||||
case kFfiInt16Cid:
|
||||
return kSmallUnboxedInt16;
|
||||
case kFfiUint8Cid:
|
||||
return kSmallUnboxedUint8;
|
||||
case kFfiUint16Cid:
|
||||
return kSmallUnboxedUint16;
|
||||
default:
|
||||
return kNoSmallRepresentation;
|
||||
}
|
||||
}
|
||||
|
||||
#if !defined(TARGET_ARCH_DBC)
|
||||
|
||||
bool NativeTypeIsVoid(const AbstractType& result_type) {
|
||||
return result_type.type_class_id() == kFfiVoidCid;
|
||||
}
|
||||
@@ -299,16 +316,10 @@ intptr_t NumStackSlots(const ZoneGrowableArray<Location>& locations) {
|
||||
return max_height_in_slots;
|
||||
}
|
||||
|
||||
#endif // !defined(DART_PRECOMPILED_RUNTIME)
|
||||
|
||||
#else
|
||||
|
||||
size_t ElementSizeInBytes(intptr_t class_id) {
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
#endif // !defined(TARGET_ARCH_DBC)
|
||||
|
||||
#endif // !defined(DART_PRECOMPILED_RUNTIME)
|
||||
|
||||
} // namespace ffi
|
||||
|
||||
} // namespace compiler
|
||||
|
||||
@@ -28,6 +28,10 @@ size_t ElementSizeInBytes(intptr_t class_id);
|
||||
// Unboxed representation of an FFI type (extends 'ffi.NativeType').
|
||||
Representation TypeRepresentation(const AbstractType& result_type);
|
||||
|
||||
// Unboxed representation of an FFI type (extends 'ffi.NativeType') for 8 and 16
|
||||
// bit integers.
|
||||
SmallRepresentation TypeSmallRepresentation(const AbstractType& result_type);
|
||||
|
||||
// Whether a type which extends 'ffi.NativeType' also extends 'ffi.Pointer'.
|
||||
bool NativeTypeIsPointer(const AbstractType& result_type);
|
||||
|
||||
|
||||
@@ -2433,12 +2433,12 @@ Fragment FlowGraphBuilder::Box(Representation from) {
|
||||
|
||||
Fragment FlowGraphBuilder::FfiUnboxedExtend(Representation representation,
|
||||
const AbstractType& ffi_type) {
|
||||
const intptr_t width =
|
||||
compiler::ffi::ElementSizeInBytes(ffi_type.type_class_id());
|
||||
if (width >= compiler::ffi::kMinimumArgumentWidth) return {};
|
||||
const SmallRepresentation from_representation =
|
||||
compiler::ffi::TypeSmallRepresentation(ffi_type);
|
||||
if (from_representation == kNoSmallRepresentation) return {};
|
||||
|
||||
auto* extend =
|
||||
new (Z) UnboxedWidthExtenderInstr(Pop(), representation, width);
|
||||
auto* extend = new (Z)
|
||||
UnboxedWidthExtenderInstr(Pop(), representation, from_representation);
|
||||
Push(extend);
|
||||
return Fragment(extend);
|
||||
}
|
||||
|
||||
@@ -311,6 +311,12 @@ namespace dart {
|
||||
// following instruction should be a jump to a label after the slow path
|
||||
// allocating a Mint box and writing into the Mint box.)
|
||||
//
|
||||
// - UnboxedWidthExtender rA rB C
|
||||
//
|
||||
// Sign- or zero-extends an unboxed integer in FP[rB] into an unboxed
|
||||
// integer in FP[rA]. C contains SmallRepresentation which determines how
|
||||
// the integer is extended.
|
||||
//
|
||||
// - WriteIntoMint rA, rD
|
||||
//
|
||||
// Box the integer in FP[rD] using the Mint box in FP[rA].
|
||||
@@ -833,6 +839,7 @@ namespace dart {
|
||||
V(BoxUint32, A_D, reg, reg, ___) \
|
||||
V(UnboxInt64, A_D, reg, reg, ___) \
|
||||
V(BoxInt64, A_D, reg, reg, ___) \
|
||||
V(UnboxedWidthExtender, A_B_C, reg, reg, num) \
|
||||
V(SmiToDouble, A_D, reg, reg, ___) \
|
||||
V(DoubleToSmi, A_D, reg, reg, ___) \
|
||||
V(DAdd, A_B_C, reg, reg, reg) \
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
#include "vm/compiler/assembler/assembler.h"
|
||||
#include "vm/compiler/assembler/disassembler.h"
|
||||
#include "vm/compiler/backend/locations.h"
|
||||
#include "vm/compiler/jit/compiler.h"
|
||||
#include "vm/constants_dbc.h"
|
||||
#include "vm/cpu.h"
|
||||
@@ -2107,6 +2108,35 @@ SwitchDispatch:
|
||||
DISPATCH();
|
||||
}
|
||||
|
||||
{
|
||||
BYTECODE(UnboxedWidthExtender, A_B_C);
|
||||
auto rep = static_cast<SmallRepresentation>(rC);
|
||||
const intptr_t value_32_or_64_bit = reinterpret_cast<intptr_t>(FP[rB]);
|
||||
int32_t value = value_32_or_64_bit & kMaxUint32; // Prevent overflow.
|
||||
switch (rep) {
|
||||
case kSmallUnboxedInt8:
|
||||
// Sign extend the top 24 bits from the sign bit.
|
||||
value <<= 24;
|
||||
value >>= 24;
|
||||
break;
|
||||
case kSmallUnboxedUint8:
|
||||
value &= 0x000000FF; // Throw away upper bits.
|
||||
break;
|
||||
case kSmallUnboxedInt16:
|
||||
// Sign extend the top 16 bits from the sign bit.
|
||||
value <<= 16;
|
||||
value >>= 16;
|
||||
break;
|
||||
case kSmallUnboxedUint16:
|
||||
value &= 0x0000FFFF; // Throw away upper bits.
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
FP[rA] = reinterpret_cast<RawObject*>(value);
|
||||
DISPATCH();
|
||||
}
|
||||
|
||||
#if defined(ARCH_IS_64_BIT)
|
||||
{
|
||||
BYTECODE(WriteIntoDouble, A_D);
|
||||
@@ -2685,7 +2715,7 @@ SwitchDispatch:
|
||||
|
||||
BYTECODE(ReturnTOS, 0);
|
||||
result = *SP;
|
||||
// Fall through to the ReturnImpl.
|
||||
// Fall through to the ReturnImpl.
|
||||
|
||||
ReturnImpl:
|
||||
// Restore caller PC.
|
||||
@@ -3073,7 +3103,7 @@ SwitchDispatch:
|
||||
NativeArguments native_args(thread, 5, SP + 1, SP - 4);
|
||||
INVOKE_RUNTIME(DRT_Instanceof, native_args);
|
||||
}
|
||||
// clang-format on
|
||||
// clang-format on
|
||||
|
||||
InstanceOfOk:
|
||||
SP -= 4;
|
||||
|
||||
Reference in New Issue
Block a user