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

Side by Side Diff: runtime/vm/flow_graph_compiler_mips.cc

Issue 59613005: Merge (x & y) == 0 pattern to emit a single test instruction. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 1 month 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
OLDNEW
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 "vm/ast_printer.h" 10 #include "vm/ast_printer.h"
(...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after
223 __ Comment("InstantiatedTypeWithArgumentsTest"); 223 __ Comment("InstantiatedTypeWithArgumentsTest");
224 ASSERT(type.IsInstantiated()); 224 ASSERT(type.IsInstantiated());
225 const Class& type_class = Class::ZoneHandle(type.type_class()); 225 const Class& type_class = Class::ZoneHandle(type.type_class());
226 ASSERT((type_class.NumTypeArguments() > 0) || type_class.IsSignatureClass()); 226 ASSERT((type_class.NumTypeArguments() > 0) || type_class.IsSignatureClass());
227 const Register kInstanceReg = A0; 227 const Register kInstanceReg = A0;
228 Error& malformed_error = Error::Handle(); 228 Error& malformed_error = Error::Handle();
229 const Type& int_type = Type::Handle(Type::IntType()); 229 const Type& int_type = Type::Handle(Type::IntType());
230 const bool smi_is_ok = int_type.IsSubtypeOf(type, &malformed_error); 230 const bool smi_is_ok = int_type.IsSubtypeOf(type, &malformed_error);
231 // Malformed type should have been handled at graph construction time. 231 // Malformed type should have been handled at graph construction time.
232 ASSERT(smi_is_ok || malformed_error.IsNull()); 232 ASSERT(smi_is_ok || malformed_error.IsNull());
233 __ andi(CMPRES, kInstanceReg, Immediate(kSmiTagMask)); 233 __ andi(CMPRES1, kInstanceReg, Immediate(kSmiTagMask));
234 if (smi_is_ok) { 234 if (smi_is_ok) {
235 __ beq(CMPRES, ZR, is_instance_lbl); 235 __ beq(CMPRES1, ZR, is_instance_lbl);
236 } else { 236 } else {
237 __ beq(CMPRES, ZR, is_not_instance_lbl); 237 __ beq(CMPRES1, ZR, is_not_instance_lbl);
238 } 238 }
239 const AbstractTypeArguments& type_arguments = 239 const AbstractTypeArguments& type_arguments =
240 AbstractTypeArguments::ZoneHandle(type.arguments()); 240 AbstractTypeArguments::ZoneHandle(type.arguments());
241 const bool is_raw_type = type_arguments.IsNull() || 241 const bool is_raw_type = type_arguments.IsNull() ||
242 type_arguments.IsRaw(type_arguments.Length()); 242 type_arguments.IsRaw(type_arguments.Length());
243 // Signature class is an instantiated parameterized type. 243 // Signature class is an instantiated parameterized type.
244 if (!type_class.IsSignatureClass()) { 244 if (!type_class.IsSignatureClass()) {
245 if (is_raw_type) { 245 if (is_raw_type) {
246 const Register kClassIdReg = T0; 246 const Register kClassIdReg = T0;
247 // dynamic type argument, check only classes. 247 // dynamic type argument, check only classes.
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after
421 FieldAddress(A1, TypeArguments::type_at_offset(type_param.index()))); 421 FieldAddress(A1, TypeArguments::type_at_offset(type_param.index())));
422 // R2: concrete type of type. 422 // R2: concrete type of type.
423 // Check if type argument is dynamic. 423 // Check if type argument is dynamic.
424 __ BranchEqual(T2, Type::ZoneHandle(Type::DynamicType()), is_instance_lbl); 424 __ BranchEqual(T2, Type::ZoneHandle(Type::DynamicType()), is_instance_lbl);
425 __ beq(T2, T7, is_instance_lbl); 425 __ beq(T2, T7, is_instance_lbl);
426 const Type& object_type = Type::ZoneHandle(Type::ObjectType()); 426 const Type& object_type = Type::ZoneHandle(Type::ObjectType());
427 __ BranchEqual(T2, object_type, is_instance_lbl); 427 __ BranchEqual(T2, object_type, is_instance_lbl);
428 428
429 // For Smi check quickly against int and num interfaces. 429 // For Smi check quickly against int and num interfaces.
430 Label not_smi; 430 Label not_smi;
431 __ andi(CMPRES, A0, Immediate(kSmiTagMask)); 431 __ andi(CMPRES1, A0, Immediate(kSmiTagMask));
432 __ bne(CMPRES, ZR, &not_smi); // Value is Smi? 432 __ bne(CMPRES1, ZR, &not_smi); // Value is Smi?
433 __ BranchEqual(T2, Type::ZoneHandle(Type::IntType()), is_instance_lbl); 433 __ BranchEqual(T2, Type::ZoneHandle(Type::IntType()), is_instance_lbl);
434 __ BranchEqual(T2, Type::ZoneHandle(Type::Number()), is_instance_lbl); 434 __ BranchEqual(T2, Type::ZoneHandle(Type::Number()), is_instance_lbl);
435 435
436 // Smi must be handled in runtime. 436 // Smi must be handled in runtime.
437 __ b(&fall_through); 437 __ b(&fall_through);
438 438
439 __ Bind(&not_smi); 439 __ Bind(&not_smi);
440 // T1: instantiator type arguments. 440 // T1: instantiator type arguments.
441 // A0: instance. 441 // A0: instance.
442 const Register kInstanceReg = A0; 442 const Register kInstanceReg = A0;
443 const Register kTypeArgumentsReg = A1; 443 const Register kTypeArgumentsReg = A1;
444 const Register kTempReg = kNoRegister; 444 const Register kTempReg = kNoRegister;
445 const SubtypeTestCache& type_test_cache = 445 const SubtypeTestCache& type_test_cache =
446 SubtypeTestCache::ZoneHandle( 446 SubtypeTestCache::ZoneHandle(
447 GenerateCallSubtypeTestStub(kTestTypeThreeArgs, 447 GenerateCallSubtypeTestStub(kTestTypeThreeArgs,
448 kInstanceReg, 448 kInstanceReg,
449 kTypeArgumentsReg, 449 kTypeArgumentsReg,
450 kTempReg, 450 kTempReg,
451 is_instance_lbl, 451 is_instance_lbl,
452 is_not_instance_lbl)); 452 is_not_instance_lbl));
453 __ Bind(&fall_through); 453 __ Bind(&fall_through);
454 return type_test_cache.raw(); 454 return type_test_cache.raw();
455 } 455 }
456 if (type.IsType()) { 456 if (type.IsType()) {
457 const Register kInstanceReg = A0; 457 const Register kInstanceReg = A0;
458 const Register kTypeArgumentsReg = A1; 458 const Register kTypeArgumentsReg = A1;
459 __ andi(CMPRES, kInstanceReg, Immediate(kSmiTagMask)); 459 __ andi(CMPRES1, kInstanceReg, Immediate(kSmiTagMask));
460 __ beq(CMPRES, ZR, is_not_instance_lbl); // Is instance Smi? 460 __ beq(CMPRES1, ZR, is_not_instance_lbl); // Is instance Smi?
461 __ lw(kTypeArgumentsReg, Address(SP, 0)); // Instantiator type args. 461 __ lw(kTypeArgumentsReg, Address(SP, 0)); // Instantiator type args.
462 // Uninstantiated type class is known at compile time, but the type 462 // Uninstantiated type class is known at compile time, but the type
463 // arguments are determined at runtime by the instantiator. 463 // arguments are determined at runtime by the instantiator.
464 const Register kTempReg = kNoRegister; 464 const Register kTempReg = kNoRegister;
465 return GenerateCallSubtypeTestStub(kTestTypeThreeArgs, 465 return GenerateCallSubtypeTestStub(kTestTypeThreeArgs,
466 kInstanceReg, 466 kInstanceReg,
467 kTypeArgumentsReg, 467 kTypeArgumentsReg,
468 kTempReg, 468 kTempReg,
469 is_instance_lbl, 469 is_instance_lbl,
470 is_not_instance_lbl); 470 is_not_instance_lbl);
(...skipping 19 matching lines...) Expand all
490 __ TraceSimMsg("InlineInstanceof"); 490 __ TraceSimMsg("InlineInstanceof");
491 __ Comment("InlineInstanceof"); 491 __ Comment("InlineInstanceof");
492 if (type.IsVoidType()) { 492 if (type.IsVoidType()) {
493 // A non-null value is returned from a void function, which will result in a 493 // A non-null value is returned from a void function, which will result in a
494 // type error. A null value is handled prior to executing this inline code. 494 // type error. A null value is handled prior to executing this inline code.
495 return SubtypeTestCache::null(); 495 return SubtypeTestCache::null();
496 } 496 }
497 if (TypeCheckAsClassEquality(type)) { 497 if (TypeCheckAsClassEquality(type)) {
498 const intptr_t type_cid = Class::Handle(type.type_class()).id(); 498 const intptr_t type_cid = Class::Handle(type.type_class()).id();
499 const Register kInstanceReg = A0; 499 const Register kInstanceReg = A0;
500 __ andi(CMPRES, kInstanceReg, Immediate(kSmiTagMask)); 500 __ andi(CMPRES1, kInstanceReg, Immediate(kSmiTagMask));
501 if (type_cid == kSmiCid) { 501 if (type_cid == kSmiCid) {
502 __ beq(CMPRES, ZR, is_instance_lbl); 502 __ beq(CMPRES1, ZR, is_instance_lbl);
503 } else { 503 } else {
504 __ beq(CMPRES, ZR, is_not_instance_lbl); 504 __ beq(CMPRES1, ZR, is_not_instance_lbl);
505 __ LoadClassId(T0, kInstanceReg); 505 __ LoadClassId(T0, kInstanceReg);
506 __ BranchEqual(T0, type_cid, is_instance_lbl); 506 __ BranchEqual(T0, type_cid, is_instance_lbl);
507 } 507 }
508 __ b(is_not_instance_lbl); 508 __ b(is_not_instance_lbl);
509 return SubtypeTestCache::null(); 509 return SubtypeTestCache::null();
510 } 510 }
511 if (type.IsInstantiated()) { 511 if (type.IsInstantiated()) {
512 const Class& type_class = Class::ZoneHandle(type.type_class()); 512 const Class& type_class = Class::ZoneHandle(type.type_class());
513 // A class equality check is only applicable with a dst type of a 513 // A class equality check is only applicable with a dst type of a
514 // non-parameterized class, non-signature class, or with a raw dst type of 514 // non-parameterized class, non-signature class, or with a raw dst type of
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after
665 665
666 if (!FLAG_eliminate_type_checks || dst_type.IsMalformed()) { 666 if (!FLAG_eliminate_type_checks || dst_type.IsMalformed()) {
667 // If type checks are not eliminated during the graph building then 667 // If type checks are not eliminated during the graph building then
668 // a transition sentinel can be seen here. 668 // a transition sentinel can be seen here.
669 __ BranchEqual(A0, Object::transition_sentinel(), &is_assignable); 669 __ BranchEqual(A0, Object::transition_sentinel(), &is_assignable);
670 } 670 }
671 671
672 // Generate throw new TypeError() if the type is malformed or malbounded. 672 // Generate throw new TypeError() if the type is malformed or malbounded.
673 if (dst_type.IsMalformed() || dst_type.IsMalbounded()) { 673 if (dst_type.IsMalformed() || dst_type.IsMalbounded()) {
674 __ addiu(SP, SP, Immediate(-4 * kWordSize)); 674 __ addiu(SP, SP, Immediate(-4 * kWordSize));
675 __ LoadObject(TMP1, Object::ZoneHandle()); 675 __ LoadObject(TMP, Object::ZoneHandle());
676 __ sw(TMP1, Address(SP, 3 * kWordSize)); // Make room for the result. 676 __ sw(TMP, Address(SP, 3 * kWordSize)); // Make room for the result.
677 __ sw(A0, Address(SP, 2 * kWordSize)); // Push the source object. 677 __ sw(A0, Address(SP, 2 * kWordSize)); // Push the source object.
678 __ LoadObject(TMP1, dst_name); 678 __ LoadObject(TMP, dst_name);
679 __ sw(TMP1, Address(SP, 1 * kWordSize)); // Push the destination name. 679 __ sw(TMP, Address(SP, 1 * kWordSize)); // Push the destination name.
680 __ LoadObject(TMP1, dst_type); 680 __ LoadObject(TMP, dst_type);
681 __ sw(TMP1, Address(SP, 0 * kWordSize)); // Push the destination type. 681 __ sw(TMP, Address(SP, 0 * kWordSize)); // Push the destination type.
682 682
683 GenerateRuntimeCall(token_pos, 683 GenerateRuntimeCall(token_pos,
684 deopt_id, 684 deopt_id,
685 kBadTypeErrorRuntimeEntry, 685 kBadTypeErrorRuntimeEntry,
686 3, 686 3,
687 locs); 687 locs);
688 // We should never return here. 688 // We should never return here.
689 __ break_(0); 689 __ break_(0);
690 690
691 __ Bind(&is_assignable); // For a null object. 691 __ Bind(&is_assignable); // For a null object.
692 // Restore instantiator and its type arguments. 692 // Restore instantiator and its type arguments.
693 __ lw(A1, Address(SP, 0 * kWordSize)); 693 __ lw(A1, Address(SP, 0 * kWordSize));
694 __ lw(A2, Address(SP, 1 * kWordSize)); 694 __ lw(A2, Address(SP, 1 * kWordSize));
695 __ addiu(SP, SP, Immediate(2 * kWordSize)); 695 __ addiu(SP, SP, Immediate(2 * kWordSize));
696 return; 696 return;
697 } 697 }
698 698
699 // Generate inline type check, linking to runtime call if not assignable. 699 // Generate inline type check, linking to runtime call if not assignable.
700 SubtypeTestCache& test_cache = SubtypeTestCache::ZoneHandle(); 700 SubtypeTestCache& test_cache = SubtypeTestCache::ZoneHandle();
701 test_cache = GenerateInlineInstanceof(token_pos, dst_type, 701 test_cache = GenerateInlineInstanceof(token_pos, dst_type,
702 &is_assignable, &runtime_call); 702 &is_assignable, &runtime_call);
703 703
704 __ Bind(&runtime_call); 704 __ Bind(&runtime_call);
705 // Load instantiator (A2) and its type arguments (A1). 705 // Load instantiator (A2) and its type arguments (A1).
706 __ lw(A1, Address(SP, 0 * kWordSize)); 706 __ lw(A1, Address(SP, 0 * kWordSize));
707 __ lw(A2, Address(SP, 1 * kWordSize)); 707 __ lw(A2, Address(SP, 1 * kWordSize));
708 708
709 __ addiu(SP, SP, Immediate(-7 * kWordSize)); 709 __ addiu(SP, SP, Immediate(-7 * kWordSize));
710 __ LoadObject(TMP1, Object::ZoneHandle()); 710 __ LoadObject(TMP, Object::ZoneHandle());
711 __ sw(TMP1, Address(SP, 6 * kWordSize)); // Make room for the result. 711 __ sw(TMP, Address(SP, 6 * kWordSize)); // Make room for the result.
712 __ sw(A0, Address(SP, 5 * kWordSize)); // Push the source object. 712 __ sw(A0, Address(SP, 5 * kWordSize)); // Push the source object.
713 __ LoadObject(TMP1, dst_type); 713 __ LoadObject(TMP, dst_type);
714 __ sw(TMP1, Address(SP, 4 * kWordSize)); // Push the type of the destination. 714 __ sw(TMP, Address(SP, 4 * kWordSize)); // Push the type of the destination.
715 __ sw(A2, Address(SP, 3 * kWordSize)); // Push instantiator. 715 __ sw(A2, Address(SP, 3 * kWordSize)); // Push instantiator.
716 __ sw(A1, Address(SP, 2 * kWordSize)); // Push type arguments. 716 __ sw(A1, Address(SP, 2 * kWordSize)); // Push type arguments.
717 __ LoadObject(TMP1, dst_name); 717 __ LoadObject(TMP, dst_name);
718 __ sw(TMP1, Address(SP, 1 * kWordSize)); // Push the name of the destination. 718 __ sw(TMP, Address(SP, 1 * kWordSize)); // Push the name of the destination.
719 __ LoadObject(T0, test_cache); 719 __ LoadObject(T0, test_cache);
720 __ sw(T0, Address(SP, 0 * kWordSize)); 720 __ sw(T0, Address(SP, 0 * kWordSize));
721 721
722 GenerateRuntimeCall(token_pos, deopt_id, kTypeCheckRuntimeEntry, 6, locs); 722 GenerateRuntimeCall(token_pos, deopt_id, kTypeCheckRuntimeEntry, 6, locs);
723 // Pop the parameters supplied to the runtime entry. The result of the 723 // Pop the parameters supplied to the runtime entry. The result of the
724 // type check runtime call is the checked value. 724 // type check runtime call is the checked value.
725 __ lw(A0, Address(SP, 6 * kWordSize)); 725 __ lw(A0, Address(SP, 6 * kWordSize));
726 __ addiu(SP, SP, Immediate(7 * kWordSize)); 726 __ addiu(SP, SP, Immediate(7 * kWordSize));
727 727
728 __ Bind(&is_assignable); 728 __ Bind(&is_assignable);
(...skipping 617 matching lines...) Expand 10 before | Expand all | Expand 10 after
1346 MegamorphicCacheTable* table = Isolate::Current()->megamorphic_cache_table(); 1346 MegamorphicCacheTable* table = Isolate::Current()->megamorphic_cache_table();
1347 const String& name = String::Handle(ic_data.target_name()); 1347 const String& name = String::Handle(ic_data.target_name());
1348 const Array& arguments_descriptor = 1348 const Array& arguments_descriptor =
1349 Array::ZoneHandle(ic_data.arguments_descriptor()); 1349 Array::ZoneHandle(ic_data.arguments_descriptor());
1350 ASSERT(!arguments_descriptor.IsNull()); 1350 ASSERT(!arguments_descriptor.IsNull());
1351 const MegamorphicCache& cache = 1351 const MegamorphicCache& cache =
1352 MegamorphicCache::ZoneHandle(table->Lookup(name, arguments_descriptor)); 1352 MegamorphicCache::ZoneHandle(table->Lookup(name, arguments_descriptor));
1353 Label not_smi, load_cache; 1353 Label not_smi, load_cache;
1354 __ TraceSimMsg("MegamorphicInstanceCall"); 1354 __ TraceSimMsg("MegamorphicInstanceCall");
1355 __ lw(T0, Address(SP, (argument_count - 1) * kWordSize)); 1355 __ lw(T0, Address(SP, (argument_count - 1) * kWordSize));
1356 __ andi(CMPRES, T0, Immediate(kSmiTagMask)); 1356 __ andi(CMPRES1, T0, Immediate(kSmiTagMask));
1357 __ bne(CMPRES, ZR, &not_smi); 1357 __ bne(CMPRES1, ZR, &not_smi);
1358 __ LoadImmediate(T0, Smi::RawValue(kSmiCid)); 1358 __ LoadImmediate(T0, Smi::RawValue(kSmiCid));
1359 __ b(&load_cache); 1359 __ b(&load_cache);
1360 1360
1361 __ Bind(&not_smi); 1361 __ Bind(&not_smi);
1362 __ LoadClassId(T0, T0); 1362 __ LoadClassId(T0, T0);
1363 __ SmiTag(T0); 1363 __ SmiTag(T0);
1364 1364
1365 // T0: class ID of the receiver (smi). 1365 // T0: class ID of the receiver (smi).
1366 __ Bind(&load_cache); 1366 __ Bind(&load_cache);
1367 __ LoadObject(T1, cache); 1367 __ LoadObject(T1, cache);
1368 __ lw(T2, FieldAddress(T1, MegamorphicCache::buckets_offset())); 1368 __ lw(T2, FieldAddress(T1, MegamorphicCache::buckets_offset()));
1369 __ lw(T1, FieldAddress(T1, MegamorphicCache::mask_offset())); 1369 __ lw(T1, FieldAddress(T1, MegamorphicCache::mask_offset()));
1370 // T2: cache buckets array. 1370 // T2: cache buckets array.
1371 // T1: mask. 1371 // T1: mask.
1372 __ mov(T3, T0); 1372 __ mov(T3, T0);
1373 1373
1374 Label loop, update, call_target_function; 1374 Label loop, update, call_target_function;
1375 __ b(&loop); 1375 __ b(&loop);
1376 1376
1377 __ Bind(&update); 1377 __ Bind(&update);
1378 __ addiu(T3, T3, Immediate(Smi::RawValue(1))); 1378 __ addiu(T3, T3, Immediate(Smi::RawValue(1)));
1379 __ Bind(&loop); 1379 __ Bind(&loop);
1380 __ and_(T3, T3, T1); 1380 __ and_(T3, T3, T1);
1381 const intptr_t base = Array::data_offset(); 1381 const intptr_t base = Array::data_offset();
1382 // T3 is smi tagged, but table entries are two words, so LSL 2. 1382 // T3 is smi tagged, but table entries are two words, so LSL 2.
1383 __ sll(TMP1, T3, 2); 1383 __ sll(TMP, T3, 2);
1384 __ addu(TMP1, T2, TMP1); 1384 __ addu(TMP, T2, TMP);
1385 __ lw(T4, FieldAddress(TMP, base)); 1385 __ lw(T4, FieldAddress(TMP, base));
1386 1386
1387 ASSERT(kIllegalCid == 0); 1387 ASSERT(kIllegalCid == 0);
1388 __ beq(T4, ZR, &call_target_function); 1388 __ beq(T4, ZR, &call_target_function);
1389 __ bne(T4, T0, &update); 1389 __ bne(T4, T0, &update);
1390 1390
1391 __ Bind(&call_target_function); 1391 __ Bind(&call_target_function);
1392 // Call the target found in the cache. For a class id match, this is a 1392 // Call the target found in the cache. For a class id match, this is a
1393 // proper target for the given name and arguments descriptor. If the 1393 // proper target for the given name and arguments descriptor. If the
1394 // illegal class id was found, the target is a cache miss handler that can 1394 // illegal class id was found, the target is a cache miss handler that can
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
1482 1482
1483 void FlowGraphCompiler::EmitEqualityRegConstCompare(Register reg, 1483 void FlowGraphCompiler::EmitEqualityRegConstCompare(Register reg,
1484 const Object& obj, 1484 const Object& obj,
1485 bool needs_number_check, 1485 bool needs_number_check,
1486 intptr_t token_pos) { 1486 intptr_t token_pos) {
1487 __ TraceSimMsg("EqualityRegConstCompare"); 1487 __ TraceSimMsg("EqualityRegConstCompare");
1488 if (needs_number_check && 1488 if (needs_number_check &&
1489 (obj.IsMint() || obj.IsDouble() || obj.IsBigint())) { 1489 (obj.IsMint() || obj.IsDouble() || obj.IsBigint())) {
1490 __ addiu(SP, SP, Immediate(-2 * kWordSize)); 1490 __ addiu(SP, SP, Immediate(-2 * kWordSize));
1491 __ sw(reg, Address(SP, 1 * kWordSize)); 1491 __ sw(reg, Address(SP, 1 * kWordSize));
1492 __ LoadObject(TMP1, obj); 1492 __ LoadObject(TMP, obj);
1493 __ sw(TMP1, Address(SP, 0 * kWordSize)); 1493 __ sw(TMP, Address(SP, 0 * kWordSize));
1494 if (is_optimizing()) { 1494 if (is_optimizing()) {
1495 __ BranchLinkPatchable( 1495 __ BranchLinkPatchable(
1496 &StubCode::OptimizedIdenticalWithNumberCheckLabel()); 1496 &StubCode::OptimizedIdenticalWithNumberCheckLabel());
1497 } else { 1497 } else {
1498 __ BranchLinkPatchable( 1498 __ BranchLinkPatchable(
1499 &StubCode::UnoptimizedIdenticalWithNumberCheckLabel()); 1499 &StubCode::UnoptimizedIdenticalWithNumberCheckLabel());
1500 } 1500 }
1501 AddCurrentDescriptor(PcDescriptors::kRuntimeCall, 1501 AddCurrentDescriptor(PcDescriptors::kRuntimeCall,
1502 Isolate::kNoDeoptId, 1502 Isolate::kNoDeoptId,
1503 token_pos); 1503 token_pos);
(...skipping 20 matching lines...) Expand all
1524 __ BranchLinkPatchable( 1524 __ BranchLinkPatchable(
1525 &StubCode::OptimizedIdenticalWithNumberCheckLabel()); 1525 &StubCode::OptimizedIdenticalWithNumberCheckLabel());
1526 } else { 1526 } else {
1527 __ BranchLinkPatchable( 1527 __ BranchLinkPatchable(
1528 &StubCode::UnoptimizedIdenticalWithNumberCheckLabel()); 1528 &StubCode::UnoptimizedIdenticalWithNumberCheckLabel());
1529 } 1529 }
1530 AddCurrentDescriptor(PcDescriptors::kRuntimeCall, 1530 AddCurrentDescriptor(PcDescriptors::kRuntimeCall,
1531 Isolate::kNoDeoptId, 1531 Isolate::kNoDeoptId,
1532 token_pos); 1532 token_pos);
1533 __ TraceSimMsg("EqualityRegRegCompare return"); 1533 __ TraceSimMsg("EqualityRegRegCompare return");
1534 // Stub returns result in CMPRES. If it is 0, then left and right are equal. 1534 // Stub returns result in CMPRES1. If it is 0, then left and right are
1535 // equal.
1535 __ lw(right, Address(SP, 0 * kWordSize)); 1536 __ lw(right, Address(SP, 0 * kWordSize));
1536 __ lw(left, Address(SP, 1 * kWordSize)); 1537 __ lw(left, Address(SP, 1 * kWordSize));
1537 __ addiu(SP, SP, Immediate(2 * kWordSize)); 1538 __ addiu(SP, SP, Immediate(2 * kWordSize));
1538 } else { 1539 } else {
1539 __ slt(CMPRES1, left, right); 1540 __ slt(CMPRES1, left, right);
1540 __ slt(CMPRES2, right, left); 1541 __ slt(CMPRES2, right, left);
1541 } 1542 }
1542 } 1543 }
1543 1544
1544 1545
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after
1693 assembler()->LoadImmediate(TMP, 1); 1694 assembler()->LoadImmediate(TMP, 1);
1694 if (true_condition == NE) { 1695 if (true_condition == NE) {
1695 assembler()->movf(CMPRES1, ZR); 1696 assembler()->movf(CMPRES1, ZR);
1696 assembler()->movt(CMPRES1, TMP); 1697 assembler()->movt(CMPRES1, TMP);
1697 } else { 1698 } else {
1698 assembler()->movf(CMPRES1, TMP); 1699 assembler()->movf(CMPRES1, TMP);
1699 assembler()->movt(CMPRES1, ZR); 1700 assembler()->movt(CMPRES1, ZR);
1700 } 1701 }
1701 assembler()->mov(CMPRES2, ZR); 1702 assembler()->mov(CMPRES2, ZR);
1702 1703
1703 // EmitBranchOnCondition expects ordering to be described by CMPRES, CMPRES2. 1704 // EmitBranchOnCondition expects ordering to be described by CMPRES1, CMPRES2.
1704 branch->EmitBranchOnCondition(this, EQ); 1705 branch->EmitBranchOnCondition(this, EQ);
1705 } 1706 }
1706 1707
1707 1708
1708 void FlowGraphCompiler::EmitDoubleCompareBool(Condition true_condition, 1709 void FlowGraphCompiler::EmitDoubleCompareBool(Condition true_condition,
1709 FpuRegister left, 1710 FpuRegister left,
1710 FpuRegister right, 1711 FpuRegister right,
1711 Register result) { 1712 Register result) {
1712 Label done; 1713 Label done;
1713 __ Comment("DoubleCompareBool"); 1714 __ Comment("DoubleCompareBool");
(...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after
1923 } else if (other_move.Blocks(destination)) { 1924 } else if (other_move.Blocks(destination)) {
1924 moves_[i]->set_src(source); 1925 moves_[i]->set_src(source);
1925 } 1926 }
1926 } 1927 }
1927 } 1928 }
1928 1929
1929 1930
1930 void ParallelMoveResolver::MoveMemoryToMemory(const Address& dst, 1931 void ParallelMoveResolver::MoveMemoryToMemory(const Address& dst,
1931 const Address& src) { 1932 const Address& src) {
1932 __ TraceSimMsg("ParallelMoveResolver::MoveMemoryToMemory"); 1933 __ TraceSimMsg("ParallelMoveResolver::MoveMemoryToMemory");
1933 __ lw(TMP1, src); 1934 __ lw(TMP, src);
1934 __ sw(TMP1, dst); 1935 __ sw(TMP, dst);
1935 } 1936 }
1936 1937
1937 1938
1938 void ParallelMoveResolver::StoreObject(const Address& dst, const Object& obj) { 1939 void ParallelMoveResolver::StoreObject(const Address& dst, const Object& obj) {
1939 __ TraceSimMsg("ParallelMoveResolver::StoreObject"); 1940 __ TraceSimMsg("ParallelMoveResolver::StoreObject");
1940 __ LoadObject(TMP1, obj); 1941 __ LoadObject(TMP, obj);
1941 __ sw(TMP1, dst); 1942 __ sw(TMP, dst);
1942 } 1943 }
1943 1944
1944 1945
1945 // Do not call or implement this function. Instead, use the form below that 1946 // Do not call or implement this function. Instead, use the form below that
1946 // uses an offset from the frame pointer instead of an Address. 1947 // uses an offset from the frame pointer instead of an Address.
1947 void ParallelMoveResolver::Exchange(Register reg, const Address& mem) { 1948 void ParallelMoveResolver::Exchange(Register reg, const Address& mem) {
1948 UNREACHABLE(); 1949 UNREACHABLE();
1949 } 1950 }
1950 1951
1951 1952
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
1998 __ AddImmediate(SP, kDoubleSize); 1999 __ AddImmediate(SP, kDoubleSize);
1999 } 2000 }
2000 2001
2001 2002
2002 #undef __ 2003 #undef __
2003 2004
2004 2005
2005 } // namespace dart 2006 } // namespace dart
2006 2007
2007 #endif // defined TARGET_ARCH_MIPS 2008 #endif // defined TARGET_ARCH_MIPS
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698