| Index: runtime/vm/stub_code_ia32.cc
|
| ===================================================================
|
| --- runtime/vm/stub_code_ia32.cc (revision 5920)
|
| +++ runtime/vm/stub_code_ia32.cc (working copy)
|
| @@ -1755,6 +1755,85 @@
|
| __ jmp(&StubCode::OneArgCheckInlineCacheLabel());
|
| }
|
|
|
| +
|
| +// Check if an instance class is a subtype of class/interface using simple
|
| +// superchain and interface array traversal. Does not take type parameters into
|
| +// account.
|
| +// EAX: instance.
|
| +// EDX: class/interface to test against (is class of instance a subtype of it).
|
| +// Result in EDX: 1 is subtype, 0 maybe not.
|
| +// Destroys EBX, ECX.
|
| +void StubCode::GenerateIsSubTypeStub(Assembler* assembler) {
|
| + const Immediate raw_null =
|
| + Immediate(reinterpret_cast<intptr_t>(Object::null()));
|
| + Label test_class, not_found, found, class_loaded_in_ECX, smi_value;
|
| + __ EnterFrame(0);
|
| + __ testl(EAX, Immediate(kSmiTagMask));
|
| + __ j(ZERO, &smi_value, Assembler::kNearJump);
|
| + __ movl(ECX, FieldAddress(EAX, Object::class_offset()));
|
| + __ jmp(&class_loaded_in_ECX, Assembler::kNearJump);
|
| + __ Bind(&smi_value);
|
| + __ movl(ECX, FieldAddress(CTX, Context::isolate_offset()));
|
| + __ movl(ECX, Address(ECX, Isolate::object_store_offset()));
|
| + __ movl(ECX, Address(ECX, ObjectStore::smi_class_offset()));
|
| + __ Bind(&class_loaded_in_ECX);
|
| +
|
| + __ movzxb(EBX, FieldAddress(EDX, Class::is_interface_offset()));
|
| + // Check if we are comparing against class or interface.
|
| + __ cmpl(EBX, Immediate(0));
|
| + __ j(EQUAL, &test_class, Assembler::kNearJump);
|
| +
|
| + // Get interfaces array from instance class.
|
| + __ movl(EBX, FieldAddress(ECX, Class::interfaces_offset()));
|
| + __ cmpl(EBX, raw_null);
|
| + __ j(EQUAL, ¬_found, Assembler::kNearJump);
|
| + __ movl(EDI, FieldAddress(EBX, Array::length_offset()));
|
| + // EDI: array index.
|
| + // EBX: interface array.
|
| + // EDX: interface searched
|
| + Label array_loop;
|
| + __ Bind(&array_loop);
|
| + __ subl(EDI, Immediate(Smi::RawValue(1)));
|
| + // __ cmpl(EDI, Immediate(0));
|
| + __ j(LESS, ¬_found, Assembler::kNearJump);
|
| + // EDI is Smi therefore TIMES_2 instead of TIMES_4.
|
| + // Get type from array.
|
| + __ movl(ECX, FieldAddress(EBX, EDI, TIMES_2, Array::data_offset()));
|
| + __ movl(ECX, FieldAddress(ECX, Type::type_class_offset()));
|
| + __ cmpl(ECX, EDX);
|
| + __ j(EQUAL, &found, Assembler::kNearJump);
|
| + __ jmp(&array_loop, Assembler::kNearJump);
|
| +
|
| + __ Bind(¬_found);
|
| + __ xorl(EAX, EAX);
|
| + __ LeaveFrame();
|
| + __ ret();
|
| +
|
| + __ Bind(&found);
|
| + __ movl(EAX, Immediate(1));
|
| + __ LeaveFrame();
|
| + __ ret();
|
| +
|
| + __ Bind(&test_class);
|
| + // EDX: test class.
|
| + __ cmpl(ECX, EDX);
|
| + __ j(EQUAL, &found, Assembler::kNearJump);
|
| +
|
| + // Check superclasses using a loop (faster than runtime call).
|
| + Label super_loop;
|
| + __ Bind(&super_loop);
|
| + // ECX: class -> super.
|
| + __ movl(ECX, FieldAddress(ECX, Class::super_type_offset()));
|
| + // The supertype of Object is a null object.
|
| + __ cmpl(ECX, raw_null);
|
| + __ j(EQUAL, ¬_found, Assembler::kNearJump);
|
| + __ movl(ECX, FieldAddress(ECX, Type::type_class_offset()));
|
| + __ cmpl(EDX, ECX);
|
| + __ j(NOT_EQUAL, &super_loop, Assembler::kNearJump);
|
| + __ jmp(&found, Assembler::kNearJump);
|
| +}
|
| +
|
| +
|
| } // namespace dart
|
|
|
| #endif // defined TARGET_ARCH_IA32
|
|
|