Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 129 intptr_t len = OS::SNPrint(NULL, 0, kFormat, function_name, reason) + 1; | 129 intptr_t len = OS::SNPrint(NULL, 0, kFormat, function_name, reason) + 1; |
| 130 char* chars = reinterpret_cast<char*>( | 130 char* chars = reinterpret_cast<char*>( |
| 131 Isolate::Current()->current_zone()->Allocate(len)); | 131 Isolate::Current()->current_zone()->Allocate(len)); |
| 132 OS::SNPrint(chars, len, kFormat, function_name, reason); | 132 OS::SNPrint(chars, len, kFormat, function_name, reason); |
| 133 const Error& error = Error::Handle( | 133 const Error& error = Error::Handle( |
| 134 LanguageError::New(String::Handle(String::New(chars)))); | 134 LanguageError::New(String::Handle(String::New(chars)))); |
| 135 Isolate::Current()->long_jump_base()->Jump(1, error); | 135 Isolate::Current()->long_jump_base()->Jump(1, error); |
| 136 } | 136 } |
| 137 | 137 |
| 138 | 138 |
| 139 static const Class* CoreClass(const char* c_name) { | 139 static RawClass* CoreClass(const char* c_name) { |
| 140 const String& class_name = String::Handle(String::NewSymbol(c_name)); | 140 const String& class_name = String::Handle(String::NewSymbol(c_name)); |
| 141 const Class& cls = Class::ZoneHandle(Library::Handle( | 141 RawClass* raw_class = Library::Handle( |
| 142 Library::CoreImplLibrary()).LookupClass(class_name)); | 142 Library::CoreImplLibrary()).LookupClass(class_name); |
| 143 ASSERT(!cls.IsNull()); | 143 ASSERT(raw_class != Class::null()); |
| 144 return &cls; | 144 return raw_class; |
| 145 } | 145 } |
| 146 | 146 |
| 147 | 147 |
| 148 #define __ assembler_-> | 148 #define __ assembler_-> |
| 149 | 149 |
| 150 | 150 |
| 151 // Jumps to labels 'is_instance' or 'is_not_instance' respectively, if | 151 // Jumps to labels 'is_instance' or 'is_not_instance' respectively, if |
| 152 // type test is conclusive, otherwise fallthrough if a type test could not | 152 // type test is conclusive, otherwise fallthrough if a type test could not |
| 153 // be completed. | 153 // be completed. |
| 154 // RAX: instance (must survive), | 154 // RAX: instance (must survive), |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 165 // A Smi object cannot be the instance of a parameterized class. | 165 // A Smi object cannot be the instance of a parameterized class. |
| 166 __ testq(RAX, Immediate(kSmiTagMask)); | 166 __ testq(RAX, Immediate(kSmiTagMask)); |
| 167 __ j(ZERO, is_not_instance_lbl); | 167 __ j(ZERO, is_not_instance_lbl); |
| 168 const AbstractTypeArguments& type_arguments = | 168 const AbstractTypeArguments& type_arguments = |
| 169 AbstractTypeArguments::ZoneHandle(type.arguments()); | 169 AbstractTypeArguments::ZoneHandle(type.arguments()); |
| 170 const bool is_raw_type = type_arguments.IsNull() || | 170 const bool is_raw_type = type_arguments.IsNull() || |
| 171 type_arguments.IsRaw(type_arguments.Length()); | 171 type_arguments.IsRaw(type_arguments.Length()); |
| 172 if (is_raw_type) { | 172 if (is_raw_type) { |
| 173 // Dynamic type argument, check only classes. | 173 // Dynamic type argument, check only classes. |
| 174 // List is a very common case. | 174 // List is a very common case. |
| 175 __ movq(R10, FieldAddress(RAX, Object::class_offset())); | 175 __ LoadClassIndexOfObject(R10, RAX); |
| 176 if (!type_class.is_interface()) { | 176 if (!type_class.is_interface()) { |
| 177 __ CompareObject(R10, type_class); | 177 __ cmpl(R10, Immediate(type_class.index())); |
| 178 __ j(EQUAL, is_instance_lbl); | 178 __ j(EQUAL, is_instance_lbl); |
| 179 } | 179 } |
| 180 if (type.IsListInterface()) { | 180 if (type.IsListInterface()) { |
| 181 Label unknown; | 181 Label unknown; |
| 182 GrowableArray<const Class*> args; | 182 GrowableArray<const Class*> args; |
| 183 args.Add(CoreClass("ObjectArray")); | 183 args.Add(&Class::Handle(CoreClass("ObjectArray"))); |
| 184 args.Add(CoreClass("GrowableObjectArray")); | 184 args.Add(&Class::Handle(CoreClass("GrowableObjectArray"))); |
| 185 args.Add(CoreClass("ImmutableArray")); | 185 args.Add(&Class::Handle(CoreClass("ImmutableArray"))); |
| 186 CheckClasses(args, is_instance_lbl, &unknown); | 186 CheckClasses(args, is_instance_lbl, &unknown); |
| 187 __ Bind(&unknown); | 187 __ Bind(&unknown); |
| 188 } | 188 } |
| 189 return GenerateSubtype1TestCacheLookup( | 189 return GenerateSubtype1TestCacheLookup( |
| 190 cid, token_index, type_class, is_instance_lbl, is_not_instance_lbl); | 190 cid, token_index, type_class, is_instance_lbl, is_not_instance_lbl); |
| 191 } | 191 } |
| 192 // If one type argument only, check if type argument is Object or Dynamic. | 192 // If one type argument only, check if type argument is Object or Dynamic. |
| 193 if (type_arguments.Length() == 1) { | 193 if (type_arguments.Length() == 1) { |
| 194 const AbstractType& tp_argument = AbstractType::ZoneHandle( | 194 const AbstractType& tp_argument = AbstractType::ZoneHandle( |
| 195 type_arguments.TypeAt(0)); | 195 type_arguments.TypeAt(0)); |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 228 __ j(EQUAL, &runtime_call, Assembler::kNearJump); | 228 __ j(EQUAL, &runtime_call, Assembler::kNearJump); |
| 229 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); | 229 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); |
| 230 __ CompareObject(RCX, bool_true); | 230 __ CompareObject(RCX, bool_true); |
| 231 __ j(EQUAL, is_instance_lbl); | 231 __ j(EQUAL, is_instance_lbl); |
| 232 __ jmp(is_not_instance_lbl); | 232 __ jmp(is_not_instance_lbl); |
| 233 __ Bind(&runtime_call); | 233 __ Bind(&runtime_call); |
| 234 return type_test_cache.raw(); | 234 return type_test_cache.raw(); |
| 235 } | 235 } |
| 236 | 236 |
| 237 | 237 |
| 238 // R10: instance class to check. | 238 // R10: instance class to check. |
|
Ivan Posva
2012/05/30 18:15:19
// R10: instance class id to check.
| |
| 239 void FlowGraphCompiler::CheckClasses(const GrowableArray<const Class*>& classes, | 239 void FlowGraphCompiler::CheckClasses(const GrowableArray<const Class*>& classes, |
|
Ivan Posva
2012/05/30 18:15:19
How about CheckClassIds and passing a GrowableArra
| |
| 240 Label* is_instance_lbl, | 240 Label* is_instance_lbl, |
| 241 Label* is_not_instance_lbl) { | 241 Label* is_not_instance_lbl) { |
| 242 for (intptr_t i = 0; i < classes.length(); i++) { | 242 for (intptr_t i = 0; i < classes.length(); i++) { |
| 243 __ CompareObject(R10, *classes[i]); | 243 __ cmpl(R10, Immediate(classes[i]->index())); |
| 244 __ j(EQUAL, is_instance_lbl); | 244 __ j(EQUAL, is_instance_lbl); |
| 245 } | 245 } |
| 246 __ jmp(is_not_instance_lbl); | 246 __ jmp(is_not_instance_lbl); |
| 247 } | 247 } |
| 248 | 248 |
| 249 | 249 |
| 250 | 250 |
| 251 // Testing against an instantiated type with no arguments, without | 251 // Testing against an instantiated type with no arguments, without |
| 252 // SubtypeTestCache. | 252 // SubtypeTestCache. |
| 253 // RAX: instance to test against (preserved). | 253 // RAX: instance to test against (preserved). |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 273 TypeArguments::Handle(), | 273 TypeArguments::Handle(), |
| 274 &malformed_error)) { | 274 &malformed_error)) { |
| 275 __ jmp(is_instance_lbl); | 275 __ jmp(is_instance_lbl); |
| 276 } else { | 276 } else { |
| 277 __ jmp(is_not_instance_lbl); | 277 __ jmp(is_not_instance_lbl); |
| 278 } | 278 } |
| 279 | 279 |
| 280 ObjectStore* object_store = Isolate::Current()->object_store(); | 280 ObjectStore* object_store = Isolate::Current()->object_store(); |
| 281 // Compare if the classes are equal. Instance is not Smi. | 281 // Compare if the classes are equal. Instance is not Smi. |
| 282 __ Bind(&compare_classes); | 282 __ Bind(&compare_classes); |
| 283 __ movq(R10, FieldAddress(RAX, Object::class_offset())); | 283 __ LoadClassIndexOfObject(R10, RAX); |
| 284 // If type is an interface, we can skip the class equality check. | 284 // If type is an interface, we can skip the class equality check. |
| 285 if (!type_class.is_interface()) { | 285 if (!type_class.is_interface()) { |
| 286 __ CompareObject(R10, type_class); | 286 __ cmpl(R10, Immediate(type_class.index())); |
| 287 __ j(EQUAL, is_instance_lbl); | 287 __ j(EQUAL, is_instance_lbl); |
| 288 } | 288 } |
| 289 // Check for interfaces that cannot be implemented by user. | 289 // Check for interfaces that cannot be implemented by user. |
| 290 // (see ClassFinalizer::ResolveInterfaces for list of restricted interfaces). | 290 // (see ClassFinalizer::ResolveInterfaces for list of restricted interfaces). |
| 291 // Bool interface can be implemented only by core class Bool. | 291 // Bool interface can be implemented only by core class Bool. |
| 292 if (type.IsBoolInterface()) { | 292 if (type.IsBoolInterface()) { |
| 293 const Class& bool_class = Class::ZoneHandle(object_store->bool_class()); | 293 __ cmpl(R10, Immediate(kBool)); |
| 294 __ CompareObject(R10, bool_class); | |
| 295 __ j(EQUAL, is_instance_lbl); | 294 __ j(EQUAL, is_instance_lbl); |
| 296 __ jmp(is_not_instance_lbl); | 295 __ jmp(is_not_instance_lbl); |
| 297 return; | 296 return; |
| 298 } | 297 } |
| 299 if (type.IsFunctionInterface()) { | 298 if (type.IsFunctionInterface()) { |
| 300 // Check if instance is a closure. | 299 // Check if instance is a closure. |
| 301 const Immediate raw_null = | 300 const Immediate raw_null = |
| 302 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 301 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 303 __ movq(R10, FieldAddress(R10, Class::signature_function_offset())); | 302 __ LoadClassByIndex(R13, R10); |
| 304 __ cmpq(R10, raw_null); | 303 __ movq(R13, FieldAddress(R13, Class::signature_function_offset())); |
| 304 __ cmpq(R13, raw_null); | |
| 305 __ j(NOT_EQUAL, is_instance_lbl); | 305 __ j(NOT_EQUAL, is_instance_lbl); |
| 306 __ jmp(is_not_instance_lbl); | 306 __ jmp(is_not_instance_lbl); |
| 307 return; | 307 return; |
| 308 } | 308 } |
| 309 // Custom checking for numbers (Smi, Mint, Bigint and Double). | 309 // Custom checking for numbers (Smi, Mint, Bigint and Double). |
| 310 // Note that instance is not Smi(checked above). | 310 // Note that instance is not Smi(checked above). |
| 311 if (type.IsSubtypeOf( | 311 if (type.IsSubtypeOf( |
| 312 Type::Handle(Type::NumberInterface()), &malformed_error)) { | 312 Type::Handle(Type::NumberInterface()), &malformed_error)) { |
| 313 const Class& mint_class = Class::ZoneHandle(object_store->mint_class()); | 313 const Class& mint_class = Class::Handle(object_store->mint_class()); |
|
Ivan Posva
2012/05/30 18:15:19
kMint
| |
| 314 const Class& bigint_class = Class::ZoneHandle(object_store->bigint_class()); | 314 const Class& bigint_class = Class::Handle(object_store->bigint_class()); |
|
Ivan Posva
2012/05/30 18:15:19
kBigInt
| |
| 315 const Class& double_class = Class::ZoneHandle(object_store->double_class()); | 315 const Class& double_class = Class::Handle(object_store->double_class()); |
|
Ivan Posva
2012/05/30 18:15:19
kDouble
| |
| 316 GrowableArray<const Class*> args; | 316 GrowableArray<const Class*> args; |
| 317 if (type.IsNumberInterface()) { | 317 if (type.IsNumberInterface()) { |
| 318 args.Add(&double_class); | 318 args.Add(&double_class); |
| 319 args.Add(&mint_class); | 319 args.Add(&mint_class); |
| 320 args.Add(&bigint_class); | 320 args.Add(&bigint_class); |
| 321 } else if (type.IsIntInterface()) { | 321 } else if (type.IsIntInterface()) { |
| 322 args.Add(&mint_class); | 322 args.Add(&mint_class); |
| 323 args.Add(&bigint_class); | 323 args.Add(&bigint_class); |
| 324 } else if (type.IsDoubleInterface()) { | 324 } else if (type.IsDoubleInterface()) { |
| 325 args.Add(&double_class); | 325 args.Add(&double_class); |
| 326 } | 326 } |
| 327 CheckClasses(args, is_instance_lbl, is_not_instance_lbl); | 327 CheckClasses(args, is_instance_lbl, is_not_instance_lbl); |
| 328 return; | 328 return; |
| 329 } | 329 } |
| 330 if (type.IsStringInterface()) { | 330 if (type.IsStringInterface()) { |
| 331 const Class& one_byte_string_class = | 331 const Class& one_byte_string_class = |
|
Ivan Posva
2012/05/30 18:15:19
ditto, here and below...
| |
| 332 Class::ZoneHandle(object_store->one_byte_string_class()); | 332 Class::Handle(object_store->one_byte_string_class()); |
| 333 const Class& two_byte_string_class = | 333 const Class& two_byte_string_class = |
| 334 Class::ZoneHandle(object_store->two_byte_string_class()); | 334 Class::Handle(object_store->two_byte_string_class()); |
| 335 const Class& four_byte_string_class = | 335 const Class& four_byte_string_class = |
| 336 Class::ZoneHandle(object_store->four_byte_string_class()); | 336 Class::Handle(object_store->four_byte_string_class()); |
| 337 const Class& external_one_byte_string_class = | 337 const Class& external_one_byte_string_class = |
| 338 Class::ZoneHandle(object_store->external_one_byte_string_class()); | 338 Class::Handle(object_store->external_one_byte_string_class()); |
| 339 const Class& external_two_byte_string_class = | 339 const Class& external_two_byte_string_class = |
| 340 Class::ZoneHandle(object_store->external_two_byte_string_class()); | 340 Class::Handle(object_store->external_two_byte_string_class()); |
| 341 const Class& external_four_byte_string_class = | 341 const Class& external_four_byte_string_class = |
| 342 Class::ZoneHandle(object_store->external_four_byte_string_class()); | 342 Class::Handle(object_store->external_four_byte_string_class()); |
| 343 GrowableArray<const Class*> args; | 343 GrowableArray<const Class*> args; |
| 344 args.Add(&one_byte_string_class); | 344 args.Add(&one_byte_string_class); |
| 345 args.Add(&two_byte_string_class); | 345 args.Add(&two_byte_string_class); |
| 346 args.Add(&four_byte_string_class); | 346 args.Add(&four_byte_string_class); |
| 347 args.Add(&external_one_byte_string_class); | 347 args.Add(&external_one_byte_string_class); |
| 348 args.Add(&external_two_byte_string_class); | 348 args.Add(&external_two_byte_string_class); |
| 349 args.Add(&external_four_byte_string_class); | 349 args.Add(&external_four_byte_string_class); |
| 350 CheckClasses(args, is_instance_lbl, is_not_instance_lbl); | 350 CheckClasses(args, is_instance_lbl, is_not_instance_lbl); |
| 351 return; | 351 return; |
| 352 } | 352 } |
| 353 // Otherwise fallthrough. | 353 // Otherwise fallthrough. |
| 354 } | 354 } |
| 355 | 355 |
| 356 | 356 |
| 357 // Uses SubtypeTestCache to store instance class and result. | 357 // Uses SubtypeTestCache to store instance class and result. |
| 358 // RAX: instance to test. | 358 // RAX: instance to test. |
| 359 // Immediate class test already done. | 359 // Immediate class test already done. |
| 360 RawSubtypeTestCache* FlowGraphCompiler::GenerateSubtype1TestCacheLookup( | 360 RawSubtypeTestCache* FlowGraphCompiler::GenerateSubtype1TestCacheLookup( |
| 361 intptr_t cid, | 361 intptr_t cid, |
| 362 intptr_t token_index, | 362 intptr_t token_index, |
| 363 const Class& type_class, | 363 const Class& type_class, |
| 364 Label* is_instance_lbl, | 364 Label* is_instance_lbl, |
| 365 Label* is_not_instance_lbl) { | 365 Label* is_not_instance_lbl) { |
| 366 const SubtypeTestCache& type_test_cache = | 366 const SubtypeTestCache& type_test_cache = |
| 367 SubtypeTestCache::ZoneHandle(SubtypeTestCache::New()); | 367 SubtypeTestCache::ZoneHandle(SubtypeTestCache::New()); |
| 368 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); | 368 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); |
| 369 const Immediate raw_null = | 369 const Immediate raw_null = |
| 370 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 370 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 371 __ movq(R10, FieldAddress(RAX, Object::class_offset())); | 371 __ LoadClassOfObject(R10, RAX); |
| 372 // Check immediate superclass equality. | 372 // Check immediate superclass equality. |
| 373 __ movq(R13, FieldAddress(R10, Class::super_type_offset())); | 373 __ movq(R13, FieldAddress(R10, Class::super_type_offset())); |
| 374 __ movq(R13, FieldAddress(R13, Type::type_class_offset())); | 374 __ movq(R13, FieldAddress(R13, Type::type_class_offset())); |
| 375 __ CompareObject(R13, type_class); | 375 __ CompareObject(R13, type_class); |
| 376 __ j(EQUAL, is_instance_lbl); | 376 __ j(EQUAL, is_instance_lbl); |
| 377 | 377 |
| 378 __ LoadObject(R10, type_test_cache); | 378 __ LoadObject(R10, type_test_cache); |
| 379 __ pushq(R10); // Cache array. | 379 __ pushq(R10); // Cache array. |
| 380 __ pushq(RAX); // Instance. | 380 __ pushq(RAX); // Instance. |
| 381 __ pushq(raw_null); // Unused | 381 __ pushq(raw_null); // Unused |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 410 if (type.IsTypeParameter()) { | 410 if (type.IsTypeParameter()) { |
| 411 // Load instantiator (or null) and instantiator type arguments on stack. | 411 // Load instantiator (or null) and instantiator type arguments on stack. |
| 412 __ movq(RDX, Address(RSP, 0)); // Get instantiator type arguments. | 412 __ movq(RDX, Address(RSP, 0)); // Get instantiator type arguments. |
| 413 // RDX: instantiator type arguments. | 413 // RDX: instantiator type arguments. |
| 414 // Check if type argument is Dynamic. | 414 // Check if type argument is Dynamic. |
| 415 __ cmpq(RDX, raw_null); | 415 __ cmpq(RDX, raw_null); |
| 416 __ j(EQUAL, is_instance_lbl); | 416 __ j(EQUAL, is_instance_lbl); |
| 417 // Can handle only type arguments that are instances of TypeArguments. | 417 // Can handle only type arguments that are instances of TypeArguments. |
| 418 // (runtime checks canonicalize type arguments). | 418 // (runtime checks canonicalize type arguments). |
| 419 Label fall_through; | 419 Label fall_through; |
| 420 __ movq(R10, FieldAddress(RDX, Object::class_offset())); | 420 __ CompareClassOfObject(RDX, |
| 421 __ CompareObject(R10, Object::ZoneHandle(Object::type_arguments_class())); | 421 Class::Handle(Object::type_arguments_class())); |
| 422 __ j(NOT_EQUAL, &fall_through); | 422 __ j(NOT_EQUAL, &fall_through); |
| 423 __ movq(RDI, | 423 __ movq(RDI, |
| 424 FieldAddress(RDX, TypeArguments::type_at_offset(type.Index()))); | 424 FieldAddress(RDX, TypeArguments::type_at_offset(type.Index()))); |
| 425 // RDI: Concrete type. | 425 // RDI: Concrete type. |
| 426 // Check if it is Dynamic, | 426 // Check if it is Dynamic, |
| 427 __ CompareObject(RDI, Type::ZoneHandle(Type::DynamicType())); | 427 __ CompareObject(RDI, Type::ZoneHandle(Type::DynamicType())); |
| 428 __ j(EQUAL, is_instance_lbl); | 428 __ j(EQUAL, is_instance_lbl); |
| 429 __ cmpq(RDI, raw_null); | 429 __ cmpq(RDI, raw_null); |
| 430 __ j(EQUAL, is_instance_lbl); | 430 __ j(EQUAL, is_instance_lbl); |
| 431 // For Smi check quickly against int and num interface types. | 431 // For Smi check quickly against int and num interface types. |
| (...skipping 577 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1009 __ cmpq(RAX, raw_null); | 1009 __ cmpq(RAX, raw_null); |
| 1010 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); | 1010 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); |
| 1011 } | 1011 } |
| 1012 // Instantiate non-null type arguments. | 1012 // Instantiate non-null type arguments. |
| 1013 if (comp->type_arguments().IsUninstantiatedIdentity()) { | 1013 if (comp->type_arguments().IsUninstantiatedIdentity()) { |
| 1014 // Check if the instantiator type argument vector is a TypeArguments of a | 1014 // Check if the instantiator type argument vector is a TypeArguments of a |
| 1015 // matching length and, if so, use it as the instantiated type_arguments. | 1015 // matching length and, if so, use it as the instantiated type_arguments. |
| 1016 // No need to check the instantiator (RAX) for null here, because a null | 1016 // No need to check the instantiator (RAX) for null here, because a null |
| 1017 // instantiator will have the wrong class (Null instead of TypeArguments). | 1017 // instantiator will have the wrong class (Null instead of TypeArguments). |
| 1018 Label type_arguments_uninstantiated; | 1018 Label type_arguments_uninstantiated; |
| 1019 __ LoadObject(RCX, Class::ZoneHandle(Object::type_arguments_class())); | 1019 __ CompareClassOfObject(RAX, |
| 1020 __ cmpq(RCX, FieldAddress(RAX, Object::class_offset())); | 1020 Class::Handle(Object::type_arguments_class())); |
| 1021 __ j(NOT_EQUAL, &type_arguments_uninstantiated, Assembler::kNearJump); | 1021 __ j(NOT_EQUAL, &type_arguments_uninstantiated, Assembler::kNearJump); |
| 1022 Immediate arguments_length = | 1022 Immediate arguments_length = |
| 1023 Immediate(Smi::RawValue(comp->type_arguments().Length())); | 1023 Immediate(Smi::RawValue(comp->type_arguments().Length())); |
| 1024 __ cmpq(FieldAddress(RAX, TypeArguments::length_offset()), | 1024 __ cmpq(FieldAddress(RAX, TypeArguments::length_offset()), |
| 1025 arguments_length); | 1025 arguments_length); |
| 1026 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); | 1026 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); |
| 1027 __ Bind(&type_arguments_uninstantiated); | 1027 __ Bind(&type_arguments_uninstantiated); |
| 1028 } | 1028 } |
| 1029 // In the non-factory case, we rely on the allocation stub to | 1029 // In the non-factory case, we rely on the allocation stub to |
| 1030 // instantiate the type arguments. | 1030 // instantiate the type arguments. |
| (...skipping 691 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1722 | 1722 |
| 1723 void FlowGraphCompiler::FinalizeComments(const Code& code) { | 1723 void FlowGraphCompiler::FinalizeComments(const Code& code) { |
| 1724 code.set_comments(assembler_->GetCodeComments()); | 1724 code.set_comments(assembler_->GetCodeComments()); |
| 1725 } | 1725 } |
| 1726 | 1726 |
| 1727 #undef __ | 1727 #undef __ |
| 1728 | 1728 |
| 1729 } // namespace dart | 1729 } // namespace dart |
| 1730 | 1730 |
| 1731 #endif // defined TARGET_ARCH_X64 | 1731 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |