| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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_MIPS. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_MIPS. |
| 6 #if defined(TARGET_ARCH_MIPS) | 6 #if defined(TARGET_ARCH_MIPS) |
| 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 266 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 277 const Register kTempReg = kNoRegister; | 277 const Register kTempReg = kNoRegister; |
| 278 return GenerateCallSubtypeTestStub(kTestTypeOneArg, | 278 return GenerateCallSubtypeTestStub(kTestTypeOneArg, |
| 279 kInstanceReg, | 279 kInstanceReg, |
| 280 kTypeArgumentsReg, | 280 kTypeArgumentsReg, |
| 281 kTempReg, | 281 kTempReg, |
| 282 is_instance_lbl, | 282 is_instance_lbl, |
| 283 is_not_instance_lbl); | 283 is_not_instance_lbl); |
| 284 } | 284 } |
| 285 | 285 |
| 286 | 286 |
| 287 // Generates inlined check if 'type' is a type parameter or type itself |
| 288 // A0: instance (preserved). |
| 287 RawSubtypeTestCache* FlowGraphCompiler::GenerateUninstantiatedTypeTest( | 289 RawSubtypeTestCache* FlowGraphCompiler::GenerateUninstantiatedTypeTest( |
| 288 intptr_t token_pos, | 290 intptr_t token_pos, |
| 289 const AbstractType& type, | 291 const AbstractType& type, |
| 290 Label* is_instance_lbl, | 292 Label* is_instance_lbl, |
| 291 Label* is_not_instance_lbl) { | 293 Label* is_not_instance_lbl) { |
| 292 UNIMPLEMENTED(); | 294 __ Comment("UninstantiatedTypeTest"); |
| 293 return NULL; | 295 ASSERT(!type.IsInstantiated()); |
| 296 // Skip check if destination is a dynamic type. |
| 297 if (type.IsTypeParameter()) { |
| 298 const TypeParameter& type_param = TypeParameter::Cast(type); |
| 299 // Load instantiator (or null) and instantiator type arguments on stack. |
| 300 __ lw(A1, Address(SP, 0)); // Get instantiator type arguments. |
| 301 // A1: instantiator type arguments. |
| 302 // Check if type argument is dynamic. |
| 303 __ BranchEqual(A1, reinterpret_cast<intptr_t>(Object::null()), |
| 304 is_instance_lbl); |
| 305 // Can handle only type arguments that are instances of TypeArguments. |
| 306 // (runtime checks canonicalize type arguments). |
| 307 Label fall_through; |
| 308 __ LoadClassId(T2, A1); |
| 309 __ BranchNotEqual(T2, kTypeArgumentsCid, &fall_through); |
| 310 __ lw(T2, |
| 311 FieldAddress(A1, TypeArguments::type_at_offset(type_param.index()))); |
| 312 // R2: concrete type of type. |
| 313 // Check if type argument is dynamic. |
| 314 __ BranchEqual(T2, Type::ZoneHandle(Type::DynamicType()), is_instance_lbl); |
| 315 __ BranchEqual(T2, reinterpret_cast<intptr_t>(Object::null()), |
| 316 is_instance_lbl); |
| 317 const Type& object_type = Type::ZoneHandle(Type::ObjectType()); |
| 318 __ BranchEqual(T2, object_type, is_instance_lbl); |
| 319 |
| 320 // For Smi check quickly against int and num interfaces. |
| 321 Label not_smi; |
| 322 __ andi(CMPRES, A0, Immediate(kSmiTagMask)); |
| 323 __ bne(CMPRES, ZR, ¬_smi); // Value is Smi? |
| 324 __ BranchEqual(T2, Type::ZoneHandle(Type::IntType()), is_instance_lbl); |
| 325 __ BranchEqual(T2, Type::ZoneHandle(Type::Number()), is_instance_lbl); |
| 326 |
| 327 // Smi must be handled in runtime. |
| 328 __ b(&fall_through); |
| 329 |
| 330 __ Bind(¬_smi); |
| 331 // T1: instantiator type arguments. |
| 332 // A0: instance. |
| 333 const Register kInstanceReg = A0; |
| 334 const Register kTypeArgumentsReg = A1; |
| 335 const Register kTempReg = kNoRegister; |
| 336 const SubtypeTestCache& type_test_cache = |
| 337 SubtypeTestCache::ZoneHandle( |
| 338 GenerateCallSubtypeTestStub(kTestTypeThreeArgs, |
| 339 kInstanceReg, |
| 340 kTypeArgumentsReg, |
| 341 kTempReg, |
| 342 is_instance_lbl, |
| 343 is_not_instance_lbl)); |
| 344 __ Bind(&fall_through); |
| 345 return type_test_cache.raw(); |
| 346 } |
| 347 if (type.IsType()) { |
| 348 const Register kInstanceReg = A0; |
| 349 const Register kTypeArgumentsReg = A1; |
| 350 __ andi(CMPRES, kInstanceReg, Immediate(kSmiTagMask)); |
| 351 __ beq(CMPRES, ZR, is_not_instance_lbl); // Is instance Smi? |
| 352 __ lw(kTypeArgumentsReg, Address(SP, 0)); // Instantiator type args. |
| 353 // Uninstantiated type class is known at compile time, but the type |
| 354 // arguments are determined at runtime by the instantiator. |
| 355 const Register kTempReg = kNoRegister; |
| 356 return GenerateCallSubtypeTestStub(kTestTypeThreeArgs, |
| 357 kInstanceReg, |
| 358 kTypeArgumentsReg, |
| 359 kTempReg, |
| 360 is_instance_lbl, |
| 361 is_not_instance_lbl); |
| 362 } |
| 363 return SubtypeTestCache::null(); |
| 294 } | 364 } |
| 295 | 365 |
| 296 | 366 |
| 297 // Inputs: | 367 // Inputs: |
| 298 // - A0: instance being type checked (preserved). | 368 // - A0: instance being type checked (preserved). |
| 299 // - A1: optional instantiator type arguments (preserved). | 369 // - A1: optional instantiator type arguments (preserved). |
| 300 // Returns: | 370 // Returns: |
| 301 // - preserved instance in A0 and optional instantiator type arguments in A1. | 371 // - preserved instance in A0 and optional instantiator type arguments in A1. |
| 302 // Clobbers: T0, T1, T2 | 372 // Clobbers: T0, T1, T2 |
| 303 // Note that this inlined code must be followed by the runtime_call code, as it | 373 // Note that this inlined code must be followed by the runtime_call code, as it |
| (...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 439 __ addiu(SP, SP, Immediate(2 * kWordSize)); | 509 __ addiu(SP, SP, Immediate(2 * kWordSize)); |
| 440 return; | 510 return; |
| 441 } | 511 } |
| 442 | 512 |
| 443 // Generate inline type check, linking to runtime call if not assignable. | 513 // Generate inline type check, linking to runtime call if not assignable. |
| 444 SubtypeTestCache& test_cache = SubtypeTestCache::ZoneHandle(); | 514 SubtypeTestCache& test_cache = SubtypeTestCache::ZoneHandle(); |
| 445 test_cache = GenerateInlineInstanceof(token_pos, dst_type, | 515 test_cache = GenerateInlineInstanceof(token_pos, dst_type, |
| 446 &is_assignable, &runtime_call); | 516 &is_assignable, &runtime_call); |
| 447 | 517 |
| 448 __ Bind(&runtime_call); | 518 __ Bind(&runtime_call); |
| 449 // Load instantiator and its type arguments. | 519 // Load instantiator (A2) and its type arguments (A1). |
| 450 __ lw(A1, Address(SP, 0 * kWordSize)); | 520 __ lw(A1, Address(SP, 0 * kWordSize)); |
| 451 __ lw(A2, Address(SP, 1 * kWordSize)); | 521 __ lw(A2, Address(SP, 1 * kWordSize)); |
| 452 | 522 |
| 453 __ addiu(SP, SP, Immediate(-7 * kWordSize)); | 523 __ addiu(SP, SP, Immediate(-7 * kWordSize)); |
| 454 __ LoadObject(TMP1, Object::ZoneHandle()); | 524 __ LoadObject(TMP1, Object::ZoneHandle()); |
| 455 __ sw(TMP1, Address(SP, 6 * kWordSize)); // Make room for the result. | 525 __ sw(TMP1, Address(SP, 6 * kWordSize)); // Make room for the result. |
| 456 __ sw(A0, Address(SP, 5 * kWordSize)); // Push the source object. | 526 __ sw(A0, Address(SP, 5 * kWordSize)); // Push the source object. |
| 457 __ LoadObject(TMP1, dst_type); | 527 __ LoadObject(TMP1, dst_type); |
| 458 __ sw(TMP1, Address(SP, 4 * kWordSize)); // Push the type of the destination. | 528 __ sw(TMP1, Address(SP, 4 * kWordSize)); // Push the type of the destination. |
| 459 __ sw(A2, Address(SP, 3 * kWordSize)); // Push instantiator. | 529 __ sw(A2, Address(SP, 3 * kWordSize)); // Push instantiator. |
| 460 __ sw(A1, Address(SP, 2 * kWordSize)); // Push type arguments. | 530 __ sw(A1, Address(SP, 2 * kWordSize)); // Push type arguments. |
| 461 __ LoadObject(TMP1, dst_name); | 531 __ LoadObject(TMP1, dst_name); |
| 462 __ sw(TMP1, Address(SP, 1 * kWordSize)); // Push the name of the destination. | 532 __ sw(TMP1, Address(SP, 1 * kWordSize)); // Push the name of the destination. |
| 533 __ LoadObject(T0, test_cache); |
| 463 __ sw(T0, Address(SP, 0 * kWordSize)); | 534 __ sw(T0, Address(SP, 0 * kWordSize)); |
| 464 | 535 |
| 465 GenerateCallRuntime(token_pos, deopt_id, kTypeCheckRuntimeEntry, locs); | 536 GenerateCallRuntime(token_pos, deopt_id, kTypeCheckRuntimeEntry, locs); |
| 466 // Pop the parameters supplied to the runtime entry. The result of the | 537 // Pop the parameters supplied to the runtime entry. The result of the |
| 467 // type check runtime call is the checked value. | 538 // type check runtime call is the checked value. |
| 468 __ lw(A0, Address(SP, 6 * kWordSize)); | 539 __ lw(A0, Address(SP, 6 * kWordSize)); |
| 469 __ addiu(SP, SP, Immediate(7 * kWordSize)); | 540 __ addiu(SP, SP, Immediate(7 * kWordSize)); |
| 470 | 541 |
| 471 __ Bind(&is_assignable); | 542 __ Bind(&is_assignable); |
| 472 // Restore instantiator and its type arguments. | 543 // Restore instantiator and its type arguments. |
| (...skipping 989 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1462 __ AddImmediate(SP, kDoubleSize); | 1533 __ AddImmediate(SP, kDoubleSize); |
| 1463 } | 1534 } |
| 1464 | 1535 |
| 1465 | 1536 |
| 1466 #undef __ | 1537 #undef __ |
| 1467 | 1538 |
| 1468 | 1539 |
| 1469 } // namespace dart | 1540 } // namespace dart |
| 1470 | 1541 |
| 1471 #endif // defined TARGET_ARCH_MIPS | 1542 #endif // defined TARGET_ARCH_MIPS |
| OLD | NEW |