mirror of
https://github.com/dart-lang/sdk
synced 2024-09-05 00:13:50 +00:00
[vm, compiler] Don't touch memory in AssertBoolean and BooleanNegate.
AssertBoolean may assume its input is nullable bool. BooleanNegate may assume its input is non-nullable bool. Use fixed alignment bits to distinguish true, false and null. TEST=ci Change-Id: Ife694e66c1225d943881c2325cd67f18575a47e7 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/189240 Commit-Queue: Ryan Macnak <rmacnak@google.com> Reviewed-by: Alexander Markov <alexmarkov@google.com>
This commit is contained in:
parent
927d45d013
commit
d1605bc5c5
|
@ -4504,23 +4504,6 @@ LocationSummary* AssertBooleanInstr::MakeLocationSummary(Zone* zone,
|
|||
return locs;
|
||||
}
|
||||
|
||||
void AssertBooleanInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
// Check that the type of the value is allowed in conditional context.
|
||||
ASSERT(locs()->always_calls());
|
||||
|
||||
auto object_store = compiler->isolate_group()->object_store();
|
||||
const auto& assert_boolean_stub =
|
||||
Code::ZoneHandle(compiler->zone(), object_store->assert_boolean_stub());
|
||||
|
||||
compiler::Label done;
|
||||
__ CompareObject(AssertBooleanABI::kObjectReg, Object::null_instance());
|
||||
__ BranchIf(NOT_EQUAL, &done);
|
||||
compiler->GenerateStubCall(source(), assert_boolean_stub,
|
||||
/*kind=*/UntaggedPcDescriptors::kOther, locs(),
|
||||
deopt_id());
|
||||
__ Bind(&done);
|
||||
}
|
||||
|
||||
LocationSummary* PhiInstr::MakeLocationSummary(Zone* zone,
|
||||
bool optimizing) const {
|
||||
UNREACHABLE();
|
||||
|
|
|
@ -822,6 +822,23 @@ LocationSummary* AssertAssignableInstr::MakeLocationSummary(Zone* zone,
|
|||
return summary;
|
||||
}
|
||||
|
||||
void AssertBooleanInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
ASSERT(locs()->always_calls());
|
||||
|
||||
auto object_store = compiler->isolate_group()->object_store();
|
||||
const auto& assert_boolean_stub =
|
||||
Code::ZoneHandle(compiler->zone(), object_store->assert_boolean_stub());
|
||||
|
||||
compiler::Label done;
|
||||
__ tst(AssertBooleanABI::kObjectReg,
|
||||
compiler::Operand(compiler::target::ObjectAlignment::kBoolVsNullMask));
|
||||
__ b(&done, NOT_ZERO);
|
||||
compiler->GenerateStubCall(source(), assert_boolean_stub,
|
||||
/*kind=*/UntaggedPcDescriptors::kOther, locs(),
|
||||
deopt_id());
|
||||
__ Bind(&done);
|
||||
}
|
||||
|
||||
static Condition TokenKindToSmiCondition(Token::Kind kind) {
|
||||
switch (kind) {
|
||||
case Token::kEQ:
|
||||
|
@ -7895,16 +7912,8 @@ LocationSummary* BooleanNegateInstr::MakeLocationSummary(Zone* zone,
|
|||
void BooleanNegateInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
const Register input = locs()->in(0).reg();
|
||||
const Register result = locs()->out(0).reg();
|
||||
|
||||
if (value()->Type()->ToCid() == kBoolCid) {
|
||||
__ eor(
|
||||
result, input,
|
||||
compiler::Operand(compiler::target::ObjectAlignment::kBoolValueMask));
|
||||
} else {
|
||||
__ LoadObject(result, Bool::True());
|
||||
__ cmp(result, compiler::Operand(input));
|
||||
__ LoadObject(result, Bool::False(), EQ);
|
||||
}
|
||||
__ eor(result, input,
|
||||
compiler::Operand(compiler::target::ObjectAlignment::kBoolValueMask));
|
||||
}
|
||||
|
||||
LocationSummary* AllocateObjectInstr::MakeLocationSummary(Zone* zone,
|
||||
|
|
|
@ -720,6 +720,21 @@ LocationSummary* AssertAssignableInstr::MakeLocationSummary(Zone* zone,
|
|||
return summary;
|
||||
}
|
||||
|
||||
void AssertBooleanInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
ASSERT(locs()->always_calls());
|
||||
|
||||
auto object_store = compiler->isolate_group()->object_store();
|
||||
const auto& assert_boolean_stub =
|
||||
Code::ZoneHandle(compiler->zone(), object_store->assert_boolean_stub());
|
||||
|
||||
compiler::Label done;
|
||||
__ tbnz(&done, AssertBooleanABI::kObjectReg, kBoolVsNullBitPosition);
|
||||
compiler->GenerateStubCall(source(), assert_boolean_stub,
|
||||
/*kind=*/UntaggedPcDescriptors::kOther, locs(),
|
||||
deopt_id());
|
||||
__ Bind(&done);
|
||||
}
|
||||
|
||||
static Condition TokenKindToSmiCondition(Token::Kind kind) {
|
||||
switch (kind) {
|
||||
case Token::kEQ:
|
||||
|
@ -6925,17 +6940,9 @@ LocationSummary* BooleanNegateInstr::MakeLocationSummary(Zone* zone,
|
|||
void BooleanNegateInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
const Register input = locs()->in(0).reg();
|
||||
const Register result = locs()->out(0).reg();
|
||||
|
||||
if (value()->Type()->ToCid() == kBoolCid) {
|
||||
__ eori(
|
||||
result, input,
|
||||
compiler::Immediate(compiler::target::ObjectAlignment::kBoolValueMask));
|
||||
} else {
|
||||
__ LoadObject(result, Bool::True());
|
||||
__ LoadObject(TMP, Bool::False());
|
||||
__ CompareRegisters(result, input);
|
||||
__ csel(result, TMP, result, EQ);
|
||||
}
|
||||
__ eori(
|
||||
result, input,
|
||||
compiler::Immediate(compiler::target::ObjectAlignment::kBoolValueMask));
|
||||
}
|
||||
|
||||
LocationSummary* AllocateObjectInstr::MakeLocationSummary(Zone* zone,
|
||||
|
|
|
@ -508,6 +508,24 @@ LocationSummary* AssertAssignableInstr::MakeLocationSummary(Zone* zone,
|
|||
return summary;
|
||||
}
|
||||
|
||||
void AssertBooleanInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
ASSERT(locs()->always_calls());
|
||||
|
||||
auto object_store = compiler->isolate_group()->object_store();
|
||||
const auto& assert_boolean_stub =
|
||||
Code::ZoneHandle(compiler->zone(), object_store->assert_boolean_stub());
|
||||
|
||||
compiler::Label done;
|
||||
__ testl(
|
||||
AssertBooleanABI::kObjectReg,
|
||||
compiler::Immediate(compiler::target::ObjectAlignment::kBoolVsNullMask));
|
||||
__ j(NOT_ZERO, &done, compiler::Assembler::kNearJump);
|
||||
compiler->GenerateStubCall(source(), assert_boolean_stub,
|
||||
/*kind=*/UntaggedPcDescriptors::kOther, locs(),
|
||||
deopt_id());
|
||||
__ Bind(&done);
|
||||
}
|
||||
|
||||
static Condition TokenKindToSmiCondition(Token::Kind kind) {
|
||||
switch (kind) {
|
||||
case Token::kEQ:
|
||||
|
@ -6836,30 +6854,16 @@ void ClosureCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
|||
|
||||
LocationSummary* BooleanNegateInstr::MakeLocationSummary(Zone* zone,
|
||||
bool opt) const {
|
||||
return LocationSummary::Make(zone, 1,
|
||||
value()->Type()->ToCid() == kBoolCid
|
||||
? Location::SameAsFirstInput()
|
||||
: Location::RequiresRegister(),
|
||||
return LocationSummary::Make(zone, 1, Location::SameAsFirstInput(),
|
||||
LocationSummary::kNoCall);
|
||||
}
|
||||
|
||||
void BooleanNegateInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
Register input = locs()->in(0).reg();
|
||||
Register result = locs()->out(0).reg();
|
||||
|
||||
if (value()->Type()->ToCid() == kBoolCid) {
|
||||
ASSERT(input == result);
|
||||
__ xorl(result, compiler::Immediate(
|
||||
compiler::target::ObjectAlignment::kBoolValueMask));
|
||||
} else {
|
||||
ASSERT(input != result);
|
||||
compiler::Label done;
|
||||
__ LoadObject(result, Bool::True());
|
||||
__ CompareRegisters(result, input);
|
||||
__ j(NOT_EQUAL, &done, compiler::Assembler::kNearJump);
|
||||
__ LoadObject(result, Bool::False());
|
||||
__ Bind(&done);
|
||||
}
|
||||
ASSERT(input == result);
|
||||
__ xorl(result, compiler::Immediate(
|
||||
compiler::target::ObjectAlignment::kBoolValueMask));
|
||||
}
|
||||
|
||||
LocationSummary* AllocateObjectInstr::MakeLocationSummary(Zone* zone,
|
||||
|
|
|
@ -656,6 +656,24 @@ LocationSummary* AssertAssignableInstr::MakeLocationSummary(Zone* zone,
|
|||
return summary;
|
||||
}
|
||||
|
||||
void AssertBooleanInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
ASSERT(locs()->always_calls());
|
||||
|
||||
auto object_store = compiler->isolate_group()->object_store();
|
||||
const auto& assert_boolean_stub =
|
||||
Code::ZoneHandle(compiler->zone(), object_store->assert_boolean_stub());
|
||||
|
||||
compiler::Label done;
|
||||
__ testq(
|
||||
AssertBooleanABI::kObjectReg,
|
||||
compiler::Immediate(compiler::target::ObjectAlignment::kBoolVsNullMask));
|
||||
__ j(NOT_ZERO, &done, compiler::Assembler::kNearJump);
|
||||
compiler->GenerateStubCall(source(), assert_boolean_stub,
|
||||
/*kind=*/UntaggedPcDescriptors::kOther, locs(),
|
||||
deopt_id());
|
||||
__ Bind(&done);
|
||||
}
|
||||
|
||||
static Condition TokenKindToIntCondition(Token::Kind kind) {
|
||||
switch (kind) {
|
||||
case Token::kEQ:
|
||||
|
@ -861,7 +879,6 @@ void ComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
|||
if (true_condition != kInvalidCondition) {
|
||||
EmitBranchOnCondition(compiler, true_condition, labels);
|
||||
}
|
||||
|
||||
Register result = locs()->out(0).reg();
|
||||
compiler::Label done;
|
||||
__ Bind(&is_false);
|
||||
|
@ -7417,30 +7434,16 @@ void ClosureCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
|||
|
||||
LocationSummary* BooleanNegateInstr::MakeLocationSummary(Zone* zone,
|
||||
bool opt) const {
|
||||
return LocationSummary::Make(zone, 1,
|
||||
value()->Type()->ToCid() == kBoolCid
|
||||
? Location::SameAsFirstInput()
|
||||
: Location::RequiresRegister(),
|
||||
return LocationSummary::Make(zone, 1, Location::SameAsFirstInput(),
|
||||
LocationSummary::kNoCall);
|
||||
}
|
||||
|
||||
void BooleanNegateInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
Register input = locs()->in(0).reg();
|
||||
Register result = locs()->out(0).reg();
|
||||
|
||||
if (value()->Type()->ToCid() == kBoolCid) {
|
||||
ASSERT(input == result);
|
||||
__ xorq(result, compiler::Immediate(
|
||||
compiler::target::ObjectAlignment::kBoolValueMask));
|
||||
} else {
|
||||
ASSERT(input != result);
|
||||
compiler::Label done;
|
||||
__ LoadObject(result, Bool::True());
|
||||
__ CompareRegisters(result, input);
|
||||
__ j(NOT_EQUAL, &done, compiler::Assembler::kNearJump);
|
||||
__ LoadObject(result, Bool::False());
|
||||
__ Bind(&done);
|
||||
}
|
||||
ASSERT(input == result);
|
||||
__ xorq(result, compiler::Immediate(
|
||||
compiler::target::ObjectAlignment::kBoolValueMask));
|
||||
}
|
||||
|
||||
LocationSummary* AllocateObjectInstr::MakeLocationSummary(Zone* zone,
|
||||
|
|
|
@ -569,6 +569,9 @@ void Object::InitNullAndBool(IsolateGroup* isolate_group) {
|
|||
ASSERT((static_cast<uword>(false_) & kBoolValueMask) != 0);
|
||||
ASSERT(static_cast<uword>(false_) ==
|
||||
(static_cast<uword>(true_) | kBoolValueMask));
|
||||
ASSERT((static_cast<uword>(null_) & kBoolVsNullMask) == 0);
|
||||
ASSERT((static_cast<uword>(true_) & kBoolVsNullMask) != 0);
|
||||
ASSERT((static_cast<uword>(false_) & kBoolVsNullMask) != 0);
|
||||
}
|
||||
|
||||
void Object::InitVtables() {
|
||||
|
@ -23581,23 +23584,6 @@ ExternalTwoByteStringPtr ExternalTwoByteString::New(
|
|||
return ExternalTwoByteString::raw(result);
|
||||
}
|
||||
|
||||
BoolPtr Bool::New(bool value) {
|
||||
ASSERT(IsolateGroup::Current()->object_store()->bool_class() !=
|
||||
Class::null());
|
||||
Bool& result = Bool::Handle();
|
||||
{
|
||||
// Since the two boolean instances are singletons we allocate them straight
|
||||
// in the old generation.
|
||||
ObjectPtr raw =
|
||||
Object::Allocate(Bool::kClassId, Bool::InstanceSize(), Heap::kOld);
|
||||
NoSafepointScope no_safepoint;
|
||||
result ^= raw;
|
||||
}
|
||||
result.set_value(value);
|
||||
result.SetCanonical();
|
||||
return result.ptr();
|
||||
}
|
||||
|
||||
const char* Bool::ToCString() const {
|
||||
return value() ? "true" : "false";
|
||||
}
|
||||
|
|
|
@ -9583,11 +9583,6 @@ class Bool : public Instance {
|
|||
}
|
||||
|
||||
private:
|
||||
void set_value(bool value) const { StoreNonPointer(&untag()->value_, value); }
|
||||
|
||||
// New should only be called to initialize the two legal bool values.
|
||||
static BoolPtr New(bool value);
|
||||
|
||||
FINAL_HEAP_OBJECT_IMPLEMENTATION(Bool, Instance);
|
||||
friend class Class;
|
||||
friend class Object; // To initialize the true and false values.
|
||||
|
|
|
@ -37,6 +37,10 @@ struct ObjectAlignment {
|
|||
static constexpr intptr_t kBoolValueBitPosition = kObjectAlignmentLog2;
|
||||
static constexpr intptr_t kBoolValueMask = 1 << kBoolValueBitPosition;
|
||||
|
||||
// Discriminate between bool and null based on bit after the alignment bit.
|
||||
static constexpr intptr_t kBoolVsNullBitPosition = kObjectAlignmentLog2 + 1;
|
||||
static constexpr intptr_t kBoolVsNullMask = 1 << kBoolVsNullBitPosition;
|
||||
|
||||
static constexpr intptr_t kTrueOffsetFromNull = kObjectAlignment * 2;
|
||||
static constexpr intptr_t kFalseOffsetFromNull = kObjectAlignment * 3;
|
||||
};
|
||||
|
@ -58,6 +62,10 @@ static constexpr intptr_t kObjectAlignmentMask =
|
|||
static constexpr intptr_t kBoolValueBitPosition =
|
||||
HostObjectAlignment::kBoolValueBitPosition;
|
||||
static constexpr intptr_t kBoolValueMask = HostObjectAlignment::kBoolValueMask;
|
||||
static constexpr intptr_t kBoolVsNullBitPosition =
|
||||
HostObjectAlignment::kBoolVsNullBitPosition;
|
||||
static constexpr intptr_t kBoolVsNullMask =
|
||||
HostObjectAlignment::kBoolVsNullMask;
|
||||
static constexpr intptr_t kTrueOffsetFromNull =
|
||||
HostObjectAlignment::kTrueOffsetFromNull;
|
||||
static constexpr intptr_t kFalseOffsetFromNull =
|
||||
|
|
Loading…
Reference in a new issue