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

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