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

Side by Side 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « runtime/vm/code_generator_ia32.cc ('k') | runtime/vm/stub_code_x64.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_X64. 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_X64.
6 #if defined(TARGET_ARCH_X64) 6 #if defined(TARGET_ARCH_X64)
7 7
8 #include "vm/flow_graph_compiler.h" 8 #include "vm/flow_graph_compiler.h"
9 9
10 #include "lib/error.h" 10 #include "lib/error.h"
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after
134 GrowableArray<const Class*> args; 134 GrowableArray<const Class*> args;
135 args.Add(CoreClass("ObjectArray")); 135 args.Add(CoreClass("ObjectArray"));
136 args.Add(CoreClass("GrowableObjectArray")); 136 args.Add(CoreClass("GrowableObjectArray"));
137 args.Add(CoreClass("ImmutableArray")); 137 args.Add(CoreClass("ImmutableArray"));
138 CheckClasses(args, is_instance_lbl, &unknown); 138 CheckClasses(args, is_instance_lbl, &unknown);
139 __ Bind(&unknown); 139 __ Bind(&unknown);
140 } 140 }
141 return GenerateSubtype1TestCacheLookup( 141 return GenerateSubtype1TestCacheLookup(
142 cid, token_index, type_class, is_instance_lbl, is_not_instance_lbl); 142 cid, token_index, type_class, is_instance_lbl, is_not_instance_lbl);
143 } 143 }
144 return SubtypeTestCache::null(); 144 // If one type argument only, check if type argument is Object or Dynamic.
145 if (type_arguments.Length() == 1) {
146 const AbstractType& tp_argument = AbstractType::ZoneHandle(
147 type_arguments.TypeAt(0));
148 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.
149 return SubtypeTestCache::null();
150 }
151 if (tp_argument.IsType()) {
152 ASSERT(tp_argument.HasResolvedTypeClass());
153 // Check if type argument is dynamic or Object.
154 const Type& object_type =
155 Type::Handle(Isolate::Current()->object_store()->object_type());
156 Error& malformed_error = Error::Handle();
157 if (object_type.IsSubtypeOf(tp_argument, &malformed_error)) {
158 // Instance class test only necessary.
159 return GenerateSubtype1TestCacheLookup(
160 cid, token_index, type_class, is_instance_lbl, is_not_instance_lbl);
161 }
162 }
163 }
164
165 // Regular subtype test cache involving instance's type arguments.
166 const SubtypeTestCache& type_test_cache =
167 SubtypeTestCache::ZoneHandle(SubtypeTestCache::New());
168 Label runtime_call;
169 const Immediate raw_null =
170 Immediate(reinterpret_cast<intptr_t>(Object::null()));
171 __ LoadObject(R10, type_test_cache);
172 __ pushq(R10); // Subtype test cache.
173 __ pushq(RAX); // Instance.
174 __ pushq(raw_null); // Unused.
175 __ call(&StubCode::Subtype2TestCacheLabel());
176 __ popq(RAX); // Discard.
177 __ popq(RAX); // Restore receiver.
178 __ popq(RDX); // Discard.
179 // Result is in RCX: null -> not found, otherwise Bool::True or Bool::False.
180
181 __ cmpq(RCX, raw_null);
182 __ j(EQUAL, &runtime_call, Assembler::kNearJump);
183 const Bool& bool_true = Bool::ZoneHandle(Bool::True());
184 __ CompareObject(RCX, bool_true);
185 __ j(EQUAL, is_instance_lbl);
186 __ jmp(is_not_instance_lbl);
187 __ Bind(&runtime_call);
188 return type_test_cache.raw();
145 } 189 }
146 190
147 191
148 // R10: instance class to check. 192 // R10: instance class to check.
149 void FlowGraphCompiler::CheckClasses(const GrowableArray<const Class*>& classes, 193 void FlowGraphCompiler::CheckClasses(const GrowableArray<const Class*>& classes,
150 Label* is_instance_lbl, 194 Label* is_instance_lbl,
151 Label* is_not_instance_lbl) { 195 Label* is_not_instance_lbl) {
152 for (intptr_t i = 0; i < classes.length(); i++) { 196 for (intptr_t i = 0; i < classes.length(); i++) {
153 __ CompareObject(R10, *classes[i]); 197 __ CompareObject(R10, *classes[i]);
154 __ j(EQUAL, is_instance_lbl); 198 __ j(EQUAL, is_instance_lbl);
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after
299 __ cmpq(RCX, raw_null); 343 __ cmpq(RCX, raw_null);
300 __ j(EQUAL, &runtime_call, Assembler::kNearJump); 344 __ j(EQUAL, &runtime_call, Assembler::kNearJump);
301 __ CompareObject(RCX, bool_true); 345 __ CompareObject(RCX, bool_true);
302 __ j(EQUAL, is_instance_lbl); 346 __ j(EQUAL, is_instance_lbl);
303 __ jmp(is_not_instance_lbl); 347 __ jmp(is_not_instance_lbl);
304 __ Bind(&runtime_call); 348 __ Bind(&runtime_call);
305 return type_test_cache.raw(); 349 return type_test_cache.raw();
306 } 350 }
307 351
308 352
353 // Generates inlined check if 'type' is a type parameter or type itsef
354 // RAX: instance (preserved).
309 RawSubtypeTestCache* FlowGraphCompiler::GenerateUninstantiatedTypeTest( 355 RawSubtypeTestCache* FlowGraphCompiler::GenerateUninstantiatedTypeTest(
310 const AbstractType& type, 356 const AbstractType& type,
311 intptr_t cid, 357 intptr_t cid,
312 intptr_t token_index, 358 intptr_t token_index,
313 Label* is_instance_lbl, 359 Label* is_instance_lbl,
314 Label* is_not_instance_lbl) { 360 Label* is_not_instance_lbl) {
361 ASSERT(!type.IsInstantiated());
362 const Immediate raw_null =
363 Immediate(reinterpret_cast<intptr_t>(Object::null()));
364 if (type.IsTypeParameter()) {
365 // Load instantiator (or null) and instantiator type arguments on stack.
366 __ movq(RDX, Address(RSP, 0)); // Get instantiator type arguments.
367 // RDX: instantiator type arguments.
368 // Check if type argument is Dynamic.
369 __ cmpq(RDX, raw_null);
370 __ j(EQUAL, is_instance_lbl);
371 // Can handle only type arguments that are instances of TypeArguments.
372 // (runtime checks canonicalize type arguments).
373 Label fall_through;
374 __ movq(R10, FieldAddress(RDX, Object::class_offset()));
375 __ CompareObject(R10, Object::ZoneHandle(Object::type_arguments_class()));
376 __ j(NOT_EQUAL, &fall_through);
377 __ movq(RDI,
378 FieldAddress(RDX, TypeArguments::type_at_offset(type.Index())));
379 // RDI: Concrete type.
380 // Check if it is Dynamic,
381 __ CompareObject(RDI, Type::ZoneHandle(Type::DynamicType()));
382 __ j(EQUAL, is_instance_lbl);
383 __ cmpq(RDI, raw_null);
384 __ j(EQUAL, is_instance_lbl);
385 // For Smi check quickly against int and num interface types.
386 Label not_smi;
387 __ testq(RAX, Immediate(kSmiTagMask)); // Value is Smi?
388 __ j(NOT_ZERO, &not_smi, Assembler::kNearJump);
389 __ CompareObject(RDI, Type::ZoneHandle(Type::IntInterface()));
390 __ j(EQUAL, is_instance_lbl);
391 __ CompareObject(RDI, Type::ZoneHandle(Type::NumberInterface()));
392 __ j(EQUAL, is_instance_lbl);
393 __ jmp(&fall_through);
394 __ Bind(&not_smi);
395 // RDX: instantiator type arguments.
396 // RAX: instance.
397 const SubtypeTestCache& type_test_cache =
398 SubtypeTestCache::ZoneHandle(SubtypeTestCache::New());
399 __ LoadObject(R10, type_test_cache);
400 __ pushq(R10); // Subtype test cache.
401 __ pushq(RAX); // Instance
402 __ pushq(RDX); // Instantiator type arguments.
403 __ call(&StubCode::Subtype3TestCacheLabel());
404 __ popq(RDX); // Discard type arguments.
405 __ popq(RAX); // Restore receiver.
406 __ popq(RDX); // Discard subtype test cache.
407 // Result is in RCX: null -> not found, otherwise Bool::True or Bool::False.
408 __ cmpq(RCX, raw_null);
409 __ j(EQUAL, &fall_through, Assembler::kNearJump);
410 const Bool& bool_true = Bool::ZoneHandle(Bool::True());
411 __ CompareObject(RCX, bool_true);
412 __ j(EQUAL, is_instance_lbl);
413 __ jmp(is_not_instance_lbl);
414 __ Bind(&fall_through);
415 return type_test_cache.raw();
416 }
417 if (type.IsType()) {
418 Label fall_through;
419 __ testq(RAX, Immediate(kSmiTagMask)); // Is instance Smi?
420 __ j(ZERO, is_not_instance_lbl);
421 __ movq(RDX, Address(RSP, 0)); // Get instantiator type arguments.
422 // Uninstantiated type class is known at compile time, but the type
423 // arguments are determined at runtime by the instantiator.
424 const SubtypeTestCache& type_test_cache =
425 SubtypeTestCache::ZoneHandle(SubtypeTestCache::New());
426 __ LoadObject(R10, type_test_cache);
427 __ pushq(R10); // Subtype test cache.
428 __ pushq(RAX); // Instance.
429 __ pushq(RDX); // Instantiator type arguments.
430 __ call(&StubCode::Subtype3TestCacheLabel());
431 __ popq(RDX); // Discard type arguments.
432 __ popq(RAX); // Restore receiver.
433 __ popq(RDX); // Discard subtype test cache.
434 // Result is in RCX: null -> not found, otherwise Bool::True or Bool::False.
435 __ cmpq(RCX, raw_null);
436 __ j(EQUAL, &fall_through, Assembler::kNearJump);
437 const Bool& bool_true = Bool::ZoneHandle(Bool::True());
438 __ CompareObject(RCX, bool_true);
439 __ j(EQUAL, is_instance_lbl);
440 __ jmp(is_not_instance_lbl);
441 __ Bind(&fall_through);
442 return type_test_cache.raw();
443 }
315 return SubtypeTestCache::null(); 444 return SubtypeTestCache::null();
316 } 445 }
317 446
318 447
319 // Inputs: 448 // Inputs:
320 // - RAX: instance to test against (preserved). 449 // - RAX: instance to test against (preserved).
321 // - RDX: optional instantiator type arguments (preserved). 450 // - RDX: optional instantiator type arguments (preserved).
322 // Destroys RCX. 451 // Destroys RCX.
323 // Returns: 452 // Returns:
324 // - unchanged object in RAX and optional instantiator type arguments in RDX. 453 // - unchanged object in RAX and optional instantiator type arguments in RDX.
(...skipping 472 matching lines...) Expand 10 before | Expand all | Expand 10 after
797 __ Bind(&done); 926 __ Bind(&done);
798 } 927 }
799 928
800 929
801 // Optimize instanceof type test by adding inlined tests for: 930 // Optimize instanceof type test by adding inlined tests for:
802 // - NULL -> return false. 931 // - NULL -> return false.
803 // - Smi -> compile time subtype check (only if dst class is not parameterized). 932 // - Smi -> compile time subtype check (only if dst class is not parameterized).
804 // - Class equality (only if class is not parameterized). 933 // - Class equality (only if class is not parameterized).
805 // Inputs: 934 // Inputs:
806 // - RAX: object. 935 // - RAX: object.
807 // - RDX: oinstantiator type arguments or raw_null. 936 // - RDX: instantiator type arguments or raw_null.
808 // - RCX: instantiator or raw_null. 937 // - RCX: instantiator or raw_null.
809 // Destroys RCX and RDX. 938 // Destroys RCX and RDX.
810 // Returns: 939 // Returns:
811 // - true or false in RAX. 940 // - true or false in RAX.
812 void FlowGraphCompiler::GenerateInstanceOf(intptr_t cid, 941 void FlowGraphCompiler::GenerateInstanceOf(intptr_t cid,
813 intptr_t token_index, 942 intptr_t token_index,
814 intptr_t try_index, 943 intptr_t try_index,
815 const AbstractType& type, 944 const AbstractType& type,
816 bool negate_result) { 945 bool negate_result) {
817 ASSERT(type.IsFinalized() && !type.IsMalformed()); 946 ASSERT(type.IsFinalized() && !type.IsMalformed());
818 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); 947 const Bool& bool_true = Bool::ZoneHandle(Bool::True());
819 const Bool& bool_false = Bool::ZoneHandle(Bool::False()); 948 const Bool& bool_false = Bool::ZoneHandle(Bool::False());
820 949
821 const Immediate raw_null = 950 const Immediate raw_null =
822 Immediate(reinterpret_cast<intptr_t>(Object::null())); 951 Immediate(reinterpret_cast<intptr_t>(Object::null()));
823 Label is_instance, is_not_instance; 952 Label is_instance, is_not_instance;
824 __ pushq(RCX); // Temporary store instantiator on stack. 953 __ pushq(RCX); // Store instantiator on stack.
954 __ pushq(RDX); // Store instantiator type arguments.
825 // If type is instantiated and non-parameterized, we can inline code 955 // If type is instantiated and non-parameterized, we can inline code
826 // checking whether the tested instance is a Smi. 956 // checking whether the tested instance is a Smi.
827 if (type.IsInstantiated()) { 957 if (type.IsInstantiated()) {
828 // A null object is only an instance of Object and Dynamic, which has 958 // A null object is only an instance of Object and Dynamic, which has
829 // already been checked above (if the type is instantiated). So we can 959 // already been checked above (if the type is instantiated). So we can
830 // return false here if the instance is null (and if the type is 960 // return false here if the instance is null (and if the type is
831 // instantiated). 961 // instantiated).
832 // We can only inline this null check if the type is instantiated at compile 962 // We can only inline this null check if the type is instantiated at compile
833 // time, since an uninstantiated type at compile time could be Object or 963 // time, since an uninstantiated type at compile time could be Object or
834 // Dynamic at run time. 964 // Dynamic at run time.
835 __ cmpq(RAX, raw_null); 965 __ cmpq(RAX, raw_null);
836 __ j(EQUAL, &is_not_instance); 966 __ j(EQUAL, &is_not_instance);
837 } 967 }
838 968
839 // Generate inline instanceof test. 969 // Generate inline instanceof test.
840 SubtypeTestCache& test_cache = SubtypeTestCache::ZoneHandle(); 970 SubtypeTestCache& test_cache = SubtypeTestCache::ZoneHandle();
841 test_cache = GenerateInlineInstanceof(cid, token_index, type, 971 test_cache = GenerateInlineInstanceof(cid, token_index, type,
842 &is_instance, &is_not_instance); 972 &is_instance, &is_not_instance);
843 973
844 // Generate runtime call. 974 // Generate runtime call.
975 __ movq(RDX, Address(RSP, 0)); // Get instantiator type arguments.
976 __ movq(RCX, Address(RSP, kWordSize)); // Get instantiator.
845 __ PushObject(Object::ZoneHandle()); // Make room for the result. 977 __ PushObject(Object::ZoneHandle()); // Make room for the result.
846 __ pushq(Immediate(Smi::RawValue(token_index))); // Source location. 978 __ pushq(Immediate(Smi::RawValue(token_index))); // Source location.
847 __ pushq(Immediate(Smi::RawValue(cid))); // Computation id. 979 __ pushq(Immediate(Smi::RawValue(cid))); // Computation id.
848 __ pushq(RAX); // Push the instance. 980 __ pushq(RAX); // Push the instance.
849 __ PushObject(type); // Push the type. 981 __ PushObject(type); // Push the type.
850 __ pushq(raw_null); // TODO(srdjan): Pass instantiator instead of null. 982 __ pushq(RCX); // TODO(srdjan): Pass instantiator instead of null.
851 if (type.IsInstantiated()) { 983 __ pushq(RDX); // Instantiator type arguments.
852 __ pushq(raw_null); // Null instantiator type arguments.
853 } else {
854 __ pushq(RDX); // Instantiator type arguments.
855 }
856 __ LoadObject(RAX, test_cache); 984 __ LoadObject(RAX, test_cache);
857 __ pushq(RAX); 985 __ pushq(RAX);
858 GenerateCallRuntime(cid, token_index, try_index, kInstanceofRuntimeEntry); 986 GenerateCallRuntime(cid, token_index, try_index, kInstanceofRuntimeEntry);
859 // Pop the two parameters supplied to the runtime entry. The result of the 987 // Pop the two parameters supplied to the runtime entry. The result of the
860 // instanceof runtime call will be left as the result of the operation. 988 // instanceof runtime call will be left as the result of the operation.
861 __ Drop(7); 989 __ Drop(7);
862 Label done; 990 Label done;
863 if (negate_result) { 991 if (negate_result) {
864 __ popq(RDX); 992 __ popq(RDX);
865 __ LoadObject(RAX, bool_true); 993 __ LoadObject(RAX, bool_true);
866 __ cmpq(RDX, RAX); 994 __ cmpq(RDX, RAX);
867 __ j(NOT_EQUAL, &done, Assembler::kNearJump); 995 __ j(NOT_EQUAL, &done, Assembler::kNearJump);
868 __ LoadObject(RAX, bool_false); 996 __ LoadObject(RAX, bool_false);
869 } else { 997 } else {
870 __ popq(RAX); 998 __ popq(RAX);
871 } 999 }
872 __ jmp(&done, Assembler::kNearJump); 1000 __ jmp(&done, Assembler::kNearJump);
873 1001
874 __ Bind(&is_not_instance); 1002 __ Bind(&is_not_instance);
875 __ LoadObject(RAX, negate_result ? bool_true : bool_false); 1003 __ LoadObject(RAX, negate_result ? bool_true : bool_false);
876 __ jmp(&done, Assembler::kNearJump); 1004 __ jmp(&done, Assembler::kNearJump);
877 1005
878 __ Bind(&is_instance); 1006 __ Bind(&is_instance);
879 __ LoadObject(RAX, negate_result ? bool_false : bool_true); 1007 __ LoadObject(RAX, negate_result ? bool_false : bool_true);
880 __ Bind(&done); 1008 __ Bind(&done);
1009 __ popq(RDX); // Remove pushed instantiator type arguments..
881 __ popq(RCX); // Remove pushed instantiator. 1010 __ popq(RCX); // Remove pushed instantiator.
882 } 1011 }
883 1012
884 1013
885 void FlowGraphCompiler::VisitInstanceOf(InstanceOfComp* comp) { 1014 void FlowGraphCompiler::VisitInstanceOf(InstanceOfComp* comp) {
886 const Immediate raw_null = 1015 const Immediate raw_null =
887 Immediate(reinterpret_cast<intptr_t>(Object::null())); 1016 Immediate(reinterpret_cast<intptr_t>(Object::null()));
888 if (comp->type_arguments() == NULL) { 1017 if (comp->type_arguments() == NULL) {
889 __ movq(RDX, raw_null); 1018 __ movq(RDX, raw_null);
890 } else { 1019 } else {
(...skipping 908 matching lines...) Expand 10 before | Expand all | Expand 10 after
1799 1928
1800 1929
1801 void FlowGraphCompiler::FinalizeComments(const Code& code) { 1930 void FlowGraphCompiler::FinalizeComments(const Code& code) {
1802 code.set_comments(assembler_->GetCodeComments()); 1931 code.set_comments(assembler_->GetCodeComments());
1803 } 1932 }
1804 1933
1805 1934
1806 } // namespace dart 1935 } // namespace dart
1807 1936
1808 #endif // defined TARGET_ARCH_X64 1937 #endif // defined TARGET_ARCH_X64
OLDNEW
« 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