Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(349)

Unified Diff: runtime/vm/flow_graph_compiler_x64.cc

Issue 10409067: More inlined type checking for x64. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « runtime/vm/code_generator_ia32.cc ('k') | runtime/vm/stub_code_x64.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/flow_graph_compiler_x64.cc
===================================================================
--- runtime/vm/flow_graph_compiler_x64.cc (revision 7858)
+++ runtime/vm/flow_graph_compiler_x64.cc (working copy)
@@ -141,7 +141,51 @@
return GenerateSubtype1TestCacheLookup(
cid, token_index, type_class, is_instance_lbl, is_not_instance_lbl);
}
- return SubtypeTestCache::null();
+ // If one type argument only, check if type argument is Object or Dynamic.
+ if (type_arguments.Length() == 1) {
+ const AbstractType& tp_argument = AbstractType::ZoneHandle(
+ type_arguments.TypeAt(0));
+ if (tp_argument.IsMalformed()) {
regis 2012/05/22 18:07:51 You can assert that it is not malformed. My pendin
srdjan 2012/05/22 18:23:57 Done.
+ return SubtypeTestCache::null();
+ }
+ if (tp_argument.IsType()) {
+ ASSERT(tp_argument.HasResolvedTypeClass());
+ // Check if type argument is dynamic or Object.
+ const Type& object_type =
+ Type::Handle(Isolate::Current()->object_store()->object_type());
+ Error& malformed_error = Error::Handle();
+ if (object_type.IsSubtypeOf(tp_argument, &malformed_error)) {
+ // Instance class test only necessary.
+ return GenerateSubtype1TestCacheLookup(
+ cid, token_index, type_class, is_instance_lbl, is_not_instance_lbl);
+ }
+ }
+ }
+
+ // Regular subtype test cache involving instance's type arguments.
+ const SubtypeTestCache& type_test_cache =
+ SubtypeTestCache::ZoneHandle(SubtypeTestCache::New());
+ Label runtime_call;
+ const Immediate raw_null =
+ Immediate(reinterpret_cast<intptr_t>(Object::null()));
+ __ LoadObject(R10, type_test_cache);
+ __ pushq(R10); // Subtype test cache.
+ __ pushq(RAX); // Instance.
+ __ pushq(raw_null); // Unused.
+ __ call(&StubCode::Subtype2TestCacheLabel());
+ __ popq(RAX); // Discard.
+ __ popq(RAX); // Restore receiver.
+ __ popq(RDX); // Discard.
+ // Result is in RCX: null -> not found, otherwise Bool::True or Bool::False.
+
+ __ cmpq(RCX, raw_null);
+ __ j(EQUAL, &runtime_call, Assembler::kNearJump);
+ const Bool& bool_true = Bool::ZoneHandle(Bool::True());
+ __ CompareObject(RCX, bool_true);
+ __ j(EQUAL, is_instance_lbl);
+ __ jmp(is_not_instance_lbl);
+ __ Bind(&runtime_call);
+ return type_test_cache.raw();
}
@@ -306,12 +350,97 @@
}
+// Generates inlined check if 'type' is a type parameter or type itsef
+// RAX: instance (preserved).
RawSubtypeTestCache* FlowGraphCompiler::GenerateUninstantiatedTypeTest(
const AbstractType& type,
intptr_t cid,
intptr_t token_index,
Label* is_instance_lbl,
Label* is_not_instance_lbl) {
+ ASSERT(!type.IsInstantiated());
+ const Immediate raw_null =
+ Immediate(reinterpret_cast<intptr_t>(Object::null()));
+ if (type.IsTypeParameter()) {
+ // Load instantiator (or null) and instantiator type arguments on stack.
+ __ movq(RDX, Address(RSP, 0)); // Get instantiator type arguments.
+ // RDX: instantiator type arguments.
+ // Check if type argument is Dynamic.
+ __ cmpq(RDX, raw_null);
+ __ j(EQUAL, is_instance_lbl);
+ // Can handle only type arguments that are instances of TypeArguments.
+ // (runtime checks canonicalize type arguments).
+ Label fall_through;
+ __ movq(R10, FieldAddress(RDX, Object::class_offset()));
+ __ CompareObject(R10, Object::ZoneHandle(Object::type_arguments_class()));
+ __ j(NOT_EQUAL, &fall_through);
+ __ movq(RDI,
+ FieldAddress(RDX, TypeArguments::type_at_offset(type.Index())));
+ // RDI: Concrete type.
+ // Check if it is Dynamic,
+ __ CompareObject(RDI, Type::ZoneHandle(Type::DynamicType()));
+ __ j(EQUAL, is_instance_lbl);
+ __ cmpq(RDI, raw_null);
+ __ j(EQUAL, is_instance_lbl);
+ // For Smi check quickly against int and num interface types.
+ Label not_smi;
+ __ testq(RAX, Immediate(kSmiTagMask)); // Value is Smi?
+ __ j(NOT_ZERO, &not_smi, Assembler::kNearJump);
+ __ CompareObject(RDI, Type::ZoneHandle(Type::IntInterface()));
+ __ j(EQUAL, is_instance_lbl);
+ __ CompareObject(RDI, Type::ZoneHandle(Type::NumberInterface()));
+ __ j(EQUAL, is_instance_lbl);
+ __ jmp(&fall_through);
+ __ Bind(&not_smi);
+ // RDX: instantiator type arguments.
+ // RAX: instance.
+ const SubtypeTestCache& type_test_cache =
+ SubtypeTestCache::ZoneHandle(SubtypeTestCache::New());
+ __ LoadObject(R10, type_test_cache);
+ __ pushq(R10); // Subtype test cache.
+ __ pushq(RAX); // Instance
+ __ pushq(RDX); // Instantiator type arguments.
+ __ call(&StubCode::Subtype3TestCacheLabel());
+ __ popq(RDX); // Discard type arguments.
+ __ popq(RAX); // Restore receiver.
+ __ popq(RDX); // Discard subtype test cache.
+ // Result is in RCX: null -> not found, otherwise Bool::True or Bool::False.
+ __ cmpq(RCX, raw_null);
+ __ j(EQUAL, &fall_through, Assembler::kNearJump);
+ const Bool& bool_true = Bool::ZoneHandle(Bool::True());
+ __ CompareObject(RCX, bool_true);
+ __ j(EQUAL, is_instance_lbl);
+ __ jmp(is_not_instance_lbl);
+ __ Bind(&fall_through);
+ return type_test_cache.raw();
+ }
+ if (type.IsType()) {
+ Label fall_through;
+ __ testq(RAX, Immediate(kSmiTagMask)); // Is instance Smi?
+ __ j(ZERO, is_not_instance_lbl);
+ __ movq(RDX, Address(RSP, 0)); // Get instantiator type arguments.
+ // Uninstantiated type class is known at compile time, but the type
+ // arguments are determined at runtime by the instantiator.
+ const SubtypeTestCache& type_test_cache =
+ SubtypeTestCache::ZoneHandle(SubtypeTestCache::New());
+ __ LoadObject(R10, type_test_cache);
+ __ pushq(R10); // Subtype test cache.
+ __ pushq(RAX); // Instance.
+ __ pushq(RDX); // Instantiator type arguments.
+ __ call(&StubCode::Subtype3TestCacheLabel());
+ __ popq(RDX); // Discard type arguments.
+ __ popq(RAX); // Restore receiver.
+ __ popq(RDX); // Discard subtype test cache.
+ // Result is in RCX: null -> not found, otherwise Bool::True or Bool::False.
+ __ cmpq(RCX, raw_null);
+ __ j(EQUAL, &fall_through, Assembler::kNearJump);
+ const Bool& bool_true = Bool::ZoneHandle(Bool::True());
+ __ CompareObject(RCX, bool_true);
+ __ j(EQUAL, is_instance_lbl);
+ __ jmp(is_not_instance_lbl);
+ __ Bind(&fall_through);
+ return type_test_cache.raw();
+ }
return SubtypeTestCache::null();
}
@@ -804,7 +933,7 @@
// - Class equality (only if class is not parameterized).
// Inputs:
// - RAX: object.
-// - RDX: oinstantiator type arguments or raw_null.
+// - RDX: instantiator type arguments or raw_null.
// - RCX: instantiator or raw_null.
// Destroys RCX and RDX.
// Returns:
@@ -821,7 +950,8 @@
const Immediate raw_null =
Immediate(reinterpret_cast<intptr_t>(Object::null()));
Label is_instance, is_not_instance;
- __ pushq(RCX); // Temporary store instantiator on stack.
+ __ pushq(RCX); // Store instantiator on stack.
+ __ pushq(RDX); // Store instantiator type arguments.
// If type is instantiated and non-parameterized, we can inline code
// checking whether the tested instance is a Smi.
if (type.IsInstantiated()) {
@@ -842,17 +972,15 @@
&is_instance, &is_not_instance);
// Generate runtime call.
+ __ movq(RDX, Address(RSP, 0)); // Get instantiator type arguments.
+ __ movq(RCX, Address(RSP, kWordSize)); // Get instantiator.
__ PushObject(Object::ZoneHandle()); // Make room for the result.
__ pushq(Immediate(Smi::RawValue(token_index))); // Source location.
__ pushq(Immediate(Smi::RawValue(cid))); // Computation id.
__ pushq(RAX); // Push the instance.
__ PushObject(type); // Push the type.
- __ pushq(raw_null); // TODO(srdjan): Pass instantiator instead of null.
- if (type.IsInstantiated()) {
- __ pushq(raw_null); // Null instantiator type arguments.
- } else {
- __ pushq(RDX); // Instantiator type arguments.
- }
+ __ pushq(RCX); // TODO(srdjan): Pass instantiator instead of null.
+ __ pushq(RDX); // Instantiator type arguments.
__ LoadObject(RAX, test_cache);
__ pushq(RAX);
GenerateCallRuntime(cid, token_index, try_index, kInstanceofRuntimeEntry);
@@ -878,6 +1006,7 @@
__ Bind(&is_instance);
__ LoadObject(RAX, negate_result ? bool_false : bool_true);
__ Bind(&done);
+ __ popq(RDX); // Remove pushed instantiator type arguments..
__ popq(RCX); // Remove pushed instantiator.
}
« no previous file with comments | « runtime/vm/code_generator_ia32.cc ('k') | runtime/vm/stub_code_x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698