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:
Tess Strickland
2020-11-18 08:15:12 +00:00
committed by commit-bot@chromium.org
parent 289bc8ce38
commit 19b4eae3f2
8 changed files with 31 additions and 143 deletions
@@ -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);
+1 -35
View File
@@ -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,
+6 -10
View File
@@ -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) |
+6 -10
View File
@@ -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) |
+8 -18
View File
@@ -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).
+6 -10
View File
@@ -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) |
+4 -1
View File
@@ -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(