Revert "[vm/compiler] Check non-constant supertypes for top types in AssertSubtype."
This reverts commit 3c87c14457.
Reason for revert: Reverting parent CL.
Original change's description:
> [vm/compiler] Check non-constant supertypes for top types in AssertSubtype.
>
> This restores the invariant that the runtime entry is never run on
> instantiated top types.
>
> TEST=Run on trybots of all architectures, since existing tests cover static and dynamic AssertSubtype well.
>
> Cq-Include-Trybots: luci.dart.try:vm-kernel-linux-debug-x64-try,vm-kernel-nnbd-linux-debug-x64-try,vm-kernel-linux-debug-ia32-try,vm-kernel-nnbd-linux-debug-ia32-try,vm-kernel-precomp-linux-debug-simarm_x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-nnbd-linux-debug-simarm_x64-try,vm-kernel-precomp-nnbd-linux-debug-x64-try,vm-kernel-linux-release-simarm-try,vm-kernel-linux-release-simarm64-try,vm-kernel-nnbd-linux-release-simarm-try,vm-kernel-nnbd-linux-release-simarm64-try,vm-kernel-precomp-linux-release-simarm-try,vm-kernel-precomp-linux-release-simarm64-try,vm-kernel-precomp-nnbd-linux-release-simarm64-try
> Change-Id: Id0ec9a90f1bcc70748af8d8d2b1e8d6198b66152
> Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/171942
> Commit-Queue: Tess Strickland <sstrickl@google.com>
> Reviewed-by: Régis Crelier <regis@google.com>
> Reviewed-by: Martin Kustermann <kustermann@google.com>
TBR=kustermann@google.com,regis@google.com,sstrickl@google.com
Change-Id: Ia7316b6e9c2aa226171ab09e066a707b4c8a4a76
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/172642
Commit-Queue: Tess Strickland <sstrickl@google.com>
Reviewed-by: Tess Strickland <sstrickl@google.com>
This commit is contained in:
committed by
commit-bot@chromium.org
parent
289bc8ce38
commit
19b4eae3f2
@@ -9,7 +9,6 @@
|
||||
|
||||
#include "vm/class_id.h"
|
||||
#include "vm/compiler/assembler/assembler.h"
|
||||
#include "vm/compiler/backend/locations.h"
|
||||
#include "vm/cpu.h"
|
||||
#include "vm/instructions.h"
|
||||
|
||||
@@ -2123,57 +2122,6 @@ void Assembler::DoubleAbs(XmmRegister reg) {
|
||||
andpd(reg, Address::Absolute(reinterpret_cast<uword>(&double_abs_constant)));
|
||||
}
|
||||
|
||||
void Assembler::PushRegisters(const RegisterSet& register_set) {
|
||||
const intptr_t xmm_regs_count = register_set.FpuRegisterCount();
|
||||
if (xmm_regs_count > 0) {
|
||||
AddImmediate(ESP, Immediate(-xmm_regs_count * kFpuRegisterSize));
|
||||
// Store XMM registers with the lowest register number at the lowest
|
||||
// address.
|
||||
intptr_t offset = 0;
|
||||
for (intptr_t i = 0; i < kNumberOfXmmRegisters; ++i) {
|
||||
XmmRegister xmm_reg = static_cast<XmmRegister>(i);
|
||||
if (register_set.ContainsFpuRegister(xmm_reg)) {
|
||||
movups(Address(ESP, offset), xmm_reg);
|
||||
offset += kFpuRegisterSize;
|
||||
}
|
||||
}
|
||||
ASSERT(offset == (xmm_regs_count * kFpuRegisterSize));
|
||||
}
|
||||
|
||||
// The order in which the registers are pushed must match the order
|
||||
// in which the registers are encoded in the safe point's stack map.
|
||||
for (intptr_t i = kNumberOfCpuRegisters - 1; i >= 0; --i) {
|
||||
Register reg = static_cast<Register>(i);
|
||||
if (register_set.ContainsRegister(reg)) {
|
||||
pushl(reg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Assembler::PopRegisters(const RegisterSet& register_set) {
|
||||
for (intptr_t i = 0; i < kNumberOfCpuRegisters; ++i) {
|
||||
Register reg = static_cast<Register>(i);
|
||||
if (register_set.ContainsRegister(reg)) {
|
||||
popl(reg);
|
||||
}
|
||||
}
|
||||
|
||||
const intptr_t xmm_regs_count = register_set.FpuRegisterCount();
|
||||
if (xmm_regs_count > 0) {
|
||||
// XMM registers have the lowest register number at the lowest address.
|
||||
intptr_t offset = 0;
|
||||
for (intptr_t i = 0; i < kNumberOfXmmRegisters; ++i) {
|
||||
XmmRegister xmm_reg = static_cast<XmmRegister>(i);
|
||||
if (register_set.ContainsFpuRegister(xmm_reg)) {
|
||||
movups(xmm_reg, Address(ESP, offset));
|
||||
offset += kFpuRegisterSize;
|
||||
}
|
||||
}
|
||||
ASSERT(offset == (xmm_regs_count * kFpuRegisterSize));
|
||||
AddImmediate(ESP, Immediate(offset));
|
||||
}
|
||||
}
|
||||
|
||||
void Assembler::EnterFrame(intptr_t frame_size) {
|
||||
if (prologue_offset_ == -1) {
|
||||
Comment("PrologueOffset = %" Pd "", CodeSize());
|
||||
|
||||
@@ -21,10 +21,6 @@
|
||||
#include "vm/pointer_tagging.h"
|
||||
|
||||
namespace dart {
|
||||
|
||||
// Forward declarations.
|
||||
class RegisterSet;
|
||||
|
||||
namespace compiler {
|
||||
|
||||
class Immediate : public ValueObject {
|
||||
@@ -731,9 +727,6 @@ class Assembler : public AssemblerBase {
|
||||
Immediate(value));
|
||||
}
|
||||
|
||||
void PushRegisters(const RegisterSet& registers);
|
||||
void PopRegisters(const RegisterSet& registers);
|
||||
|
||||
void EnterFrame(intptr_t frame_space);
|
||||
void LeaveFrame();
|
||||
void ReserveAlignedFrameSpace(intptr_t frame_space);
|
||||
|
||||
@@ -5311,40 +5311,6 @@ LocationSummary* AssertSubtypeInstr::MakeLocationSummary(Zone* zone,
|
||||
}
|
||||
|
||||
void AssertSubtypeInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
compiler::Label done;
|
||||
if (!super_type()->BindsToConstant()) {
|
||||
RegisterSet saved_registers;
|
||||
// The TypeIsTopTypeForSubtyping stub clobbers
|
||||
// TypeTestABI::kSubtypeTestCacheReg for its output.
|
||||
static_assert(
|
||||
TypeTestABI::kSubtypeTestCacheReg == AssertSubtypeABI::kDstNameReg,
|
||||
"Different register will be clobbered by stub");
|
||||
saved_registers.Add(locs()->in(kDstNamePos));
|
||||
#if !defined(TARGET_ARCH_IA32)
|
||||
// It also clobbers TypeTestABI::kScratchReg on non-IA32.
|
||||
static_assert(TypeTestABI::kScratchReg == AssertSubtypeABI::kSubTypeReg,
|
||||
"Different register will be clobbered by stub");
|
||||
saved_registers.Add(locs()->in(kSubTypePos));
|
||||
#else
|
||||
// On IA32 it also uses TypeTestABI::kFunctionTypeArgumentsReg as scratch,
|
||||
// but it saves it on the stack and restores it before returning, so it
|
||||
// does not need to be preserved here.
|
||||
#endif
|
||||
// The runtime entry assumes it is not be called with a top type as the
|
||||
// super type, so check this on the caller side.
|
||||
const bool null_safety = Isolate::Current()->null_safety();
|
||||
static_assert(
|
||||
TypeTestABI::kSubtypeTestCacheReg == AssertSubtypeABI::kDstNameReg,
|
||||
"Different register will be clobbered by stub");
|
||||
__ PushRegisters(saved_registers);
|
||||
compiler->GenerateStubCall(
|
||||
token_pos(), StubCode::GetTypeIsTopTypeForSubtyping(null_safety),
|
||||
PcDescriptorsLayout::kOther, locs());
|
||||
// AssertSubtypeABI::kDstNameReg is 0 if the type is a top type.
|
||||
__ CompareImmediate(AssertSubtypeABI::kDstNameReg, 0);
|
||||
__ PopRegisters(saved_registers);
|
||||
__ BranchIf(EQUAL, &done, compiler::Assembler::kNearJump);
|
||||
}
|
||||
#if defined(TARGET_ARCH_IA32)
|
||||
__ PushRegister(AssertSubtypeABI::kInstantiatorTypeArgumentsReg);
|
||||
__ PushRegister(AssertSubtypeABI::kFunctionTypeArgumentsReg);
|
||||
@@ -5353,12 +5319,12 @@ void AssertSubtypeInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
||||
__ PushRegister(AssertSubtypeABI::kDstNameReg);
|
||||
compiler->GenerateRuntimeCall(token_pos(), deopt_id(),
|
||||
kSubtypeCheckRuntimeEntry, 5, locs());
|
||||
|
||||
__ Drop(5);
|
||||
#else
|
||||
compiler->GenerateStubCall(token_pos(), StubCode::AssertSubtype(),
|
||||
PcDescriptorsLayout::kOther, locs());
|
||||
#endif
|
||||
__ Bind(&done);
|
||||
}
|
||||
|
||||
LocationSummary* DeoptimizeInstr::MakeLocationSummary(Zone* zone,
|
||||
|
||||
@@ -349,17 +349,13 @@ struct TypeTestABI {
|
||||
(1 << kSubtypeTestCacheReg) | (1 << kScratchReg);
|
||||
};
|
||||
|
||||
// Calling convention when calling AssertSubtypeStub. Defined in terms of
|
||||
// TypeTestABI as that enables us to call the TypeIsTopTypeForSubtyping
|
||||
// stub without juggling registers.
|
||||
// Calling convention when calling AssertSubtypeStub.
|
||||
struct AssertSubtypeABI {
|
||||
static const Register kSubTypeReg = TypeTestABI::kScratchReg;
|
||||
static const Register kSuperTypeReg = TypeTestABI::kDstTypeReg;
|
||||
static const Register kInstantiatorTypeArgumentsReg =
|
||||
TypeTestABI::kInstantiatorTypeArgumentsReg;
|
||||
static const Register kFunctionTypeArgumentsReg =
|
||||
TypeTestABI::kFunctionTypeArgumentsReg;
|
||||
static const Register kDstNameReg = TypeTestABI::kSubtypeTestCacheReg;
|
||||
static const Register kSubTypeReg = R0;
|
||||
static const Register kSuperTypeReg = R8;
|
||||
static const Register kInstantiatorTypeArgumentsReg = R2;
|
||||
static const Register kFunctionTypeArgumentsReg = R1;
|
||||
static const Register kDstNameReg = R3;
|
||||
|
||||
static const intptr_t kAbiRegisters =
|
||||
(1 << kSubTypeReg) | (1 << kSuperTypeReg) |
|
||||
|
||||
@@ -182,17 +182,13 @@ struct TypeTestABI {
|
||||
(1 << kSubtypeTestCacheResultReg);
|
||||
};
|
||||
|
||||
// Calling convention when calling AssertSubtypeStub. Defined in terms of
|
||||
// TypeTestABI as that enables us to call the TypeIsTopTypeForSubtyping
|
||||
// stub without juggling registers.
|
||||
// Calling convention when calling AssertSubtypeStub.
|
||||
struct AssertSubtypeABI {
|
||||
static const Register kSubTypeReg = TypeTestABI::kScratchReg;
|
||||
static const Register kSuperTypeReg = TypeTestABI::kDstTypeReg;
|
||||
static const Register kInstantiatorTypeArgumentsReg =
|
||||
TypeTestABI::kInstantiatorTypeArgumentsReg;
|
||||
static const Register kFunctionTypeArgumentsReg =
|
||||
TypeTestABI::kFunctionTypeArgumentsReg;
|
||||
static const Register kDstNameReg = TypeTestABI::kSubtypeTestCacheReg;
|
||||
static const Register kSubTypeReg = R0;
|
||||
static const Register kSuperTypeReg = R8;
|
||||
static const Register kInstantiatorTypeArgumentsReg = R2;
|
||||
static const Register kFunctionTypeArgumentsReg = R1;
|
||||
static const Register kDstNameReg = R3;
|
||||
|
||||
static const intptr_t kAbiRegisters =
|
||||
(1 << kSubTypeReg) | (1 << kSuperTypeReg) |
|
||||
|
||||
@@ -124,25 +124,15 @@ struct TypeTestABI {
|
||||
TypeTestABI::kSubtypeTestCacheReg;
|
||||
};
|
||||
|
||||
// Calling convention when calling AssertSubtypeStub. Defined in terms of
|
||||
// TypeTestABI as that enables us to call the TypeIsTopTypeForSubtyping
|
||||
// stub without juggling registers.
|
||||
//
|
||||
// Note that we don't generate a call to AssertSubtypeStub because we need
|
||||
// CODE_REG to store a fifth argument, so instead a runtime call is generated.
|
||||
// Calling convention when calling kSubtypeCheckRuntimeEntry, to match other
|
||||
// architectures. We don't generate a call to the AssertSubtypeStub because we
|
||||
// need CODE_REG to store a fifth argument.
|
||||
struct AssertSubtypeABI {
|
||||
static const Register kSubTypeReg = TypeTestABI::kInstanceReg;
|
||||
static const Register kSuperTypeReg = TypeTestABI::kDstTypeReg;
|
||||
static const Register kInstantiatorTypeArgumentsReg =
|
||||
TypeTestABI::kInstantiatorTypeArgumentsReg;
|
||||
static const Register kFunctionTypeArgumentsReg =
|
||||
TypeTestABI::kFunctionTypeArgumentsReg;
|
||||
static const Register kDstNameReg = TypeTestABI::kSubtypeTestCacheReg;
|
||||
|
||||
static const intptr_t kAbiRegisters =
|
||||
(1 << kSubTypeReg) | (1 << kSuperTypeReg) |
|
||||
(1 << kInstantiatorTypeArgumentsReg) | (1 << kFunctionTypeArgumentsReg) |
|
||||
(1 << kDstNameReg);
|
||||
static const Register kSubTypeReg = EAX;
|
||||
static const Register kSuperTypeReg = EBX;
|
||||
static const Register kInstantiatorTypeArgumentsReg = EDX;
|
||||
static const Register kFunctionTypeArgumentsReg = ECX;
|
||||
static const Register kDstNameReg = EDI; /// On ia32 we don't use CODE_REG.
|
||||
|
||||
// No result register, as AssertSubtype is only run for side effect
|
||||
// (throws if the subtype check fails).
|
||||
|
||||
@@ -171,17 +171,13 @@ struct TypeTestABI {
|
||||
(1 << kSubtypeTestCacheResultReg);
|
||||
};
|
||||
|
||||
// Calling convention when calling AssertSubtypeStub. Defined in terms of
|
||||
// TypeTestABI as that enables us to call the TypeIsTopTypeForSubtyping
|
||||
// stub without juggling registers.
|
||||
// Calling convention when calling AssertSubtypeStub.
|
||||
struct AssertSubtypeABI {
|
||||
static const Register kSubTypeReg = TypeTestABI::kScratchReg;
|
||||
static const Register kSuperTypeReg = TypeTestABI::kDstTypeReg;
|
||||
static const Register kInstantiatorTypeArgumentsReg =
|
||||
TypeTestABI::kInstantiatorTypeArgumentsReg;
|
||||
static const Register kFunctionTypeArgumentsReg =
|
||||
TypeTestABI::kFunctionTypeArgumentsReg;
|
||||
static const Register kDstNameReg = TypeTestABI::kSubtypeTestCacheReg;
|
||||
static const Register kSubTypeReg = RAX;
|
||||
static const Register kSuperTypeReg = RBX;
|
||||
static const Register kInstantiatorTypeArgumentsReg = RDX;
|
||||
static const Register kFunctionTypeArgumentsReg = RCX;
|
||||
static const Register kDstNameReg = R9;
|
||||
|
||||
static const intptr_t kAbiRegisters =
|
||||
(1 << kSubTypeReg) | (1 << kSuperTypeReg) |
|
||||
|
||||
@@ -476,7 +476,10 @@ DEFINE_RUNTIME_ENTRY(SubtypeCheck, 5) {
|
||||
|
||||
ASSERT(!subtype.IsNull() && !subtype.IsTypeRef());
|
||||
ASSERT(!supertype.IsNull() && !supertype.IsTypeRef());
|
||||
ASSERT(!supertype.IsTopTypeForSubtyping());
|
||||
|
||||
// Now that AssertSubtype may be checking types only available at runtime,
|
||||
// we can't guarantee the supertype isn't the top type.
|
||||
if (supertype.IsTopTypeForSubtyping()) return;
|
||||
|
||||
// The supertype or subtype may not be instantiated.
|
||||
if (AbstractType::InstantiateAndTestSubtype(
|
||||
|
||||
Reference in New Issue
Block a user