diff --git a/runtime/vm/compiler/assembler/assembler_ia32.cc b/runtime/vm/compiler/assembler/assembler_ia32.cc index 10c337118f9..d07c40f2387 100644 --- a/runtime/vm/compiler/assembler/assembler_ia32.cc +++ b/runtime/vm/compiler/assembler/assembler_ia32.cc @@ -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(&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(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(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(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(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()); diff --git a/runtime/vm/compiler/assembler/assembler_ia32.h b/runtime/vm/compiler/assembler/assembler_ia32.h index cf0d8b44ba5..dfa7f35b0d0 100644 --- a/runtime/vm/compiler/assembler/assembler_ia32.h +++ b/runtime/vm/compiler/assembler/assembler_ia32.h @@ -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); diff --git a/runtime/vm/compiler/backend/il.cc b/runtime/vm/compiler/backend/il.cc index 05dc6c20ecd..4042a0499c0 100644 --- a/runtime/vm/compiler/backend/il.cc +++ b/runtime/vm/compiler/backend/il.cc @@ -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, diff --git a/runtime/vm/constants_arm.h b/runtime/vm/constants_arm.h index 0751784946f..82a86da513f 100644 --- a/runtime/vm/constants_arm.h +++ b/runtime/vm/constants_arm.h @@ -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) | diff --git a/runtime/vm/constants_arm64.h b/runtime/vm/constants_arm64.h index eca097024ac..da0e6d78eb8 100644 --- a/runtime/vm/constants_arm64.h +++ b/runtime/vm/constants_arm64.h @@ -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) | diff --git a/runtime/vm/constants_ia32.h b/runtime/vm/constants_ia32.h index 5d1ae67eaa4..1827e824846 100644 --- a/runtime/vm/constants_ia32.h +++ b/runtime/vm/constants_ia32.h @@ -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). diff --git a/runtime/vm/constants_x64.h b/runtime/vm/constants_x64.h index 6d601d5c8cf..e154cb251ac 100644 --- a/runtime/vm/constants_x64.h +++ b/runtime/vm/constants_x64.h @@ -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) | diff --git a/runtime/vm/runtime_entry.cc b/runtime/vm/runtime_entry.cc index c21a7f3b019..571ea55f950 100644 --- a/runtime/vm/runtime_entry.cc +++ b/runtime/vm/runtime_entry.cc @@ -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(