| 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) { | |
| 140 const String& class_name = String::Handle(String::NewSymbol(c_name)); | |
| 141 const Class& cls = Class::ZoneHandle(Library::Handle( | |
| 142 Library::CoreImplLibrary()).LookupClass(class_name)); | |
| 143 ASSERT(!cls.IsNull()); | |
| 144 return &cls; | |
| 145 } | |
| 146 | |
| 147 | |
| 148 #define __ assembler_-> | 139 #define __ assembler_-> |
| 149 | 140 |
| 150 | 141 |
| 151 // Jumps to labels 'is_instance' or 'is_not_instance' respectively, if | 142 // Jumps to labels 'is_instance' or 'is_not_instance' respectively, if |
| 152 // type test is conclusive, otherwise fallthrough if a type test could not | 143 // type test is conclusive, otherwise fallthrough if a type test could not |
| 153 // be completed. | 144 // be completed. |
| 154 // RAX: instance (must survive), | 145 // RAX: instance (must survive), |
| 155 RawSubtypeTestCache* | 146 RawSubtypeTestCache* |
| 156 FlowGraphCompiler::GenerateInstantiatedTypeWithArgumentsTest( | 147 FlowGraphCompiler::GenerateInstantiatedTypeWithArgumentsTest( |
| 157 intptr_t cid, | 148 intptr_t cid, |
| 158 intptr_t token_index, | 149 intptr_t token_index, |
| 159 const AbstractType& type, | 150 const AbstractType& type, |
| 160 Label* is_instance_lbl, | 151 Label* is_instance_lbl, |
| 161 Label* is_not_instance_lbl) { | 152 Label* is_not_instance_lbl) { |
| 162 ASSERT(type.IsInstantiated()); | 153 ASSERT(type.IsInstantiated()); |
| 163 const Class& type_class = Class::ZoneHandle(type.type_class()); | 154 const Class& type_class = Class::ZoneHandle(type.type_class()); |
| 164 ASSERT(type_class.HasTypeArguments()); | 155 ASSERT(type_class.HasTypeArguments()); |
| 165 // A Smi object cannot be the instance of a parameterized class. | 156 // A Smi object cannot be the instance of a parameterized class. |
| 166 __ testq(RAX, Immediate(kSmiTagMask)); | 157 __ testq(RAX, Immediate(kSmiTagMask)); |
| 167 __ j(ZERO, is_not_instance_lbl); | 158 __ j(ZERO, is_not_instance_lbl); |
| 168 const AbstractTypeArguments& type_arguments = | 159 const AbstractTypeArguments& type_arguments = |
| 169 AbstractTypeArguments::ZoneHandle(type.arguments()); | 160 AbstractTypeArguments::ZoneHandle(type.arguments()); |
| 170 const bool is_raw_type = type_arguments.IsNull() || | 161 const bool is_raw_type = type_arguments.IsNull() || |
| 171 type_arguments.IsRaw(type_arguments.Length()); | 162 type_arguments.IsRaw(type_arguments.Length()); |
| 172 if (is_raw_type) { | 163 if (is_raw_type) { |
| 173 // Dynamic type argument, check only classes. | 164 // Dynamic type argument, check only classes. |
| 174 // List is a very common case. | 165 // List is a very common case. |
| 175 __ movq(R10, FieldAddress(RAX, Object::class_offset())); | 166 __ LoadClassId(R10, RAX); |
| 176 if (!type_class.is_interface()) { | 167 if (!type_class.is_interface()) { |
| 177 __ CompareObject(R10, type_class); | 168 __ cmpl(R10, Immediate(type_class.index())); |
| 178 __ j(EQUAL, is_instance_lbl); | 169 __ j(EQUAL, is_instance_lbl); |
| 179 } | 170 } |
| 180 if (type.IsListInterface()) { | 171 if (type.IsListInterface()) { |
| 181 Label unknown; | 172 Label unknown; |
| 182 GrowableArray<const Class*> args; | 173 GrowableArray<intptr_t> args; |
| 183 args.Add(CoreClass("ObjectArray")); | 174 args.Add(kArray); |
| 184 args.Add(CoreClass("GrowableObjectArray")); | 175 args.Add(kGrowableObjectArray); |
| 185 args.Add(CoreClass("ImmutableArray")); | 176 args.Add(kImmutableArray); |
| 186 CheckClasses(args, is_instance_lbl, &unknown); | 177 CheckClassIds(args, is_instance_lbl, &unknown); |
| 187 __ Bind(&unknown); | 178 __ Bind(&unknown); |
| 188 } | 179 } |
| 189 return GenerateSubtype1TestCacheLookup( | 180 return GenerateSubtype1TestCacheLookup( |
| 190 cid, token_index, type_class, is_instance_lbl, is_not_instance_lbl); | 181 cid, token_index, type_class, is_instance_lbl, is_not_instance_lbl); |
| 191 } | 182 } |
| 192 // If one type argument only, check if type argument is Object or Dynamic. | 183 // If one type argument only, check if type argument is Object or Dynamic. |
| 193 if (type_arguments.Length() == 1) { | 184 if (type_arguments.Length() == 1) { |
| 194 const AbstractType& tp_argument = AbstractType::ZoneHandle( | 185 const AbstractType& tp_argument = AbstractType::ZoneHandle( |
| 195 type_arguments.TypeAt(0)); | 186 type_arguments.TypeAt(0)); |
| 196 ASSERT(!tp_argument.IsMalformed()); | 187 ASSERT(!tp_argument.IsMalformed()); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 228 __ j(EQUAL, &runtime_call, Assembler::kNearJump); | 219 __ j(EQUAL, &runtime_call, Assembler::kNearJump); |
| 229 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); | 220 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); |
| 230 __ CompareObject(RCX, bool_true); | 221 __ CompareObject(RCX, bool_true); |
| 231 __ j(EQUAL, is_instance_lbl); | 222 __ j(EQUAL, is_instance_lbl); |
| 232 __ jmp(is_not_instance_lbl); | 223 __ jmp(is_not_instance_lbl); |
| 233 __ Bind(&runtime_call); | 224 __ Bind(&runtime_call); |
| 234 return type_test_cache.raw(); | 225 return type_test_cache.raw(); |
| 235 } | 226 } |
| 236 | 227 |
| 237 | 228 |
| 238 // R10: instance class to check. | 229 // R10: instance class id to check. |
| 239 void FlowGraphCompiler::CheckClasses(const GrowableArray<const Class*>& classes, | 230 void FlowGraphCompiler::CheckClassIds(const GrowableArray<intptr_t>& class_ids, |
| 240 Label* is_instance_lbl, | 231 Label* is_instance_lbl, |
| 241 Label* is_not_instance_lbl) { | 232 Label* is_not_instance_lbl) { |
| 242 for (intptr_t i = 0; i < classes.length(); i++) { | 233 for (intptr_t i = 0; i < class_ids.length(); i++) { |
| 243 __ CompareObject(R10, *classes[i]); | 234 __ cmpl(R10, Immediate(class_ids[i])); |
| 244 __ j(EQUAL, is_instance_lbl); | 235 __ j(EQUAL, is_instance_lbl); |
| 245 } | 236 } |
| 246 __ jmp(is_not_instance_lbl); | 237 __ jmp(is_not_instance_lbl); |
| 247 } | 238 } |
| 248 | 239 |
| 249 | 240 |
| 250 | 241 |
| 251 // Testing against an instantiated type with no arguments, without | 242 // Testing against an instantiated type with no arguments, without |
| 252 // SubtypeTestCache. | 243 // SubtypeTestCache. |
| 253 // RAX: instance to test against (preserved). | 244 // RAX: instance to test against (preserved). |
| (...skipping 16 matching lines...) Expand all Loading... |
| 270 Error& malformed_error = Error::Handle(); | 261 Error& malformed_error = Error::Handle(); |
| 271 if (smi_class.IsSubtypeOf(TypeArguments::Handle(), | 262 if (smi_class.IsSubtypeOf(TypeArguments::Handle(), |
| 272 type_class, | 263 type_class, |
| 273 TypeArguments::Handle(), | 264 TypeArguments::Handle(), |
| 274 &malformed_error)) { | 265 &malformed_error)) { |
| 275 __ jmp(is_instance_lbl); | 266 __ jmp(is_instance_lbl); |
| 276 } else { | 267 } else { |
| 277 __ jmp(is_not_instance_lbl); | 268 __ jmp(is_not_instance_lbl); |
| 278 } | 269 } |
| 279 | 270 |
| 280 ObjectStore* object_store = Isolate::Current()->object_store(); | |
| 281 // Compare if the classes are equal. Instance is not Smi. | 271 // Compare if the classes are equal. Instance is not Smi. |
| 282 __ Bind(&compare_classes); | 272 __ Bind(&compare_classes); |
| 283 __ movq(R10, FieldAddress(RAX, Object::class_offset())); | 273 __ LoadClassId(R10, RAX); |
| 284 // If type is an interface, we can skip the class equality check. | 274 // If type is an interface, we can skip the class equality check. |
| 285 if (!type_class.is_interface()) { | 275 if (!type_class.is_interface()) { |
| 286 __ CompareObject(R10, type_class); | 276 __ cmpl(R10, Immediate(type_class.index())); |
| 287 __ j(EQUAL, is_instance_lbl); | 277 __ j(EQUAL, is_instance_lbl); |
| 288 } | 278 } |
| 289 // Check for interfaces that cannot be implemented by user. | 279 // Check for interfaces that cannot be implemented by user. |
| 290 // (see ClassFinalizer::ResolveInterfaces for list of restricted interfaces). | 280 // (see ClassFinalizer::ResolveInterfaces for list of restricted interfaces). |
| 291 // Bool interface can be implemented only by core class Bool. | 281 // Bool interface can be implemented only by core class Bool. |
| 292 if (type.IsBoolInterface()) { | 282 if (type.IsBoolInterface()) { |
| 293 const Class& bool_class = Class::ZoneHandle(object_store->bool_class()); | 283 __ cmpl(R10, Immediate(kBool)); |
| 294 __ CompareObject(R10, bool_class); | |
| 295 __ j(EQUAL, is_instance_lbl); | 284 __ j(EQUAL, is_instance_lbl); |
| 296 __ jmp(is_not_instance_lbl); | 285 __ jmp(is_not_instance_lbl); |
| 297 return; | 286 return; |
| 298 } | 287 } |
| 299 if (type.IsFunctionInterface()) { | 288 if (type.IsFunctionInterface()) { |
| 300 // Check if instance is a closure. | 289 // Check if instance is a closure. |
| 301 const Immediate raw_null = | 290 const Immediate raw_null = |
| 302 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 291 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 303 __ movq(R10, FieldAddress(R10, Class::signature_function_offset())); | 292 __ LoadClassById(R13, R10); |
| 304 __ cmpq(R10, raw_null); | 293 __ movq(R13, FieldAddress(R13, Class::signature_function_offset())); |
| 294 __ cmpq(R13, raw_null); |
| 305 __ j(NOT_EQUAL, is_instance_lbl); | 295 __ j(NOT_EQUAL, is_instance_lbl); |
| 306 __ jmp(is_not_instance_lbl); | 296 __ jmp(is_not_instance_lbl); |
| 307 return; | 297 return; |
| 308 } | 298 } |
| 309 // Custom checking for numbers (Smi, Mint, Bigint and Double). | 299 // Custom checking for numbers (Smi, Mint, Bigint and Double). |
| 310 // Note that instance is not Smi(checked above). | 300 // Note that instance is not Smi(checked above). |
| 311 if (type.IsSubtypeOf( | 301 if (type.IsSubtypeOf( |
| 312 Type::Handle(Type::NumberInterface()), &malformed_error)) { | 302 Type::Handle(Type::NumberInterface()), &malformed_error)) { |
| 313 const Class& mint_class = Class::ZoneHandle(object_store->mint_class()); | 303 GrowableArray<intptr_t> args; |
| 314 const Class& bigint_class = Class::ZoneHandle(object_store->bigint_class()); | |
| 315 const Class& double_class = Class::ZoneHandle(object_store->double_class()); | |
| 316 GrowableArray<const Class*> args; | |
| 317 if (type.IsNumberInterface()) { | 304 if (type.IsNumberInterface()) { |
| 318 args.Add(&double_class); | 305 args.Add(kDouble); |
| 319 args.Add(&mint_class); | 306 args.Add(kMint); |
| 320 args.Add(&bigint_class); | 307 args.Add(kBigint); |
| 321 } else if (type.IsIntInterface()) { | 308 } else if (type.IsIntInterface()) { |
| 322 args.Add(&mint_class); | 309 args.Add(kMint); |
| 323 args.Add(&bigint_class); | 310 args.Add(kBigint); |
| 324 } else if (type.IsDoubleInterface()) { | 311 } else if (type.IsDoubleInterface()) { |
| 325 args.Add(&double_class); | 312 args.Add(kDouble); |
| 326 } | 313 } |
| 327 CheckClasses(args, is_instance_lbl, is_not_instance_lbl); | 314 CheckClassIds(args, is_instance_lbl, is_not_instance_lbl); |
| 328 return; | 315 return; |
| 329 } | 316 } |
| 330 if (type.IsStringInterface()) { | 317 if (type.IsStringInterface()) { |
| 331 const Class& one_byte_string_class = | 318 GrowableArray<intptr_t> args; |
| 332 Class::ZoneHandle(object_store->one_byte_string_class()); | 319 args.Add(kOneByteString); |
| 333 const Class& two_byte_string_class = | 320 args.Add(kTwoByteString); |
| 334 Class::ZoneHandle(object_store->two_byte_string_class()); | 321 args.Add(kFourByteString); |
| 335 const Class& four_byte_string_class = | 322 args.Add(kExternalOneByteString); |
| 336 Class::ZoneHandle(object_store->four_byte_string_class()); | 323 args.Add(kExternalTwoByteString); |
| 337 const Class& external_one_byte_string_class = | 324 args.Add(kExternalFourByteString); |
| 338 Class::ZoneHandle(object_store->external_one_byte_string_class()); | 325 CheckClassIds(args, is_instance_lbl, is_not_instance_lbl); |
| 339 const Class& external_two_byte_string_class = | |
| 340 Class::ZoneHandle(object_store->external_two_byte_string_class()); | |
| 341 const Class& external_four_byte_string_class = | |
| 342 Class::ZoneHandle(object_store->external_four_byte_string_class()); | |
| 343 GrowableArray<const Class*> args; | |
| 344 args.Add(&one_byte_string_class); | |
| 345 args.Add(&two_byte_string_class); | |
| 346 args.Add(&four_byte_string_class); | |
| 347 args.Add(&external_one_byte_string_class); | |
| 348 args.Add(&external_two_byte_string_class); | |
| 349 args.Add(&external_four_byte_string_class); | |
| 350 CheckClasses(args, is_instance_lbl, is_not_instance_lbl); | |
| 351 return; | 326 return; |
| 352 } | 327 } |
| 353 // Otherwise fallthrough. | 328 // Otherwise fallthrough. |
| 354 } | 329 } |
| 355 | 330 |
| 356 | 331 |
| 357 // Uses SubtypeTestCache to store instance class and result. | 332 // Uses SubtypeTestCache to store instance class and result. |
| 358 // RAX: instance to test. | 333 // RAX: instance to test. |
| 359 // Immediate class test already done. | 334 // Immediate class test already done. |
| 360 RawSubtypeTestCache* FlowGraphCompiler::GenerateSubtype1TestCacheLookup( | 335 RawSubtypeTestCache* FlowGraphCompiler::GenerateSubtype1TestCacheLookup( |
| 361 intptr_t cid, | 336 intptr_t cid, |
| 362 intptr_t token_index, | 337 intptr_t token_index, |
| 363 const Class& type_class, | 338 const Class& type_class, |
| 364 Label* is_instance_lbl, | 339 Label* is_instance_lbl, |
| 365 Label* is_not_instance_lbl) { | 340 Label* is_not_instance_lbl) { |
| 366 const SubtypeTestCache& type_test_cache = | 341 const SubtypeTestCache& type_test_cache = |
| 367 SubtypeTestCache::ZoneHandle(SubtypeTestCache::New()); | 342 SubtypeTestCache::ZoneHandle(SubtypeTestCache::New()); |
| 368 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); | 343 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); |
| 369 const Immediate raw_null = | 344 const Immediate raw_null = |
| 370 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 345 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 371 __ movq(R10, FieldAddress(RAX, Object::class_offset())); | 346 __ LoadClass(R10, RAX); |
| 372 // Check immediate superclass equality. | 347 // Check immediate superclass equality. |
| 373 __ movq(R13, FieldAddress(R10, Class::super_type_offset())); | 348 __ movq(R13, FieldAddress(R10, Class::super_type_offset())); |
| 374 __ movq(R13, FieldAddress(R13, Type::type_class_offset())); | 349 __ movq(R13, FieldAddress(R13, Type::type_class_offset())); |
| 375 __ CompareObject(R13, type_class); | 350 __ CompareObject(R13, type_class); |
| 376 __ j(EQUAL, is_instance_lbl); | 351 __ j(EQUAL, is_instance_lbl); |
| 377 | 352 |
| 378 __ LoadObject(R10, type_test_cache); | 353 __ LoadObject(R10, type_test_cache); |
| 379 __ pushq(R10); // Cache array. | 354 __ pushq(R10); // Cache array. |
| 380 __ pushq(RAX); // Instance. | 355 __ pushq(RAX); // Instance. |
| 381 __ pushq(raw_null); // Unused | 356 __ pushq(raw_null); // Unused |
| (...skipping 28 matching lines...) Expand all Loading... |
| 410 if (type.IsTypeParameter()) { | 385 if (type.IsTypeParameter()) { |
| 411 // Load instantiator (or null) and instantiator type arguments on stack. | 386 // Load instantiator (or null) and instantiator type arguments on stack. |
| 412 __ movq(RDX, Address(RSP, 0)); // Get instantiator type arguments. | 387 __ movq(RDX, Address(RSP, 0)); // Get instantiator type arguments. |
| 413 // RDX: instantiator type arguments. | 388 // RDX: instantiator type arguments. |
| 414 // Check if type argument is Dynamic. | 389 // Check if type argument is Dynamic. |
| 415 __ cmpq(RDX, raw_null); | 390 __ cmpq(RDX, raw_null); |
| 416 __ j(EQUAL, is_instance_lbl); | 391 __ j(EQUAL, is_instance_lbl); |
| 417 // Can handle only type arguments that are instances of TypeArguments. | 392 // Can handle only type arguments that are instances of TypeArguments. |
| 418 // (runtime checks canonicalize type arguments). | 393 // (runtime checks canonicalize type arguments). |
| 419 Label fall_through; | 394 Label fall_through; |
| 420 __ movq(R10, FieldAddress(RDX, Object::class_offset())); | 395 __ CompareClassId(RDX, kTypeArguments); |
| 421 __ CompareObject(R10, Object::ZoneHandle(Object::type_arguments_class())); | |
| 422 __ j(NOT_EQUAL, &fall_through); | 396 __ j(NOT_EQUAL, &fall_through); |
| 423 __ movq(RDI, | 397 __ movq(RDI, |
| 424 FieldAddress(RDX, TypeArguments::type_at_offset(type.Index()))); | 398 FieldAddress(RDX, TypeArguments::type_at_offset(type.Index()))); |
| 425 // RDI: Concrete type. | 399 // RDI: Concrete type. |
| 426 // Check if it is Dynamic, | 400 // Check if it is Dynamic, |
| 427 __ CompareObject(RDI, Type::ZoneHandle(Type::DynamicType())); | 401 __ CompareObject(RDI, Type::ZoneHandle(Type::DynamicType())); |
| 428 __ j(EQUAL, is_instance_lbl); | 402 __ j(EQUAL, is_instance_lbl); |
| 429 __ cmpq(RDI, raw_null); | 403 __ cmpq(RDI, raw_null); |
| 430 __ j(EQUAL, is_instance_lbl); | 404 __ j(EQUAL, is_instance_lbl); |
| 431 // For Smi check quickly against int and num interface types. | 405 // 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); | 983 __ cmpq(RAX, raw_null); |
| 1010 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); | 984 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); |
| 1011 } | 985 } |
| 1012 // Instantiate non-null type arguments. | 986 // Instantiate non-null type arguments. |
| 1013 if (comp->type_arguments().IsUninstantiatedIdentity()) { | 987 if (comp->type_arguments().IsUninstantiatedIdentity()) { |
| 1014 // Check if the instantiator type argument vector is a TypeArguments of a | 988 // 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. | 989 // 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 | 990 // No need to check the instantiator (RAX) for null here, because a null |
| 1017 // instantiator will have the wrong class (Null instead of TypeArguments). | 991 // instantiator will have the wrong class (Null instead of TypeArguments). |
| 1018 Label type_arguments_uninstantiated; | 992 Label type_arguments_uninstantiated; |
| 1019 __ LoadObject(RCX, Class::ZoneHandle(Object::type_arguments_class())); | 993 __ CompareClassId(RAX, kTypeArguments); |
| 1020 __ cmpq(RCX, FieldAddress(RAX, Object::class_offset())); | |
| 1021 __ j(NOT_EQUAL, &type_arguments_uninstantiated, Assembler::kNearJump); | 994 __ j(NOT_EQUAL, &type_arguments_uninstantiated, Assembler::kNearJump); |
| 1022 Immediate arguments_length = | 995 Immediate arguments_length = |
| 1023 Immediate(Smi::RawValue(comp->type_arguments().Length())); | 996 Immediate(Smi::RawValue(comp->type_arguments().Length())); |
| 1024 __ cmpq(FieldAddress(RAX, TypeArguments::length_offset()), | 997 __ cmpq(FieldAddress(RAX, TypeArguments::length_offset()), |
| 1025 arguments_length); | 998 arguments_length); |
| 1026 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); | 999 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); |
| 1027 __ Bind(&type_arguments_uninstantiated); | 1000 __ Bind(&type_arguments_uninstantiated); |
| 1028 } | 1001 } |
| 1029 // In the non-factory case, we rely on the allocation stub to | 1002 // In the non-factory case, we rely on the allocation stub to |
| 1030 // instantiate the type arguments. | 1003 // instantiate the type arguments. |
| (...skipping 691 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1722 | 1695 |
| 1723 void FlowGraphCompiler::FinalizeComments(const Code& code) { | 1696 void FlowGraphCompiler::FinalizeComments(const Code& code) { |
| 1724 code.set_comments(assembler_->GetCodeComments()); | 1697 code.set_comments(assembler_->GetCodeComments()); |
| 1725 } | 1698 } |
| 1726 | 1699 |
| 1727 #undef __ | 1700 #undef __ |
| 1728 | 1701 |
| 1729 } // namespace dart | 1702 } // namespace dart |
| 1730 | 1703 |
| 1731 #endif // defined TARGET_ARCH_X64 | 1704 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |