diff --git a/runtime/vm/compiler/backend/il.cc b/runtime/vm/compiler/backend/il.cc index 5f51a5b384c..85abf0f970c 100644 --- a/runtime/vm/compiler/backend/il.cc +++ b/runtime/vm/compiler/backend/il.cc @@ -478,6 +478,80 @@ bool HierarchyInfo::InstanceOfHasClassRange(const AbstractType& type, return false; } +// The set of supported non-integer unboxed representations. +// Format: (unboxed representations suffix, boxed class type) +#define FOR_EACH_NON_INT_BOXED_REPRESENTATION(M) \ + M(Double, Double) \ + M(Float, Double) \ + M(Float32x4, Float32x4) \ + M(Float64x2, Float64x2) \ + M(Int32x4, Int32x4) + +#define BOXING_IN_SET_CASE(unboxed, boxed) \ + case kUnboxed##unboxed: \ + return true; +#define BOXING_VALUE_OFFSET_CASE(unboxed, boxed) \ + case kUnboxed##unboxed: \ + return compiler::target::boxed::value_offset(); +#define BOXING_CID_CASE(unboxed, boxed) \ + case kUnboxed##unboxed: \ + return k##boxed##Cid; + +bool Boxing::Supports(Representation rep) { + if (RepresentationUtils::IsUnboxedInteger(rep)) { + return true; + } + switch (rep) { + FOR_EACH_NON_INT_BOXED_REPRESENTATION(BOXING_IN_SET_CASE) + default: + return false; + } +} + +bool Boxing::RequiresAllocation(Representation rep) { + if (RepresentationUtils::IsUnboxedInteger(rep)) { + return (kBitsPerByte * RepresentationUtils::ValueSize(rep)) > + compiler::target::kSmiBits; + } + return true; +} + +intptr_t Boxing::ValueOffset(Representation rep) { + if (RepresentationUtils::IsUnboxedInteger(rep) && + Boxing::RequiresAllocation(rep) && + RepresentationUtils::ValueSize(rep) <= sizeof(int64_t)) { + return compiler::target::Mint::value_offset(); + } + switch (rep) { + FOR_EACH_NON_INT_BOXED_REPRESENTATION(BOXING_VALUE_OFFSET_CASE) + default: + UNREACHABLE(); + return 0; + } +} + +// Note that not all boxes require allocation (e.g., Smis). +intptr_t Boxing::BoxCid(Representation rep) { + if (RepresentationUtils::IsUnboxedInteger(rep)) { + if (!Boxing::RequiresAllocation(rep)) { + return kSmiCid; + } else if (RepresentationUtils::ValueSize(rep) <= sizeof(int64_t)) { + return kMintCid; + } + } + switch (rep) { + FOR_EACH_NON_INT_BOXED_REPRESENTATION(BOXING_CID_CASE) + default: + UNREACHABLE(); + return kIllegalCid; + } +} + +#undef BOXING_CID_CASE +#undef BOXING_VALUE_OFFSET_CASE +#undef BOXING_IN_SET_CASE +#undef FOR_EACH_NON_INT_BOXED_REPRESENTATION + #if defined(DEBUG) void Instruction::CheckField(const Field& field) const { ASSERT(field.IsZoneHandle()); @@ -5255,6 +5329,7 @@ void RangeErrorSlowPath::EmitSharedStubCall(FlowGraphCompiler* compiler, void UnboxInstr::EmitLoadFromBoxWithDeopt(FlowGraphCompiler* compiler) { const intptr_t box_cid = BoxCid(); + ASSERT(box_cid != kSmiCid); // Should never reach here with Smi-able ints. const Register box = locs()->in(0).reg(); const Register temp = (locs()->temp_count() > 0) ? locs()->temp(0).reg() : kNoRegister; @@ -5285,6 +5360,11 @@ void UnboxInstr::EmitLoadFromBoxWithDeopt(FlowGraphCompiler* compiler) { void UnboxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { if (SpeculativeModeOfInputs() == kNotSpeculative) { + if (BoxCid() == kSmiCid) { + // Since the representation fits in a Smi, we can extract it directly. + ASSERT_EQUAL(value()->Type()->ToCid(), kSmiCid); + return EmitSmiConversion(compiler); + } switch (representation()) { case kUnboxedDouble: case kUnboxedFloat: @@ -5317,14 +5397,15 @@ void UnboxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { const intptr_t value_cid = value()->Type()->ToCid(); const intptr_t box_cid = BoxCid(); - if (value_cid == box_cid) { - EmitLoadFromBox(compiler); - } else if (CanConvertSmi() && (value_cid == kSmiCid)) { + if (box_cid == kSmiCid || (CanConvertSmi() && (value_cid == kSmiCid))) { + ASSERT_EQUAL(value_cid, kSmiCid); EmitSmiConversion(compiler); } else if (representation() == kUnboxedInt32 && value()->Type()->IsInt()) { EmitLoadInt32FromBoxOrSmi(compiler); } else if (representation() == kUnboxedInt64 && value()->Type()->IsInt()) { EmitLoadInt64FromBoxOrSmi(compiler); + } else if (value_cid == box_cid) { + EmitLoadFromBox(compiler); } else { ASSERT(CanDeoptimize()); EmitLoadFromBoxWithDeopt(compiler); diff --git a/runtime/vm/compiler/backend/il.h b/runtime/vm/compiler/backend/il.h index b3c6d6986e8..df2ec7f541c 100644 --- a/runtime/vm/compiler/backend/il.h +++ b/runtime/vm/compiler/backend/il.h @@ -3492,19 +3492,6 @@ class ConstantInstr : public TemplateDefinition<0, NoThrow, Pure> { virtual TokenPosition token_pos() const { return token_pos_; } - // Returns whether the constant fits in an unboxed 64-bit signed integer. - bool IsUnboxedSignedIntegerConstant() const { - return representation() == kUnboxedUint32 || - representation() == kUnboxedInt32 || - representation() == kUnboxedInt64; - } - - int64_t GetUnboxedSignedIntegerConstantValue() const { - ASSERT(IsUnboxedSignedIntegerConstant()); - return value_.IsSmi() ? Smi::Cast(value_).Value() - : Mint::Cast(value_).value(); - } - void EmitMoveToLocation(FlowGraphCompiler* compiler, const Location& destination, Register tmp = kNoRegister); @@ -6664,97 +6651,21 @@ class CheckEitherNonSmiInstr : public TemplateInstruction<2, NoThrow, Pure> { DISALLOW_COPY_AND_ASSIGN(CheckEitherNonSmiInstr); }; -class Boxing : public AllStatic { - public: - static bool Supports(Representation rep) { - switch (rep) { - case kUnboxedDouble: - case kUnboxedFloat32x4: - case kUnboxedFloat64x2: - case kUnboxedInt32x4: - case kUnboxedInt64: - case kUnboxedInt32: - case kUnboxedUint32: - return true; - default: - return false; - } - } +struct Boxing : public AllStatic { + // Whether the given representation can be boxed or unboxed. + static bool Supports(Representation rep); - static bool RequiresAllocation(Representation rep) { - switch (rep) { - case kUnboxedDouble: - case kUnboxedFloat32x4: - case kUnboxedFloat64x2: - case kUnboxedInt32x4: - case kUnboxedInt64: - return true; - case kUnboxedInt32: - case kUnboxedUint32: - return kBitsPerInt32 > compiler::target::kSmiBits; - default: - UNREACHABLE(); - return true; - } - } + // Whether boxing this value requires allocating a new object. + static bool RequiresAllocation(Representation rep); - static intptr_t ValueOffset(Representation rep) { - switch (rep) { - case kUnboxedFloat: - case kUnboxedDouble: - return Double::value_offset(); + // The offset into the Layout object for the boxed value that can store + // the full range of values in the representation. + // Only defined for allocated boxes (i.e., RequiresAllocation must be true). + static intptr_t ValueOffset(Representation rep); - case kUnboxedFloat32x4: - return Float32x4::value_offset(); - - case kUnboxedFloat64x2: - return Float64x2::value_offset(); - - case kUnboxedInt32x4: - return Int32x4::value_offset(); - - case kUnboxedInt64: - return Mint::value_offset(); - - case kUnboxedInt32: - case kUnboxedUint32: - if (RequiresAllocation(rep)) { - return Mint::value_offset(); - } - UNREACHABLE(); - return 0; - - default: - UNREACHABLE(); - return 0; - } - } - - static intptr_t BoxCid(Representation rep) { - switch (rep) { - case kUnboxedInt32: - case kUnboxedUint32: - if (RequiresAllocation(rep)) { - return kMintCid; - } - UNREACHABLE(); - return kIllegalCid; - case kUnboxedInt64: - return kMintCid; - case kUnboxedDouble: - case kUnboxedFloat: - return kDoubleCid; - case kUnboxedFloat32x4: - return kFloat32x4Cid; - case kUnboxedFloat64x2: - return kFloat64x2Cid; - case kUnboxedInt32x4: - return kInt32x4Cid; - default: - UNREACHABLE(); - return kIllegalCid; - } - } + // The class ID for the boxed value that can store the full range + // of values in the representation. + static intptr_t BoxCid(Representation rep); }; class BoxInstr : public TemplateDefinition<1, NoThrow, Pure> { diff --git a/runtime/vm/compiler/backend/il_arm.cc b/runtime/vm/compiler/backend/il_arm.cc index bedb2ec6976..1c3daa9c038 100644 --- a/runtime/vm/compiler/backend/il_arm.cc +++ b/runtime/vm/compiler/backend/il_arm.cc @@ -672,14 +672,12 @@ void ConstantInstr::EmitNativeCode(FlowGraphCompiler* compiler) { void ConstantInstr::EmitMoveToLocation(FlowGraphCompiler* compiler, const Location& destination, Register tmp) { - const bool is_unboxed_int = - representation() == kUnboxedUint32 || representation() == kUnboxedInt32; if (destination.IsRegister()) { - if (is_unboxed_int) { + if (RepresentationUtils::IsUnboxedInteger(representation())) { int64_t v; const bool ok = compiler::HasIntegerValue(value_, &v); RELEASE_ASSERT(ok); - if (value_.IsSmi() && representation() == kUnboxedUint32) { + if (value_.IsSmi() && RepresentationUtils::IsUnsigned(representation())) { // If the value is negative, then the sign bit was preserved during // Smi untagging, which means the resulting value may be unexpected. ASSERT(v >= 0); @@ -713,7 +711,7 @@ void ConstantInstr::EmitMoveToLocation(FlowGraphCompiler* compiler, ASSERT(destination.IsStackSlot()); ASSERT(tmp != kNoRegister); const intptr_t dest_offset = destination.ToStackSlotOffset(); - if (is_unboxed_int) { + if (RepresentationUtils::IsUnboxedInteger(representation())) { int64_t v; const bool ok = compiler::HasIntegerValue(value_, &v); RELEASE_ASSERT(ok); @@ -728,7 +726,9 @@ void ConstantInstr::EmitMoveToLocation(FlowGraphCompiler* compiler, LocationSummary* UnboxedConstantInstr::MakeLocationSummary(Zone* zone, bool opt) const { const bool is_unboxed_int = - representation() == kUnboxedUint32 || representation() == kUnboxedInt32; + RepresentationUtils::IsUnboxedInteger(representation()); + ASSERT(!is_unboxed_int || RepresentationUtils::ValueSize(representation()) <= + compiler::target::kWordSize); const intptr_t kNumInputs = 0; const intptr_t kNumTemps = is_unboxed_int ? 0 : 1; LocationSummary* locs = new (zone) @@ -4826,6 +4826,7 @@ void BoxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { } LocationSummary* UnboxInstr::MakeLocationSummary(Zone* zone, bool opt) const { + ASSERT(BoxCid() != kSmiCid); const bool needs_temp = CanDeoptimize(); const intptr_t kNumInputs = 1; const intptr_t kNumTemps = needs_temp ? 1 : 0; diff --git a/runtime/vm/compiler/backend/il_arm64.cc b/runtime/vm/compiler/backend/il_arm64.cc index 51f63300714..8b5e74633b9 100644 --- a/runtime/vm/compiler/backend/il_arm64.cc +++ b/runtime/vm/compiler/backend/il_arm64.cc @@ -619,23 +619,26 @@ void ConstantInstr::EmitMoveToLocation(FlowGraphCompiler* compiler, LocationSummary* UnboxedConstantInstr::MakeLocationSummary(Zone* zone, bool opt) const { + const bool is_unboxed_int = + RepresentationUtils::IsUnboxedInteger(representation()); + ASSERT(!is_unboxed_int || RepresentationUtils::ValueSize(representation()) <= + compiler::target::kWordSize); const intptr_t kNumInputs = 0; - const intptr_t kNumTemps = IsUnboxedSignedIntegerConstant() ? 0 : 1; + const intptr_t kNumTemps = is_unboxed_int ? 0 : 1; LocationSummary* locs = new (zone) LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); - switch (representation()) { - case kUnboxedDouble: - locs->set_out(0, Location::RequiresFpuRegister()); - locs->set_temp(0, Location::RequiresRegister()); - break; - case kUnboxedInt32: - case kUnboxedUint32: - case kUnboxedInt64: - locs->set_out(0, Location::RequiresRegister()); - break; - default: - UNREACHABLE(); - break; + if (is_unboxed_int) { + locs->set_out(0, Location::RequiresRegister()); + } else { + switch (representation()) { + case kUnboxedDouble: + locs->set_out(0, Location::RequiresFpuRegister()); + locs->set_temp(0, Location::RequiresRegister()); + break; + default: + UNREACHABLE(); + break; + } } return locs; } @@ -643,7 +646,9 @@ LocationSummary* UnboxedConstantInstr::MakeLocationSummary(Zone* zone, void UnboxedConstantInstr::EmitNativeCode(FlowGraphCompiler* compiler) { if (!locs()->out(0).IsInvalid()) { const Register scratch = - IsUnboxedSignedIntegerConstant() ? kNoRegister : locs()->temp(0).reg(); + RepresentationUtils::IsUnboxedInteger(representation()) + ? kNoRegister + : locs()->temp(0).reg(); EmitMoveToLocation(compiler, locs()->out(0), scratch); } } @@ -835,29 +840,29 @@ static Condition EmitInt64ComparisonOp(FlowGraphCompiler* compiler, Condition true_condition = TokenKindToSmiCondition(kind); if (left.IsConstant() || right.IsConstant()) { // Ensure constant is on the right. - ConstantInstr* right_constant = NULL; + ConstantInstr* constant = nullptr; if (left.IsConstant()) { - right_constant = left.constant_instruction(); + constant = left.constant_instruction(); Location tmp = right; right = left; left = tmp; true_condition = FlipCondition(true_condition); } else { - right_constant = right.constant_instruction(); + constant = right.constant_instruction(); } - if (right_constant->IsUnboxedSignedIntegerConstant()) { - const int64_t constant = - right_constant->GetUnboxedSignedIntegerConstantValue(); - if (constant == 0 && CanUseCbzTbzForComparison(compiler, left.reg(), - true_condition, labels)) { + if (RepresentationUtils::IsUnboxedInteger(constant->representation())) { + int64_t value; + const bool ok = compiler::HasIntegerValue(constant->value(), &value); + RELEASE_ASSERT(ok); + if (value == 0 && CanUseCbzTbzForComparison(compiler, left.reg(), + true_condition, labels)) { EmitCbzTbz(left.reg(), compiler, true_condition, labels); return kInvalidCondition; } - __ CompareImmediate( - left.reg(), right_constant->GetUnboxedSignedIntegerConstantValue()); + __ CompareImmediate(left.reg(), value); } else { - ASSERT(right_constant->representation() == kTagged); + ASSERT(constant->representation() == kTagged); __ CompareObject(left.reg(), right.constant()); } } else { @@ -4050,10 +4055,11 @@ void BoxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { } LocationSummary* UnboxInstr::MakeLocationSummary(Zone* zone, bool opt) const { + ASSERT(!RepresentationUtils::IsUnsigned(representation())); const intptr_t kNumInputs = 1; const intptr_t kNumTemps = 0; const bool is_floating_point = - representation() != kUnboxedInt64 && representation() != kUnboxedInt32; + !RepresentationUtils::IsUnboxedInteger(representation()); LocationSummary* summary = new (zone) LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); summary->set_in(0, Location::RequiresRegister()); @@ -4103,6 +4109,7 @@ void UnboxInstr::EmitSmiConversion(FlowGraphCompiler* compiler) { const Register box = locs()->in(0).reg(); switch (representation()) { + case kUnboxedInt32: case kUnboxedInt64: { const Register result = locs()->out(0).reg(); __ SmiUntag(result, box); @@ -5855,9 +5862,9 @@ void BinaryInt64OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { } else if (op_kind() == Token::kMUL) { Register r = TMP; if (right.IsConstant()) { - ConstantInstr* constant_instr = right.constant_instruction(); - const int64_t value = - constant_instr->GetUnboxedSignedIntegerConstantValue(); + int64_t value; + const bool ok = compiler::HasIntegerValue(right.constant(), &value); + RELEASE_ASSERT(ok); __ LoadImmediate(r, value); } else { r = right.reg(); @@ -5867,9 +5874,9 @@ void BinaryInt64OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { } if (right.IsConstant()) { - ConstantInstr* constant_instr = right.constant_instruction(); - const int64_t value = - constant_instr->GetUnboxedSignedIntegerConstantValue(); + int64_t value; + const bool ok = compiler::HasIntegerValue(right.constant(), &value); + RELEASE_ASSERT(ok); switch (op_kind()) { case Token::kADD: __ AddImmediate(out, left, value); diff --git a/runtime/vm/compiler/backend/il_ia32.cc b/runtime/vm/compiler/backend/il_ia32.cc index 4a2ad851d34..45958f9eb62 100644 --- a/runtime/vm/compiler/backend/il_ia32.cc +++ b/runtime/vm/compiler/backend/il_ia32.cc @@ -397,14 +397,12 @@ void ConstantInstr::EmitNativeCode(FlowGraphCompiler* compiler) { void ConstantInstr::EmitMoveToLocation(FlowGraphCompiler* compiler, const Location& destination, Register tmp) { - const bool is_unboxed_int = - representation() == kUnboxedUint32 || representation() == kUnboxedInt32; if (destination.IsRegister()) { - if (is_unboxed_int) { + if (RepresentationUtils::IsUnboxedInteger(representation())) { int64_t v; const bool ok = compiler::HasIntegerValue(value_, &v); RELEASE_ASSERT(ok); - if (value_.IsSmi() && representation() == kUnboxedUint32) { + if (value_.IsSmi() && RepresentationUtils::IsUnsigned(representation())) { // If the value is negative, then the sign bit was preserved during // Smi untagging, which means the resulting value may be unexpected. ASSERT(v >= 0); @@ -444,7 +442,8 @@ void ConstantInstr::EmitMoveToLocation(FlowGraphCompiler* compiler, __ movsd(LocationToStackSlotAddress(destination), FpuTMP); } else { ASSERT(destination.IsStackSlot()); - if (value_.IsSmi() && is_unboxed_int) { + if (value_.IsSmi() && + RepresentationUtils::IsUnboxedInteger(representation())) { __ movl(LocationToStackSlotAddress(destination), compiler::Immediate(Smi::Cast(value_).Value())); } else { @@ -464,7 +463,9 @@ void ConstantInstr::EmitMoveToLocation(FlowGraphCompiler* compiler, LocationSummary* UnboxedConstantInstr::MakeLocationSummary(Zone* zone, bool opt) const { const bool is_unboxed_int = - representation() == kUnboxedUint32 || representation() == kUnboxedInt32; + RepresentationUtils::IsUnboxedInteger(representation()); + ASSERT(!is_unboxed_int || RepresentationUtils::ValueSize(representation()) <= + compiler::target::kWordSize); const intptr_t kNumInputs = 0; const intptr_t kNumTemps = (constant_address() == 0) && !is_unboxed_int ? 1 : 0; @@ -3758,6 +3759,7 @@ void BoxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { } LocationSummary* UnboxInstr::MakeLocationSummary(Zone* zone, bool opt) const { + ASSERT(BoxCid() != kSmiCid); const bool needs_temp = CanDeoptimize() || (CanConvertSmi() && (value()->Type()->ToCid() == kSmiCid)); diff --git a/runtime/vm/compiler/backend/il_x64.cc b/runtime/vm/compiler/backend/il_x64.cc index a803165ceee..94c6beee901 100644 --- a/runtime/vm/compiler/backend/il_x64.cc +++ b/runtime/vm/compiler/backend/il_x64.cc @@ -510,9 +510,7 @@ void ConstantInstr::EmitMoveToLocation(FlowGraphCompiler* compiler, const Location& destination, Register tmp) { if (destination.IsRegister()) { - if (representation() == kUnboxedInt32 || - representation() == kUnboxedUint32 || - representation() == kUnboxedInt64) { + if (RepresentationUtils::IsUnboxedInteger(representation())) { const int64_t value = Integer::Cast(value_).AsInt64Value(); if (value == 0) { __ xorl(destination.reg(), destination.reg()); @@ -543,9 +541,7 @@ void ConstantInstr::EmitMoveToLocation(FlowGraphCompiler* compiler, __ movsd(LocationToStackSlotAddress(destination), FpuTMP); } else { ASSERT(destination.IsStackSlot()); - if (representation() == kUnboxedInt32 || - representation() == kUnboxedUint32 || - representation() == kUnboxedInt64) { + if (RepresentationUtils::IsUnboxedInteger(representation())) { const int64_t value = Integer::Cast(value_).AsInt64Value(); __ movq(LocationToStackSlotAddress(destination), compiler::Immediate(value)); @@ -558,23 +554,26 @@ void ConstantInstr::EmitMoveToLocation(FlowGraphCompiler* compiler, LocationSummary* UnboxedConstantInstr::MakeLocationSummary(Zone* zone, bool opt) const { + const bool is_unboxed_int = + RepresentationUtils::IsUnboxedInteger(representation()); + ASSERT(!is_unboxed_int || RepresentationUtils::ValueSize(representation()) <= + compiler::target::kWordSize); const intptr_t kNumInputs = 0; - const intptr_t kNumTemps = IsUnboxedSignedIntegerConstant() ? 0 : 1; + const intptr_t kNumTemps = is_unboxed_int ? 0 : 1; LocationSummary* locs = new (zone) LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); - switch (representation()) { - case kUnboxedDouble: - locs->set_out(0, Location::RequiresFpuRegister()); - locs->set_temp(0, Location::RequiresRegister()); - break; - case kUnboxedInt32: - case kUnboxedUint32: - case kUnboxedInt64: - locs->set_out(0, Location::RequiresRegister()); - break; - default: - UNREACHABLE(); - break; + if (is_unboxed_int) { + locs->set_out(0, Location::RequiresRegister()); + } else { + switch (representation()) { + case kUnboxedDouble: + locs->set_out(0, Location::RequiresFpuRegister()); + locs->set_temp(0, Location::RequiresRegister()); + break; + default: + UNREACHABLE(); + break; + } } return locs; } @@ -583,7 +582,9 @@ void UnboxedConstantInstr::EmitNativeCode(FlowGraphCompiler* compiler) { // The register allocator drops constant definitions that have no uses. if (!locs()->out(0).IsInvalid()) { const Register scratch = - IsUnboxedSignedIntegerConstant() ? kNoRegister : locs()->temp(0).reg(); + RepresentationUtils::IsUnboxedInteger(representation()) + ? kNoRegister + : locs()->temp(0).reg(); EmitMoveToLocation(compiler, locs()->out(0), scratch); } } @@ -794,10 +795,11 @@ static Condition EmitInt64ComparisonOp(FlowGraphCompiler* compiler, constant = right.constant_instruction(); } - if (constant->IsUnboxedSignedIntegerConstant()) { - __ cmpq(left.reg(), - compiler::Immediate( - constant->GetUnboxedSignedIntegerConstantValue())); + if (RepresentationUtils::IsUnboxedInteger(constant->representation())) { + int64_t value; + const bool ok = compiler::HasIntegerValue(constant->value(), &value); + RELEASE_ASSERT(ok); + __ cmpq(left.reg(), compiler::Immediate(value)); } else { ASSERT(constant->representation() == kTagged); __ CompareObject(left.reg(), right.constant()); @@ -4270,6 +4272,7 @@ void BoxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { } LocationSummary* UnboxInstr::MakeLocationSummary(Zone* zone, bool opt) const { + ASSERT(!RepresentationUtils::IsUnsigned(representation())); const intptr_t kNumInputs = 1; const intptr_t kNumTemps = 0; const bool needs_writable_input = @@ -4279,7 +4282,7 @@ LocationSummary* UnboxInstr::MakeLocationSummary(Zone* zone, bool opt) const { LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); summary->set_in(0, needs_writable_input ? Location::WritableRegister() : Location::RequiresRegister()); - if (representation() == kUnboxedInt64 || representation() == kUnboxedInt32) { + if (RepresentationUtils::IsUnboxedInteger(representation())) { summary->set_out(0, Location::SameAsFirstInput()); } else { summary->set_out(0, Location::RequiresFpuRegister()); @@ -4328,6 +4331,7 @@ void UnboxInstr::EmitSmiConversion(FlowGraphCompiler* compiler) { const Register box = locs()->in(0).reg(); switch (representation()) { + case kUnboxedInt32: case kUnboxedInt64: { const Register result = locs()->out(0).reg(); ASSERT(result == box); @@ -6253,9 +6257,9 @@ void BinaryInt64OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { temp.reg(), out.reg()); } else if (right.IsConstant()) { ASSERT(out.reg() == left.reg()); - ConstantInstr* constant_instr = right.constant_instruction(); - const int64_t value = - constant_instr->GetUnboxedSignedIntegerConstantValue(); + int64_t value; + const bool ok = compiler::HasIntegerValue(right.constant(), &value); + RELEASE_ASSERT(ok); EmitInt64Arithmetic(compiler, op_kind(), left.reg(), compiler::Immediate(value)); } else { diff --git a/runtime/vm/compiler/backend/locations.cc b/runtime/vm/compiler/backend/locations.cc index 2c40969dfaa..d31957cfe3d 100644 --- a/runtime/vm/compiler/backend/locations.cc +++ b/runtime/vm/compiler/backend/locations.cc @@ -11,9 +11,57 @@ namespace dart { +#define REP_IN_SET_CLAUSE(name, __, ___) \ + case k##name: \ + return true; +#define REP_SIZEOF_CLAUSE(name, __, type) \ + case k##name: \ + return sizeof(type); +#define REP_IS_UNSIGNED_CLAUSE(name, unsigned, ___) \ + case k##name: \ + return unsigned; + +bool RepresentationUtils::IsUnboxedInteger(Representation rep) { + switch (rep) { + FOR_EACH_INTEGER_REPRESENTATION_KIND(REP_IN_SET_CLAUSE) + default: + return false; + } +} + +bool RepresentationUtils::IsUnboxed(Representation rep) { + switch (rep) { + FOR_EACH_UNBOXED_REPRESENTATION_KIND(REP_IN_SET_CLAUSE) + default: + return false; + } +} + +size_t RepresentationUtils::ValueSize(Representation rep) { + switch (rep) { + FOR_EACH_SIMPLE_REPRESENTATION_KIND(REP_SIZEOF_CLAUSE) + default: + UNREACHABLE(); + return compiler::target::kWordSize; + } +} + +bool RepresentationUtils::IsUnsigned(Representation rep) { + switch (rep) { + FOR_EACH_SIMPLE_REPRESENTATION_KIND(REP_IS_UNSIGNED_CLAUSE) + default: + UNREACHABLE(); + return false; + } +} + +#undef REP_IS_UNSIGNED_CLAUSE +#undef REP_SIZEOF_CLAUSE +#undef REP_IN_SET_CLAUSE + const char* Location::RepresentationToCString(Representation repr) { switch (repr) { -#define REPR_CASE(Name) \ +#define REPR_CASE(Name, __, ___) \ case k##Name: \ return #Name; FOR_EACH_REPRESENTATION_KIND(REPR_CASE) @@ -26,7 +74,7 @@ const char* Location::RepresentationToCString(Representation repr) { bool Location::ParseRepresentation(const char* str, Representation* out) { ASSERT(str != nullptr && out != nullptr); -#define KIND_CASE(Name) \ +#define KIND_CASE(Name, __, ___) \ if (strcmp(str, #Name) == 0) { \ *out = k##Name; \ return true; \ diff --git a/runtime/vm/compiler/backend/locations.h b/runtime/vm/compiler/backend/locations.h index 34edf4c510a..8f4c37ff26e 100644 --- a/runtime/vm/compiler/backend/locations.h +++ b/runtime/vm/compiler/backend/locations.h @@ -24,27 +24,60 @@ class Definition; class PairLocation; class Value; +// All unboxed integer representations. +// Format: (representation name, is unsigned, value type) +#define FOR_EACH_INTEGER_REPRESENTATION_KIND(M) \ + M(UnboxedInt32, false, int32_t) \ + M(UnboxedUint32, true, uint32_t) \ + M(UnboxedInt64, false, int64_t) + +// All unboxed representations. +// Format: (representation name, is unsigned, value type) +#define FOR_EACH_UNBOXED_REPRESENTATION_KIND(M) \ + M(UnboxedDouble, false, double_t) \ + M(UnboxedFloat, false, float_t) \ + FOR_EACH_INTEGER_REPRESENTATION_KIND(M) \ + M(UnboxedFloat32x4, false, simd128_value_t) \ + M(UnboxedInt32x4, false, simd128_value_t) \ + M(UnboxedFloat64x2, false, simd128_value_t) + +// All representations that represent a single boxed or unboxed value. +// (Note that packed SIMD values are considered a single value here.) +// Format: (representation name, is unsigned, value type) +#define FOR_EACH_SIMPLE_REPRESENTATION_KIND(M) \ + M(Tagged, false, compiler::target::word) \ + M(Untagged, false, compiler::target::word) \ + FOR_EACH_UNBOXED_REPRESENTATION_KIND(M) + +// All representations, including sentinel and multi-value representations. +// Format: (representation name, _, _) (only the name is guaranteed to exist) +// Ordered so that NoRepresentation is first (and thus 0 in the enum). #define FOR_EACH_REPRESENTATION_KIND(M) \ - M(NoRepresentation) \ - M(Tagged) \ - M(Untagged) \ - M(UnboxedDouble) \ - M(UnboxedFloat) \ - M(UnboxedInt32) \ - M(UnboxedUint32) \ - M(UnboxedInt64) \ - M(UnboxedFloat32x4) \ - M(UnboxedInt32x4) \ - M(UnboxedFloat64x2) \ - M(PairOfTagged) + M(NoRepresentation, _, _) \ + FOR_EACH_SIMPLE_REPRESENTATION_KIND(M) \ + M(PairOfTagged, _, _) enum Representation { -#define DECLARE_REPRESENTATION(name) k##name, +#define DECLARE_REPRESENTATION(name, __, ___) k##name, FOR_EACH_REPRESENTATION_KIND(DECLARE_REPRESENTATION) #undef DECLARE_REPRESENTATION kNumRepresentations }; +struct RepresentationUtils : AllStatic { + // Whether the representation is for a type of unboxed integer. + static bool IsUnboxedInteger(Representation rep); + + // Whether the representation is for a type of unboxed value. + static bool IsUnboxed(Representation rep); + + // The size of values described by this representation. + static size_t ValueSize(Representation rep); + + // Whether the values described by this representation are unsigned integers. + static bool IsUnsigned(Representation rep); +}; + // '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 diff --git a/runtime/vm/compiler/backend/slot.cc b/runtime/vm/compiler/backend/slot.cc index a8a9ec074ea..5f256b66e6b 100644 --- a/runtime/vm/compiler/backend/slot.cc +++ b/runtime/vm/compiler/backend/slot.cc @@ -46,16 +46,15 @@ class SlotCache : public ZoneAllocated { DirectChainedHashMap > fields_; }; -#define NATIVE_SLOT_NAME(C, F, id, M) Kind::k##C##_##F -#define NATIVE_TO_STR(C, F, id, M) #C "_" #F +#define NATIVE_SLOT_NAME(C, F) Kind::k##C##_##F +#define NATIVE_TO_STR(C, F) #C "_" #F const char* Slot::KindToCString(Kind k) { switch (k) { -#define NATIVE_CASE(C, U, F, id, M) \ - case NATIVE_SLOT_NAME(C, F, id, M): \ - return NATIVE_TO_STR(C, F, id, M); - BOXED_NATIVE_SLOTS_LIST(NATIVE_CASE) - UNBOXED_NATIVE_SLOTS_LIST(NATIVE_CASE) +#define NATIVE_CASE(C, __, F, ___, ____) \ + case NATIVE_SLOT_NAME(C, F): \ + return NATIVE_TO_STR(C, F); + NATIVE_SLOTS_LIST(NATIVE_CASE) #undef NATIVE_CASE case Kind::kTypeArguments: return "TypeArguments"; @@ -71,13 +70,12 @@ const char* Slot::KindToCString(Kind k) { bool Slot::ParseKind(const char* str, Kind* out) { ASSERT(str != nullptr && out != nullptr); -#define NATIVE_CASE(C, U, F, id, M) \ - if (strcmp(str, NATIVE_TO_STR(C, F, id, M)) == 0) { \ - *out = NATIVE_SLOT_NAME(C, F, id, M); \ +#define NATIVE_CASE(C, __, F, ___, ____) \ + if (strcmp(str, NATIVE_TO_STR(C, F)) == 0) { \ + *out = NATIVE_SLOT_NAME(C, F); \ return true; \ } - BOXED_NATIVE_SLOTS_LIST(NATIVE_CASE) - UNBOXED_NATIVE_SLOTS_LIST(NATIVE_CASE) + NATIVE_SLOTS_LIST(NATIVE_CASE) #undef NATIVE_CASE if (strcmp(str, "TypeArguments") == 0) { *out = Kind::kTypeArguments; @@ -97,31 +95,11 @@ bool Slot::ParseKind(const char* str, Kind* out) { #undef NATIVE_TO_STR #undef NATIVE_SLOT_NAME -static Representation CheckFit(Representation rep) { - ASSERT(Boxing::Supports(rep)); - switch (rep) { - case kUnboxedInt64: - case kUnboxedInt32: - case kUnboxedUint32: - break; - default: - UNREACHABLE(); - break; - } - return rep; -} - static classid_t GetUnboxedNativeSlotCid(Representation rep) { - ASSERT(Boxing::Supports(rep)); - if (Boxing::RequiresAllocation(rep)) { + // Currently we only support integer unboxed fields. + if (RepresentationUtils::IsUnboxedInteger(rep)) { return Boxing::BoxCid(rep); } -#if defined(TARGET_ARCH_IS_64_BIT) - // On 64-bit platforms, these always fit in Smis. - if (rep == kUnboxedInt32 || rep == kUnboxedUint32) { - return kSmiCid; - } -#endif UNREACHABLE(); return kIllegalCid; } @@ -130,30 +108,45 @@ const Slot& Slot::GetNativeSlot(Kind kind) { // There is a fixed statically known number of native slots so we cache // them statically. static const Slot fields[] = { -#define FIELD_FINAL (IsImmutableBit::encode(true)) -#define FIELD_VAR (0) -#define DEFINE_BOXED_NATIVE_FIELD(ClassName, UnderlyingType, FieldName, cid, \ - mutability) \ - Slot(Kind::k##ClassName##_##FieldName, FIELD_##mutability, k##cid##Cid, \ - compiler::target::ClassName::FieldName##_offset(), \ +#define NULLABLE_FIELD_FINAL \ + (IsNullableBit::encode(true) | IsImmutableBit::encode(true)) +#define NULLABLE_FIELD_VAR (IsNullableBit::encode(true)) +#define DEFINE_NULLABLE_BOXED_NATIVE_FIELD(ClassName, UnderlyingType, \ + FieldName, cid, mutability) \ + Slot(Kind::k##ClassName##_##FieldName, NULLABLE_FIELD_##mutability, \ + k##cid##Cid, compiler::target::ClassName::FieldName##_offset(), \ #ClassName "." #FieldName, nullptr, kTagged), - BOXED_NATIVE_SLOTS_LIST(DEFINE_BOXED_NATIVE_FIELD) + NULLABLE_BOXED_NATIVE_SLOTS_LIST(DEFINE_NULLABLE_BOXED_NATIVE_FIELD) -#undef DEFINE_BOXED_NATIVE_FIELD +#undef DEFINE_NULLABLE_BOXED_NATIVE_FIELD +#undef NULLABLE_FIELD_FINAL +#undef NULLABLE_FIELD_VAR + +#define NONNULLABLE_FIELD_FINAL (Slot::IsImmutableBit::encode(true)) +#define NONNULLABLE_FIELD_VAR (0) +#define DEFINE_NONNULLABLE_BOXED_NATIVE_FIELD(ClassName, UnderlyingType, \ + FieldName, cid, mutability) \ + Slot(Kind::k##ClassName##_##FieldName, NONNULLABLE_FIELD_##mutability, \ + k##cid##Cid, compiler::target::ClassName::FieldName##_offset(), \ + #ClassName "." #FieldName, nullptr, kTagged), + + NONNULLABLE_BOXED_NATIVE_SLOTS_LIST( + DEFINE_NONNULLABLE_BOXED_NATIVE_FIELD) + +#undef DEFINE_NONNULLABLE_BOXED_NATIVE_FIELD #define DEFINE_UNBOXED_NATIVE_FIELD(ClassName, UnderlyingType, FieldName, \ representation, mutability) \ - Slot(Kind::k##ClassName##_##FieldName, FIELD_##mutability, \ + Slot(Kind::k##ClassName##_##FieldName, NONNULLABLE_FIELD_##mutability, \ GetUnboxedNativeSlotCid(kUnboxed##representation), \ compiler::target::ClassName::FieldName##_offset(), \ - #ClassName "." #FieldName, nullptr, \ - CheckFit(kUnboxed##representation)), + #ClassName "." #FieldName, nullptr, kUnboxed##representation), - UNBOXED_NATIVE_SLOTS_LIST(DEFINE_UNBOXED_NATIVE_FIELD) + UNBOXED_NATIVE_SLOTS_LIST(DEFINE_UNBOXED_NATIVE_FIELD) #undef DEFINE_UNBOXED_NATIVE_FIELD -#undef FIELD_VAR -#undef FIELD_FINAL +#undef NONNULLABLE_FIELD_VAR +#undef NONNULLABLE_FIELD_FINAL }; ASSERT(static_cast(kind) < ARRAY_SIZE(fields)); diff --git a/runtime/vm/compiler/backend/slot.h b/runtime/vm/compiler/backend/slot.h index 6b2bd688068..c73b017ca2c 100644 --- a/runtime/vm/compiler/backend/slot.h +++ b/runtime/vm/compiler/backend/slot.h @@ -38,8 +38,8 @@ class LocalScope; class LocalVariable; class ParsedFunction; -// List of slots that correspond to fields of native objects in the following -// format: +// The list of slots that correspond to nullable boxed fields of native objects +// in the following format: // // V(class_name, underlying_type, field_name, exact_type, FINAL|VAR) // @@ -51,20 +51,34 @@ class ParsedFunction; // - the last component specifies whether field behaves like a final field // (i.e. initialized once at construction time and does not change after // that) or like a non-final field. -// -// Note: native slots are expected to be non-nullable. -#define BOXED_NATIVE_SLOTS_LIST(V) \ - V(Array, ArrayLayout, length, Smi, FINAL) \ +#define NULLABLE_BOXED_NATIVE_SLOTS_LIST(V) \ V(Context, ContextLayout, parent, Context, FINAL) \ V(Closure, ClosureLayout, instantiator_type_arguments, TypeArguments, FINAL) \ V(Closure, ClosureLayout, delayed_type_arguments, TypeArguments, FINAL) \ V(Closure, ClosureLayout, function_type_arguments, TypeArguments, FINAL) \ + V(Function, FunctionLayout, type_parameters, TypeArguments, FINAL) \ + V(Type, TypeLayout, arguments, TypeArguments, FINAL) + +// The list of slots that correspond to non-nullable boxed fields of native +// objects in the following format: +// +// V(class_name, underlying_type, field_name, exact_type, FINAL|VAR) +// +// - class_name and field_name specify the name of the host class and the name +// of the field respectively; +// - underlying_type: the Raw class which holds the field; +// - exact_type specifies exact type of the field (any load from this field +// would only yield instances of this type); +// - the last component specifies whether field behaves like a final field +// (i.e. initialized once at construction time and does not change after +// that) or like a non-final field. +#define NONNULLABLE_BOXED_NATIVE_SLOTS_LIST(V) \ + V(Array, ArrayLayout, length, Smi, FINAL) \ V(Closure, ClosureLayout, function, Function, FINAL) \ V(Closure, ClosureLayout, context, Context, FINAL) \ V(Closure, ClosureLayout, hash, Context, VAR) \ V(Function, FunctionLayout, parameter_names, Array, FINAL) \ V(Function, FunctionLayout, parameter_types, Array, FINAL) \ - V(Function, FunctionLayout, type_parameters, Array, FINAL) \ V(GrowableObjectArray, GrowableObjectArrayLayout, length, Smi, VAR) \ V(GrowableObjectArray, GrowableObjectArrayLayout, data, Array, VAR) \ V(TypedDataBase, TypedDataBaseLayout, length, Smi, FINAL) \ @@ -81,7 +95,6 @@ class ParsedFunction; V(ArgumentsDescriptor, ArrayLayout, count, Smi, FINAL) \ V(ArgumentsDescriptor, ArrayLayout, size, Smi, FINAL) \ V(PointerBase, PointerBaseLayout, data_field, Dynamic, FINAL) \ - V(Type, TypeLayout, arguments, TypeArguments, FINAL) \ V(UnhandledException, UnhandledExceptionLayout, exception, Dynamic, FINAL) \ V(UnhandledException, UnhandledExceptionLayout, stacktrace, Dynamic, FINAL) @@ -99,10 +112,18 @@ class ParsedFunction; // (i.e. initialized once at construction time and does not change after // that) or like a non-final field. // -// Note: As the underlying field is not boxed, these slots cannot be nullable. +// Note: As the underlying field is unboxed, these slots cannot be nullable. #define UNBOXED_NATIVE_SLOTS_LIST(V) \ V(Function, FunctionLayout, packed_fields, Uint32, FINAL) +// For uses that do not need the exact_type (boxed) or representation (unboxed) +// or whether a boxed native slot is nullable. (Generally, such users only need +// the class name, the underlying type, and/or the field name.) +#define NATIVE_SLOTS_LIST(V) \ + NULLABLE_BOXED_NATIVE_SLOTS_LIST(V) \ + NONNULLABLE_BOXED_NATIVE_SLOTS_LIST(V) \ + UNBOXED_NATIVE_SLOTS_LIST(V) + // Slot is an abstraction that describes an readable (and possibly writeable) // location within an object. // @@ -115,10 +136,9 @@ class Slot : public ZoneAllocated { // clang-format off enum class Kind : uint8_t { // Native slots are identified by their kind - each native slot has its own. -#define DECLARE_KIND(ClassName, UnderlyingType, FieldName, cid, mutability) \ +#define DECLARE_KIND(ClassName, __, FieldName, ___, ____) \ k##ClassName##_##FieldName, - BOXED_NATIVE_SLOTS_LIST(DECLARE_KIND) - UNBOXED_NATIVE_SLOTS_LIST(DECLARE_KIND) + NATIVE_SLOTS_LIST(DECLARE_KIND) #undef DECLARE_KIND // A slot used to store type arguments. @@ -164,13 +184,12 @@ class Slot : public ZoneAllocated { const ParsedFunction* parsed_function); // Convenience getters for native slots. -#define DEFINE_GETTER(ClassName, UnderlyingType, FieldName, cid, mutability) \ +#define DEFINE_GETTER(ClassName, UnderlyingType, FieldName, __, ___) \ static const Slot& ClassName##_##FieldName() { \ return GetNativeSlot(Kind::k##ClassName##_##FieldName); \ } - BOXED_NATIVE_SLOTS_LIST(DEFINE_GETTER) - UNBOXED_NATIVE_SLOTS_LIST(DEFINE_GETTER) + NATIVE_SLOTS_LIST(DEFINE_GETTER) #undef DEFINE_GETTER Kind kind() const { return kind_; } diff --git a/runtime/vm/compiler/runtime_api.h b/runtime/vm/compiler/runtime_api.h index 572f0a00df1..048038e1546 100644 --- a/runtime/vm/compiler/runtime_api.h +++ b/runtime/vm/compiler/runtime_api.h @@ -714,6 +714,7 @@ class ExternalTwoByteString : public AllStatic { class Int32x4 : public AllStatic { public: + static word value_offset(); static word InstanceSize(); static word NextFieldOffset(); }; diff --git a/runtime/vm/compiler/runtime_offsets_extracted.h b/runtime/vm/compiler/runtime_offsets_extracted.h index 63f65ca106a..6320c51c5a0 100644 --- a/runtime/vm/compiler/runtime_offsets_extracted.h +++ b/runtime/vm/compiler/runtime_offsets_extracted.h @@ -146,6 +146,7 @@ static constexpr dart::compiler::target::word ICData_NumArgsTestedShift = 0; static constexpr dart::compiler::target::word ICData_entries_offset = 12; static constexpr dart::compiler::target::word ICData_owner_offset = 20; static constexpr dart::compiler::target::word ICData_state_bits_offset = 28; +static constexpr dart::compiler::target::word Int32x4_value_offset = 8; static constexpr dart::compiler::target::word Isolate_shared_class_table_offset = 36; static constexpr dart::compiler::target::word @@ -648,6 +649,7 @@ static constexpr dart::compiler::target::word ICData_NumArgsTestedShift = 0; static constexpr dart::compiler::target::word ICData_entries_offset = 24; static constexpr dart::compiler::target::word ICData_owner_offset = 40; static constexpr dart::compiler::target::word ICData_state_bits_offset = 52; +static constexpr dart::compiler::target::word Int32x4_value_offset = 8; static constexpr dart::compiler::target::word Isolate_shared_class_table_offset = 72; static constexpr dart::compiler::target::word @@ -1154,6 +1156,7 @@ static constexpr dart::compiler::target::word ICData_NumArgsTestedShift = 0; static constexpr dart::compiler::target::word ICData_entries_offset = 12; static constexpr dart::compiler::target::word ICData_owner_offset = 20; static constexpr dart::compiler::target::word ICData_state_bits_offset = 28; +static constexpr dart::compiler::target::word Int32x4_value_offset = 8; static constexpr dart::compiler::target::word Isolate_shared_class_table_offset = 36; static constexpr dart::compiler::target::word @@ -1653,6 +1656,7 @@ static constexpr dart::compiler::target::word ICData_NumArgsTestedShift = 0; static constexpr dart::compiler::target::word ICData_entries_offset = 24; static constexpr dart::compiler::target::word ICData_owner_offset = 40; static constexpr dart::compiler::target::word ICData_state_bits_offset = 52; +static constexpr dart::compiler::target::word Int32x4_value_offset = 8; static constexpr dart::compiler::target::word Isolate_shared_class_table_offset = 72; static constexpr dart::compiler::target::word @@ -2160,6 +2164,7 @@ static constexpr dart::compiler::target::word ICData_NumArgsTestedShift = 0; static constexpr dart::compiler::target::word ICData_entries_offset = 12; static constexpr dart::compiler::target::word ICData_owner_offset = 20; static constexpr dart::compiler::target::word ICData_state_bits_offset = 28; +static constexpr dart::compiler::target::word Int32x4_value_offset = 8; static constexpr dart::compiler::target::word Isolate_shared_class_table_offset = 36; static constexpr dart::compiler::target::word @@ -2656,6 +2661,7 @@ static constexpr dart::compiler::target::word ICData_NumArgsTestedShift = 0; static constexpr dart::compiler::target::word ICData_entries_offset = 24; static constexpr dart::compiler::target::word ICData_owner_offset = 40; static constexpr dart::compiler::target::word ICData_state_bits_offset = 52; +static constexpr dart::compiler::target::word Int32x4_value_offset = 8; static constexpr dart::compiler::target::word Isolate_shared_class_table_offset = 72; static constexpr dart::compiler::target::word @@ -3156,6 +3162,7 @@ static constexpr dart::compiler::target::word ICData_NumArgsTestedShift = 0; static constexpr dart::compiler::target::word ICData_entries_offset = 12; static constexpr dart::compiler::target::word ICData_owner_offset = 20; static constexpr dart::compiler::target::word ICData_state_bits_offset = 28; +static constexpr dart::compiler::target::word Int32x4_value_offset = 8; static constexpr dart::compiler::target::word Isolate_shared_class_table_offset = 36; static constexpr dart::compiler::target::word @@ -3649,6 +3656,7 @@ static constexpr dart::compiler::target::word ICData_NumArgsTestedShift = 0; static constexpr dart::compiler::target::word ICData_entries_offset = 24; static constexpr dart::compiler::target::word ICData_owner_offset = 40; static constexpr dart::compiler::target::word ICData_state_bits_offset = 52; +static constexpr dart::compiler::target::word Int32x4_value_offset = 8; static constexpr dart::compiler::target::word Isolate_shared_class_table_offset = 72; static constexpr dart::compiler::target::word @@ -4158,6 +4166,7 @@ static constexpr dart::compiler::target::word AOT_ICData_NumArgsTestedShift = 0; static constexpr dart::compiler::target::word AOT_ICData_entries_offset = 12; static constexpr dart::compiler::target::word AOT_ICData_owner_offset = 16; static constexpr dart::compiler::target::word AOT_ICData_state_bits_offset = 20; +static constexpr dart::compiler::target::word AOT_Int32x4_value_offset = 8; static constexpr dart::compiler::target::word AOT_Isolate_shared_class_table_offset = 36; static constexpr dart::compiler::target::word @@ -4712,6 +4721,7 @@ static constexpr dart::compiler::target::word AOT_ICData_NumArgsTestedShift = 0; static constexpr dart::compiler::target::word AOT_ICData_entries_offset = 24; static constexpr dart::compiler::target::word AOT_ICData_owner_offset = 32; static constexpr dart::compiler::target::word AOT_ICData_state_bits_offset = 40; +static constexpr dart::compiler::target::word AOT_Int32x4_value_offset = 8; static constexpr dart::compiler::target::word AOT_Isolate_shared_class_table_offset = 72; static constexpr dart::compiler::target::word @@ -5272,6 +5282,7 @@ static constexpr dart::compiler::target::word AOT_ICData_NumArgsTestedShift = 0; static constexpr dart::compiler::target::word AOT_ICData_entries_offset = 24; static constexpr dart::compiler::target::word AOT_ICData_owner_offset = 32; static constexpr dart::compiler::target::word AOT_ICData_state_bits_offset = 40; +static constexpr dart::compiler::target::word AOT_Int32x4_value_offset = 8; static constexpr dart::compiler::target::word AOT_Isolate_shared_class_table_offset = 72; static constexpr dart::compiler::target::word @@ -5829,6 +5840,7 @@ static constexpr dart::compiler::target::word AOT_ICData_NumArgsTestedShift = 0; static constexpr dart::compiler::target::word AOT_ICData_entries_offset = 12; static constexpr dart::compiler::target::word AOT_ICData_owner_offset = 16; static constexpr dart::compiler::target::word AOT_ICData_state_bits_offset = 20; +static constexpr dart::compiler::target::word AOT_Int32x4_value_offset = 8; static constexpr dart::compiler::target::word AOT_Isolate_shared_class_table_offset = 36; static constexpr dart::compiler::target::word @@ -6376,6 +6388,7 @@ static constexpr dart::compiler::target::word AOT_ICData_NumArgsTestedShift = 0; static constexpr dart::compiler::target::word AOT_ICData_entries_offset = 24; static constexpr dart::compiler::target::word AOT_ICData_owner_offset = 32; static constexpr dart::compiler::target::word AOT_ICData_state_bits_offset = 40; +static constexpr dart::compiler::target::word AOT_Int32x4_value_offset = 8; static constexpr dart::compiler::target::word AOT_Isolate_shared_class_table_offset = 72; static constexpr dart::compiler::target::word @@ -6929,6 +6942,7 @@ static constexpr dart::compiler::target::word AOT_ICData_NumArgsTestedShift = 0; static constexpr dart::compiler::target::word AOT_ICData_entries_offset = 24; static constexpr dart::compiler::target::word AOT_ICData_owner_offset = 32; static constexpr dart::compiler::target::word AOT_ICData_state_bits_offset = 40; +static constexpr dart::compiler::target::word AOT_Int32x4_value_offset = 8; static constexpr dart::compiler::target::word AOT_Isolate_shared_class_table_offset = 72; static constexpr dart::compiler::target::word diff --git a/runtime/vm/compiler/runtime_offsets_list.h b/runtime/vm/compiler/runtime_offsets_list.h index b477334bfc5..0dc6a352dd2 100644 --- a/runtime/vm/compiler/runtime_offsets_list.h +++ b/runtime/vm/compiler/runtime_offsets_list.h @@ -109,6 +109,7 @@ FIELD(ICData, entries_offset) \ FIELD(ICData, owner_offset) \ FIELD(ICData, state_bits_offset) \ + FIELD(Int32x4, value_offset) \ FIELD(Isolate, shared_class_table_offset) \ FIELD(Isolate, cached_class_table_table_offset) \ FIELD(Isolate, current_tag_offset) \ diff --git a/runtime/vm/compiler/write_barrier_elimination.cc b/runtime/vm/compiler/write_barrier_elimination.cc index 4d1e453f453..10b18c5af8f 100644 --- a/runtime/vm/compiler/write_barrier_elimination.cc +++ b/runtime/vm/compiler/write_barrier_elimination.cc @@ -329,14 +329,13 @@ bool WriteBarrierElimination::SlotEligibleForWBE(const Slot& slot) { case Slot::Kind::kDartField: // Instance return true; -#define FOR_EACH_NATIVE_SLOT(class, underlying_type, field, type, modifiers) \ +#define FOR_EACH_NATIVE_SLOT(class, underlying_type, field, __, ___) \ case Slot::Kind::k##class##_##field: \ return std::is_base_of::value || \ std::is_base_of::value || \ std::is_base_of::value; - BOXED_NATIVE_SLOTS_LIST(FOR_EACH_NATIVE_SLOT) - UNBOXED_NATIVE_SLOTS_LIST(FOR_EACH_NATIVE_SLOT) + NATIVE_SLOTS_LIST(FOR_EACH_NATIVE_SLOT) #undef FOR_EACH_NATIVE_SLOT default: