| 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 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 42 | 42 |
| 43 void CompilerDeoptInfoWithStub::GenerateCode(FlowGraphCompiler* compiler, | 43 void CompilerDeoptInfoWithStub::GenerateCode(FlowGraphCompiler* compiler, |
| 44 intptr_t stub_ix) { | 44 intptr_t stub_ix) { |
| 45 UNIMPLEMENTED(); | 45 UNIMPLEMENTED(); |
| 46 } | 46 } |
| 47 | 47 |
| 48 | 48 |
| 49 #define __ assembler()-> | 49 #define __ assembler()-> |
| 50 | 50 |
| 51 | 51 |
| 52 // Fall through if bool_register contains null. |
| 52 void FlowGraphCompiler::GenerateBoolToJump(Register bool_register, | 53 void FlowGraphCompiler::GenerateBoolToJump(Register bool_register, |
| 53 Label* is_true, | 54 Label* is_true, |
| 54 Label* is_false) { | 55 Label* is_false) { |
| 55 UNIMPLEMENTED(); | 56 Label fall_through; |
| 57 __ BranchEqual(bool_register, reinterpret_cast<intptr_t>(Object::null()), |
| 58 &fall_through); |
| 59 __ BranchEqual(bool_register, Bool::True(), is_true); |
| 60 __ b(is_false); |
| 61 __ Bind(&fall_through); |
| 56 } | 62 } |
| 57 | 63 |
| 58 | 64 |
| 65 // A0: instance (must be preserved). |
| 66 // A1: instantiator type arguments (if used). |
| 59 RawSubtypeTestCache* FlowGraphCompiler::GenerateCallSubtypeTestStub( | 67 RawSubtypeTestCache* FlowGraphCompiler::GenerateCallSubtypeTestStub( |
| 60 TypeTestStubKind test_kind, | 68 TypeTestStubKind test_kind, |
| 61 Register instance_reg, | 69 Register instance_reg, |
| 62 Register type_arguments_reg, | 70 Register type_arguments_reg, |
| 63 Register temp_reg, | 71 Register temp_reg, |
| 64 Label* is_instance_lbl, | 72 Label* is_instance_lbl, |
| 65 Label* is_not_instance_lbl) { | 73 Label* is_not_instance_lbl) { |
| 66 UNIMPLEMENTED(); | 74 ASSERT(instance_reg == A0); |
| 67 return NULL; | 75 ASSERT(temp_reg == kNoRegister); // Unused on MIPS. |
| 76 const SubtypeTestCache& type_test_cache = |
| 77 SubtypeTestCache::ZoneHandle(SubtypeTestCache::New()); |
| 78 __ LoadObject(A2, type_test_cache); |
| 79 if (test_kind == kTestTypeOneArg) { |
| 80 ASSERT(type_arguments_reg == kNoRegister); |
| 81 __ LoadImmediate(A1, reinterpret_cast<intptr_t>(Object::null())); |
| 82 __ BranchLink(&StubCode::Subtype1TestCacheLabel()); |
| 83 } else if (test_kind == kTestTypeTwoArgs) { |
| 84 ASSERT(type_arguments_reg == kNoRegister); |
| 85 __ LoadImmediate(A1, reinterpret_cast<intptr_t>(Object::null())); |
| 86 __ BranchLink(&StubCode::Subtype2TestCacheLabel()); |
| 87 } else if (test_kind == kTestTypeThreeArgs) { |
| 88 ASSERT(type_arguments_reg == A1); |
| 89 __ BranchLink(&StubCode::Subtype3TestCacheLabel()); |
| 90 } else { |
| 91 UNREACHABLE(); |
| 92 } |
| 93 // Result is in V0: null -> not found, otherwise Bool::True or Bool::False. |
| 94 GenerateBoolToJump(V0, is_instance_lbl, is_not_instance_lbl); |
| 95 return type_test_cache.raw(); |
| 68 } | 96 } |
| 69 | 97 |
| 70 | 98 |
| 71 RawSubtypeTestCache* | 99 RawSubtypeTestCache* |
| 72 FlowGraphCompiler::GenerateInstantiatedTypeWithArgumentsTest( | 100 FlowGraphCompiler::GenerateInstantiatedTypeWithArgumentsTest( |
| 73 intptr_t token_pos, | 101 intptr_t token_pos, |
| 74 const AbstractType& type, | 102 const AbstractType& type, |
| 75 Label* is_instance_lbl, | 103 Label* is_instance_lbl, |
| 76 Label* is_not_instance_lbl) { | 104 Label* is_not_instance_lbl) { |
| 77 UNIMPLEMENTED(); | 105 UNIMPLEMENTED(); |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 146 } | 174 } |
| 147 if (type.IsStringType()) { | 175 if (type.IsStringType()) { |
| 148 GenerateStringTypeCheck(kClassIdReg, is_instance_lbl, is_not_instance_lbl); | 176 GenerateStringTypeCheck(kClassIdReg, is_instance_lbl, is_not_instance_lbl); |
| 149 return false; | 177 return false; |
| 150 } | 178 } |
| 151 // Otherwise fallthrough. | 179 // Otherwise fallthrough. |
| 152 return true; | 180 return true; |
| 153 } | 181 } |
| 154 | 182 |
| 155 | 183 |
| 184 // Uses SubtypeTestCache to store instance class and result. |
| 185 // A0: instance to test. |
| 186 // Clobbers A1, A2, T0-T3. |
| 187 // Immediate class test already done. |
| 188 // TODO(srdjan): Implement a quicker subtype check, as type test |
| 189 // arrays can grow too high, but they may be useful when optimizing |
| 190 // code (type-feedback). |
| 156 RawSubtypeTestCache* FlowGraphCompiler::GenerateSubtype1TestCacheLookup( | 191 RawSubtypeTestCache* FlowGraphCompiler::GenerateSubtype1TestCacheLookup( |
| 157 intptr_t token_pos, | 192 intptr_t token_pos, |
| 158 const Class& type_class, | 193 const Class& type_class, |
| 159 Label* is_instance_lbl, | 194 Label* is_instance_lbl, |
| 160 Label* is_not_instance_lbl) { | 195 Label* is_not_instance_lbl) { |
| 161 UNIMPLEMENTED(); | 196 __ Comment("Subtype1TestCacheLookup"); |
| 162 return NULL; | 197 const Register kInstanceReg = A0; |
| 198 __ LoadClass(T0, kInstanceReg); |
| 199 // T0: instance class. |
| 200 // Check immediate superclass equality. |
| 201 __ lw(T0, FieldAddress(T0, Class::super_type_offset())); |
| 202 __ lw(T0, FieldAddress(T0, Type::type_class_offset())); |
| 203 __ BranchEqual(T0, type_class, is_instance_lbl); |
| 204 |
| 205 const Register kTypeArgumentsReg = kNoRegister; |
| 206 const Register kTempReg = kNoRegister; |
| 207 return GenerateCallSubtypeTestStub(kTestTypeOneArg, |
| 208 kInstanceReg, |
| 209 kTypeArgumentsReg, |
| 210 kTempReg, |
| 211 is_instance_lbl, |
| 212 is_not_instance_lbl); |
| 163 } | 213 } |
| 164 | 214 |
| 165 | 215 |
| 166 RawSubtypeTestCache* FlowGraphCompiler::GenerateUninstantiatedTypeTest( | 216 RawSubtypeTestCache* FlowGraphCompiler::GenerateUninstantiatedTypeTest( |
| 167 intptr_t token_pos, | 217 intptr_t token_pos, |
| 168 const AbstractType& type, | 218 const AbstractType& type, |
| 169 Label* is_instance_lbl, | 219 Label* is_instance_lbl, |
| 170 Label* is_not_instance_lbl) { | 220 Label* is_not_instance_lbl) { |
| 171 UNIMPLEMENTED(); | 221 UNIMPLEMENTED(); |
| 172 return NULL; | 222 return NULL; |
| (...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 322 __ lw(A2, Address(SP, 1 * kWordSize)); | 372 __ lw(A2, Address(SP, 1 * kWordSize)); |
| 323 __ addiu(SP, SP, Immediate(2 * kWordSize)); | 373 __ addiu(SP, SP, Immediate(2 * kWordSize)); |
| 324 __ PushObject(Object::ZoneHandle()); // Make room for the result. | 374 __ PushObject(Object::ZoneHandle()); // Make room for the result. |
| 325 __ Push(A0); // Push the source object. | 375 __ Push(A0); // Push the source object. |
| 326 __ PushObject(dst_type); // Push the type of the destination. | 376 __ PushObject(dst_type); // Push the type of the destination. |
| 327 // Push instantiator and its type arguments. | 377 // Push instantiator and its type arguments. |
| 328 __ addiu(SP, SP, Immediate(-2 * kWordSize)); | 378 __ addiu(SP, SP, Immediate(-2 * kWordSize)); |
| 329 __ sw(A2, Address(SP, 1 * kWordSize)); | 379 __ sw(A2, Address(SP, 1 * kWordSize)); |
| 330 __ sw(A1, Address(SP, 0 * kWordSize)); | 380 __ sw(A1, Address(SP, 0 * kWordSize)); |
| 331 __ PushObject(dst_name); // Push the name of the destination. | 381 __ PushObject(dst_name); // Push the name of the destination. |
| 332 __ LoadObject(A0, test_cache); | 382 __ LoadObject(T0, test_cache); |
| 333 __ Push(A0); | 383 __ Push(T0); |
| 334 GenerateCallRuntime(token_pos, deopt_id, kTypeCheckRuntimeEntry, locs); | 384 GenerateCallRuntime(token_pos, deopt_id, kTypeCheckRuntimeEntry, locs); |
| 335 // Pop the parameters supplied to the runtime entry. The result of the | 385 // Pop the parameters supplied to the runtime entry. The result of the |
| 336 // type check runtime call is the checked value. | 386 // type check runtime call is the checked value. |
| 337 __ Drop(6); | 387 __ Drop(6); |
| 338 __ Pop(A0); | 388 __ Pop(A0); |
| 339 | 389 |
| 340 __ Bind(&is_assignable); | 390 __ Bind(&is_assignable); |
| 341 // Restore instantiator and its type arguments. | 391 // Restore instantiator and its type arguments. |
| 342 __ lw(A1, Address(SP, 0 * kWordSize)); | 392 __ lw(A1, Address(SP, 0 * kWordSize)); |
| 343 __ lw(A2, Address(SP, 1 * kWordSize)); | 393 __ lw(A2, Address(SP, 1 * kWordSize)); |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 398 // Argument i passed at fp[kLastParamSlotIndex + num_args - 1 - i] is copied | 448 // Argument i passed at fp[kLastParamSlotIndex + num_args - 1 - i] is copied |
| 399 // to fp[kFirstLocalSlotIndex - i]. | 449 // to fp[kFirstLocalSlotIndex - i]. |
| 400 | 450 |
| 401 __ lw(T1, FieldAddress(S4, ArgumentsDescriptor::count_offset())); | 451 __ lw(T1, FieldAddress(S4, ArgumentsDescriptor::count_offset())); |
| 402 // Since T1 and T2 are Smi, use sll 1 instead of sll 2. | 452 // Since T1 and T2 are Smi, use sll 1 instead of sll 2. |
| 403 // Let T1 point to the last passed positional argument, i.e. to | 453 // Let T1 point to the last passed positional argument, i.e. to |
| 404 // fp[kLastParamSlotIndex + num_args - 1 - (num_pos_args - 1)]. | 454 // fp[kLastParamSlotIndex + num_args - 1 - (num_pos_args - 1)]. |
| 405 __ subu(T1, T1, T2); | 455 __ subu(T1, T1, T2); |
| 406 __ sll(T1, T1, 1); | 456 __ sll(T1, T1, 1); |
| 407 __ addu(T1, FP, T1); | 457 __ addu(T1, FP, T1); |
| 408 __ addiu(T1, T1, Immediate(kLastParamSlotIndex * kWordSize)); | 458 __ AddImmediate(T1, kLastParamSlotIndex * kWordSize); |
| 409 | 459 |
| 410 // Let T0 point to the last copied positional argument, i.e. to | 460 // Let T0 point to the last copied positional argument, i.e. to |
| 411 // fp[kFirstLocalSlotIndex - (num_pos_args - 1)]. | 461 // fp[kFirstLocalSlotIndex - (num_pos_args - 1)]. |
| 412 __ addiu(T0, FP, Immediate((kFirstLocalSlotIndex + 1) * kWordSize)); | 462 __ AddImmediate(T0, FP, (kFirstLocalSlotIndex + 1) * kWordSize); |
| 413 __ sll(T3, T2, 1); // T2 is a Smi. | 463 __ sll(T3, T2, 1); // T2 is a Smi. |
| 414 __ subu(T0, T0, T3); | 464 __ subu(T0, T0, T3); |
| 415 | 465 |
| 416 Label loop, loop_condition; | 466 Label loop, loop_condition; |
| 417 __ b(&loop_condition); | 467 __ b(&loop_condition); |
| 418 __ delay_slot()->SmiUntag(T2); | 468 __ delay_slot()->SmiUntag(T2); |
| 419 // We do not use the final allocation index of the variable here, i.e. | 469 // We do not use the final allocation index of the variable here, i.e. |
| 420 // scope->VariableAt(i)->index(), because captured variables still need | 470 // scope->VariableAt(i)->index(), because captured variables still need |
| 421 // to be copied to the context that is not yet allocated. | 471 // to be copied to the context that is not yet allocated. |
| 422 __ Bind(&loop); | 472 __ Bind(&loop); |
| (...skipping 27 matching lines...) Expand all Loading... |
| 450 opt_param_position[i + 1] = pos; | 500 opt_param_position[i + 1] = pos; |
| 451 } | 501 } |
| 452 // Generate code handling each optional parameter in alphabetical order. | 502 // Generate code handling each optional parameter in alphabetical order. |
| 453 __ lw(T1, FieldAddress(S4, ArgumentsDescriptor::count_offset())); | 503 __ lw(T1, FieldAddress(S4, ArgumentsDescriptor::count_offset())); |
| 454 __ lw(T2, FieldAddress(S4, ArgumentsDescriptor::positional_count_offset())); | 504 __ lw(T2, FieldAddress(S4, ArgumentsDescriptor::positional_count_offset())); |
| 455 __ SmiUntag(T2); | 505 __ SmiUntag(T2); |
| 456 // Let T1 point to the first passed argument, i.e. to | 506 // Let T1 point to the first passed argument, i.e. to |
| 457 // fp[kLastParamSlotIndex + num_args - 1 - 0]; num_args (T1) is Smi. | 507 // fp[kLastParamSlotIndex + num_args - 1 - 0]; num_args (T1) is Smi. |
| 458 __ sll(T3, T1, 1); | 508 __ sll(T3, T1, 1); |
| 459 __ addu(T1, FP, T3); | 509 __ addu(T1, FP, T3); |
| 460 __ addiu(T1, T1, Immediate((kLastParamSlotIndex - 1) * kWordSize)); | 510 __ AddImmediate(T1, (kLastParamSlotIndex - 1) * kWordSize); |
| 461 // Let T0 point to the entry of the first named argument. | 511 // Let T0 point to the entry of the first named argument. |
| 462 __ addiu(T0, S4, Immediate( | 512 __ AddImmediate(T0, S4, |
| 463 ArgumentsDescriptor::first_named_entry_offset() - kHeapObjectTag)); | 513 ArgumentsDescriptor::first_named_entry_offset() - kHeapObjectTag); |
| 464 for (int i = 0; i < num_opt_named_params; i++) { | 514 for (int i = 0; i < num_opt_named_params; i++) { |
| 465 Label load_default_value, assign_optional_parameter; | 515 Label load_default_value, assign_optional_parameter; |
| 466 const int param_pos = opt_param_position[i]; | 516 const int param_pos = opt_param_position[i]; |
| 467 // Check if this named parameter was passed in. | 517 // Check if this named parameter was passed in. |
| 468 // Load T3 with the name of the argument. | 518 // Load T3 with the name of the argument. |
| 469 __ lw(T3, Address(T0, ArgumentsDescriptor::name_offset())); | 519 __ lw(T3, Address(T0, ArgumentsDescriptor::name_offset())); |
| 470 ASSERT(opt_param[i]->name().IsSymbol()); | 520 ASSERT(opt_param[i]->name().IsSymbol()); |
| 471 __ BranchNotEqual(T3, opt_param[i]->name(), &load_default_value); | 521 __ BranchNotEqual(T3, opt_param[i]->name(), &load_default_value); |
| 472 | 522 |
| 473 // Load T3 with passed-in argument at provided arg_pos, i.e. at | 523 // Load T3 with passed-in argument at provided arg_pos, i.e. at |
| 474 // fp[kLastParamSlotIndex + num_args - 1 - arg_pos]. | 524 // fp[kLastParamSlotIndex + num_args - 1 - arg_pos]. |
| 475 __ lw(T3, Address(T0, ArgumentsDescriptor::position_offset())); | 525 __ lw(T3, Address(T0, ArgumentsDescriptor::position_offset())); |
| 476 // T3 is arg_pos as Smi. | 526 // T3 is arg_pos as Smi. |
| 477 // Point to next named entry. | 527 // Point to next named entry. |
| 478 __ addiu(T0, T0, Immediate(ArgumentsDescriptor::named_entry_size())); | 528 __ AddImmediate(T0, ArgumentsDescriptor::named_entry_size()); |
| 479 __ subu(T3, ZR, T3); | 529 __ subu(T3, ZR, T3); |
| 480 __ sll(T3, T3, 1); | 530 __ sll(T3, T3, 1); |
| 481 __ addu(T3, T1, T3); | 531 __ addu(T3, T1, T3); |
| 482 __ b(&assign_optional_parameter); | 532 __ b(&assign_optional_parameter); |
| 483 __ delay_slot()->lw(T3, Address(T3)); | 533 __ delay_slot()->lw(T3, Address(T3)); |
| 484 | 534 |
| 485 __ Bind(&load_default_value); | 535 __ Bind(&load_default_value); |
| 486 // Load T3 with default argument. | 536 // Load T3 with default argument. |
| 487 const Object& value = Object::ZoneHandle( | 537 const Object& value = Object::ZoneHandle( |
| 488 parsed_function().default_parameter_values().At( | 538 parsed_function().default_parameter_values().At( |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 530 __ SmiUntag(T1); | 580 __ SmiUntag(T1); |
| 531 // Check that T2 equals T1, i.e. no named arguments passed. | 581 // Check that T2 equals T1, i.e. no named arguments passed. |
| 532 __ beq(T2, T1, &all_arguments_processed); | 582 __ beq(T2, T1, &all_arguments_processed); |
| 533 } | 583 } |
| 534 | 584 |
| 535 __ Bind(&wrong_num_arguments); | 585 __ Bind(&wrong_num_arguments); |
| 536 if (StackSize() != 0) { | 586 if (StackSize() != 0) { |
| 537 // We need to unwind the space we reserved for locals and copied parameters. | 587 // We need to unwind the space we reserved for locals and copied parameters. |
| 538 // The NoSuchMethodFunction stub does not expect to see that area on the | 588 // The NoSuchMethodFunction stub does not expect to see that area on the |
| 539 // stack. | 589 // stack. |
| 540 __ addiu(SP, SP, Immediate(StackSize() * kWordSize)); | 590 __ AddImmediate(SP, StackSize() * kWordSize); |
| 541 } | 591 } |
| 542 // The call below has an empty stackmap because we have just | 592 // The call below has an empty stackmap because we have just |
| 543 // dropped the spill slots. | 593 // dropped the spill slots. |
| 544 BitmapBuilder* empty_stack_bitmap = new BitmapBuilder(); | 594 BitmapBuilder* empty_stack_bitmap = new BitmapBuilder(); |
| 545 | 595 |
| 546 // Invoke noSuchMethod function passing the original name of the function. | 596 // Invoke noSuchMethod function passing the original name of the function. |
| 547 // If the function is a closure function, use "call" as the original name. | 597 // If the function is a closure function, use "call" as the original name. |
| 548 const String& name = String::Handle( | 598 const String& name = String::Handle( |
| 549 function.IsClosureFunction() ? Symbols::Call().raw() : function.name()); | 599 function.IsClosureFunction() ? Symbols::Call().raw() : function.name()); |
| 550 const int kNumArgsChecked = 1; | 600 const int kNumArgsChecked = 1; |
| (...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 723 | 773 |
| 724 __ lw(T1, FieldAddress(S4, | 774 __ lw(T1, FieldAddress(S4, |
| 725 ArgumentsDescriptor::positional_count_offset())); | 775 ArgumentsDescriptor::positional_count_offset())); |
| 726 __ beq(T0, T1, &correct_num_arguments); | 776 __ beq(T0, T1, &correct_num_arguments); |
| 727 __ Bind(&wrong_num_arguments); | 777 __ Bind(&wrong_num_arguments); |
| 728 if (function.IsClosureFunction()) { | 778 if (function.IsClosureFunction()) { |
| 729 if (StackSize() != 0) { | 779 if (StackSize() != 0) { |
| 730 // We need to unwind the space we reserved for locals and copied | 780 // We need to unwind the space we reserved for locals and copied |
| 731 // parameters. The NoSuchMethodFunction stub does not expect to see | 781 // parameters. The NoSuchMethodFunction stub does not expect to see |
| 732 // that area on the stack. | 782 // that area on the stack. |
| 733 __ addiu(SP, SP, Immediate(StackSize() * kWordSize)); | 783 __ AddImmediate(SP, StackSize() * kWordSize); |
| 734 } | 784 } |
| 735 // The call below has an empty stackmap because we have just | 785 // The call below has an empty stackmap because we have just |
| 736 // dropped the spill slots. | 786 // dropped the spill slots. |
| 737 BitmapBuilder* empty_stack_bitmap = new BitmapBuilder(); | 787 BitmapBuilder* empty_stack_bitmap = new BitmapBuilder(); |
| 738 | 788 |
| 739 // Invoke noSuchMethod function passing "call" as the function name. | 789 // Invoke noSuchMethod function passing "call" as the function name. |
| 740 const int kNumArgsChecked = 1; | 790 const int kNumArgsChecked = 1; |
| 741 const ICData& ic_data = ICData::ZoneHandle( | 791 const ICData& ic_data = ICData::ZoneHandle( |
| 742 ICData::New(function, Symbols::Call(), | 792 ICData::New(function, Symbols::Call(), |
| 743 Isolate::kNoDeoptId, kNumArgsChecked)); | 793 Isolate::kNoDeoptId, kNumArgsChecked)); |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 851 deopt_id, | 901 deopt_id, |
| 852 token_pos); | 902 token_pos); |
| 853 } | 903 } |
| 854 } | 904 } |
| 855 | 905 |
| 856 | 906 |
| 857 void FlowGraphCompiler::GenerateCallRuntime(intptr_t token_pos, | 907 void FlowGraphCompiler::GenerateCallRuntime(intptr_t token_pos, |
| 858 intptr_t deopt_id, | 908 intptr_t deopt_id, |
| 859 const RuntimeEntry& entry, | 909 const RuntimeEntry& entry, |
| 860 LocationSummary* locs) { | 910 LocationSummary* locs) { |
| 861 __ Unimplemented("call runtime"); | 911 __ CallRuntime(entry); |
| 912 AddCurrentDescriptor(PcDescriptors::kOther, deopt_id, token_pos); |
| 913 RecordSafepoint(locs); |
| 914 if (deopt_id != Isolate::kNoDeoptId) { |
| 915 // Marks either the continuation point in unoptimized code or the |
| 916 // deoptimization point in optimized code, after call. |
| 917 if (is_optimizing()) { |
| 918 AddDeoptIndexAtCall(deopt_id, token_pos); |
| 919 } else { |
| 920 // Add deoptimization continuation point after the call and before the |
| 921 // arguments are removed. |
| 922 AddCurrentDescriptor(PcDescriptors::kDeoptAfter, |
| 923 deopt_id, |
| 924 token_pos); |
| 925 } |
| 926 } |
| 862 } | 927 } |
| 863 | 928 |
| 864 | 929 |
| 865 void FlowGraphCompiler::EmitOptimizedInstanceCall( | 930 void FlowGraphCompiler::EmitOptimizedInstanceCall( |
| 866 ExternalLabel* target_label, | 931 ExternalLabel* target_label, |
| 867 const ICData& ic_data, | 932 const ICData& ic_data, |
| 868 const Array& arguments_descriptor, | 933 const Array& arguments_descriptor, |
| 869 intptr_t argument_count, | 934 intptr_t argument_count, |
| 870 intptr_t deopt_id, | 935 intptr_t deopt_id, |
| 871 intptr_t token_pos, | 936 intptr_t token_pos, |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 925 void FlowGraphCompiler::EmitEqualityRegConstCompare(Register reg, | 990 void FlowGraphCompiler::EmitEqualityRegConstCompare(Register reg, |
| 926 const Object& obj, | 991 const Object& obj, |
| 927 bool needs_number_check) { | 992 bool needs_number_check) { |
| 928 UNIMPLEMENTED(); | 993 UNIMPLEMENTED(); |
| 929 } | 994 } |
| 930 | 995 |
| 931 | 996 |
| 932 void FlowGraphCompiler::EmitEqualityRegRegCompare(Register left, | 997 void FlowGraphCompiler::EmitEqualityRegRegCompare(Register left, |
| 933 Register right, | 998 Register right, |
| 934 bool needs_number_check) { | 999 bool needs_number_check) { |
| 935 UNIMPLEMENTED(); | 1000 if (needs_number_check) { |
| 1001 __ Push(left); |
| 1002 __ Push(right); |
| 1003 __ BranchLink(&StubCode::IdenticalWithNumberCheckLabel()); |
| 1004 // Stub returns result in CMPRES. If it is 0, then left and right are equal. |
| 1005 __ Pop(right); |
| 1006 __ Pop(left); |
| 1007 } else { |
| 1008 __ subu(CMPRES, left, right); |
| 1009 } |
| 936 } | 1010 } |
| 937 | 1011 |
| 938 | 1012 |
| 939 void FlowGraphCompiler::EmitSuperEqualityCallPrologue(Register result, | 1013 void FlowGraphCompiler::EmitSuperEqualityCallPrologue(Register result, |
| 940 Label* skip_call) { | 1014 Label* skip_call) { |
| 941 UNIMPLEMENTED(); | 1015 UNIMPLEMENTED(); |
| 942 } | 1016 } |
| 943 | 1017 |
| 944 | 1018 |
| 945 void FlowGraphCompiler::SaveLiveRegisters(LocationSummary* locs) { | 1019 void FlowGraphCompiler::SaveLiveRegisters(LocationSummary* locs) { |
| (...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1116 | 1190 |
| 1117 | 1191 |
| 1118 void ParallelMoveResolver::RestoreFpuScratch(FpuRegister reg) { | 1192 void ParallelMoveResolver::RestoreFpuScratch(FpuRegister reg) { |
| 1119 UNIMPLEMENTED(); | 1193 UNIMPLEMENTED(); |
| 1120 } | 1194 } |
| 1121 | 1195 |
| 1122 | 1196 |
| 1123 } // namespace dart | 1197 } // namespace dart |
| 1124 | 1198 |
| 1125 #endif // defined TARGET_ARCH_MIPS | 1199 #endif // defined TARGET_ARCH_MIPS |
| OLD | NEW |