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

Side by Side Diff: src/arm/lithium-codegen-arm.cc

Issue 5976014: Set a fixed scratch register for ARM code generation... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 9 years, 11 months 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
« src/arm/assembler-arm.h ('K') | « src/arm/lithium-codegen-arm.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2010 the V8 project authors. All rights reserved. 1 // Copyright 2010 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 580 matching lines...) Expand 10 before | Expand all | Expand 10 after
591 current_block_ = label->block_id(); 591 current_block_ = label->block_id();
592 LCodeGen::DoGap(label); 592 LCodeGen::DoGap(label);
593 } 593 }
594 594
595 595
596 void LCodeGen::DoParallelMove(LParallelMove* move) { 596 void LCodeGen::DoParallelMove(LParallelMove* move) {
597 // d0 must always be a scratch register. 597 // d0 must always be a scratch register.
598 DoubleRegister dbl_scratch = d0; 598 DoubleRegister dbl_scratch = d0;
599 LUnallocated marker_operand(LUnallocated::NONE); 599 LUnallocated marker_operand(LUnallocated::NONE);
600 600
601 Register core_scratch = r9; 601 Register core_scratch = scratch0();
602 bool destroys_core_scratch = false; 602 bool destroys_core_scratch = false;
603 603
604 LGapResolver resolver(move->move_operands(), &marker_operand); 604 LGapResolver resolver(move->move_operands(), &marker_operand);
605 const ZoneList<LMoveOperands>* moves = resolver.ResolveInReverseOrder(); 605 const ZoneList<LMoveOperands>* moves = resolver.ResolveInReverseOrder();
606 for (int i = moves->length() - 1; i >= 0; --i) { 606 for (int i = moves->length() - 1; i >= 0; --i) {
607 LMoveOperands move = moves->at(i); 607 LMoveOperands move = moves->at(i);
608 LOperand* from = move.from(); 608 LOperand* from = move.from();
609 LOperand* to = move.to(); 609 LOperand* to = move.to();
610 ASSERT(!from->IsDoubleRegister() || 610 ASSERT(!from->IsDoubleRegister() ||
611 !ToDoubleRegister(from).is(dbl_scratch)); 611 !ToDoubleRegister(from).is(dbl_scratch));
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after
743 Abort("DoModI unimplemented."); 743 Abort("DoModI unimplemented.");
744 } 744 }
745 745
746 746
747 void LCodeGen::DoDivI(LDivI* instr) { 747 void LCodeGen::DoDivI(LDivI* instr) {
748 Abort("DoDivI unimplemented."); 748 Abort("DoDivI unimplemented.");
749 } 749 }
750 750
751 751
752 void LCodeGen::DoMulI(LMulI* instr) { 752 void LCodeGen::DoMulI(LMulI* instr) {
753 Register scratch = scratch0();
753 Register left = ToRegister(instr->left()); 754 Register left = ToRegister(instr->left());
754 Register scratch = r9;
755 Register right = EmitLoadRegister(instr->right(), scratch); 755 Register right = EmitLoadRegister(instr->right(), scratch);
756 756
757 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero) && 757 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero) &&
758 !instr->right()->IsConstantOperand()) { 758 !instr->right()->IsConstantOperand()) {
759 __ orr(ToRegister(instr->temp()), left, right); 759 __ orr(ToRegister(instr->temp()), left, right);
760 } 760 }
761 761
762 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { 762 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) {
763 // scratch:left = left * right. 763 // scratch:left = left * right.
764 __ smull(scratch, left, left, right); 764 __ smull(scratch, left, left, right);
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
806 __ eor(result, ToRegister(left), Operand(right_reg)); 806 __ eor(result, ToRegister(left), Operand(right_reg));
807 break; 807 break;
808 default: 808 default:
809 UNREACHABLE(); 809 UNREACHABLE();
810 break; 810 break;
811 } 811 }
812 } 812 }
813 813
814 814
815 void LCodeGen::DoShiftI(LShiftI* instr) { 815 void LCodeGen::DoShiftI(LShiftI* instr) {
816 Register scratch = scratch0();
816 LOperand* left = instr->left(); 817 LOperand* left = instr->left();
817 LOperand* right = instr->right(); 818 LOperand* right = instr->right();
818 ASSERT(left->Equals(instr->result())); 819 ASSERT(left->Equals(instr->result()));
819 ASSERT(left->IsRegister()); 820 ASSERT(left->IsRegister());
820 Register result = ToRegister(left); 821 Register result = ToRegister(left);
821 if (right->IsRegister()) { 822 if (right->IsRegister()) {
822 // Mask the right operand. 823 // Mask the right operand.
823 __ and_(r9, ToRegister(right), Operand(0x1F)); 824 __ and_(scratch, ToRegister(right), Operand(0x1F));
824 switch (instr->op()) { 825 switch (instr->op()) {
825 case Token::SAR: 826 case Token::SAR:
826 __ mov(result, Operand(result, ASR, r9)); 827 __ mov(result, Operand(result, ASR, scratch));
827 break; 828 break;
828 case Token::SHR: 829 case Token::SHR:
829 if (instr->can_deopt()) { 830 if (instr->can_deopt()) {
830 __ mov(result, Operand(result, LSR, r9), SetCC); 831 __ mov(result, Operand(result, LSR, scratch), SetCC);
831 DeoptimizeIf(mi, instr->environment()); 832 DeoptimizeIf(mi, instr->environment());
832 } else { 833 } else {
833 __ mov(result, Operand(result, LSR, r9)); 834 __ mov(result, Operand(result, LSR, scratch));
834 } 835 }
835 break; 836 break;
836 case Token::SHL: 837 case Token::SHL:
837 __ mov(result, Operand(result, LSL, r9)); 838 __ mov(result, Operand(result, LSL, scratch));
838 break; 839 break;
839 default: 840 default:
840 UNREACHABLE(); 841 UNREACHABLE();
841 break; 842 break;
842 } 843 }
843 } else { 844 } else {
844 int value = ToInteger32(LConstantOperand::cast(right)); 845 int value = ToInteger32(LConstantOperand::cast(right));
845 uint8_t shift_count = static_cast<uint8_t>(value & 0x1F); 846 uint8_t shift_count = static_cast<uint8_t>(value & 0x1F);
846 switch (instr->op()) { 847 switch (instr->op()) {
847 case Token::SAR: 848 case Token::SAR:
(...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after
1053 __ cmp(reg, ip); 1054 __ cmp(reg, ip);
1054 __ b(eq, false_label); 1055 __ b(eq, false_label);
1055 __ cmp(reg, Operand(0)); 1056 __ cmp(reg, Operand(0));
1056 __ b(eq, false_label); 1057 __ b(eq, false_label);
1057 __ tst(reg, Operand(kSmiTagMask)); 1058 __ tst(reg, Operand(kSmiTagMask));
1058 __ b(eq, true_label); 1059 __ b(eq, true_label);
1059 1060
1060 // Test for double values. Zero is false. 1061 // Test for double values. Zero is false.
1061 Label call_stub; 1062 Label call_stub;
1062 DoubleRegister dbl_scratch = d0; 1063 DoubleRegister dbl_scratch = d0;
1063 Register core_scratch = r9; 1064 Register scratch = scratch0();
1064 ASSERT(!reg.is(core_scratch)); 1065 __ ldr(scratch, FieldMemOperand(reg, HeapObject::kMapOffset));
1065 __ ldr(core_scratch, FieldMemOperand(reg, HeapObject::kMapOffset));
1066 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex); 1066 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex);
1067 __ cmp(core_scratch, Operand(ip)); 1067 __ cmp(scratch, Operand(ip));
1068 __ b(ne, &call_stub); 1068 __ b(ne, &call_stub);
1069 __ sub(ip, reg, Operand(kHeapObjectTag)); 1069 __ sub(ip, reg, Operand(kHeapObjectTag));
1070 __ vldr(dbl_scratch, ip, HeapNumber::kValueOffset); 1070 __ vldr(dbl_scratch, ip, HeapNumber::kValueOffset);
1071 __ vcmp(dbl_scratch, 0.0); 1071 __ vcmp(dbl_scratch, 0.0);
1072 __ b(eq, false_label); 1072 __ b(eq, false_label);
1073 __ b(true_label); 1073 __ b(true_label);
1074 1074
1075 // The conversion stub doesn't cause garbage collections so it's 1075 // The conversion stub doesn't cause garbage collections so it's
1076 // safe to not record a safepoint after the call. 1076 // safe to not record a safepoint after the call.
1077 __ bind(&call_stub); 1077 __ bind(&call_stub);
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
1169 Abort("DoCmpJSObjectEqAndBranch unimplemented."); 1169 Abort("DoCmpJSObjectEqAndBranch unimplemented.");
1170 } 1170 }
1171 1171
1172 1172
1173 void LCodeGen::DoIsNull(LIsNull* instr) { 1173 void LCodeGen::DoIsNull(LIsNull* instr) {
1174 Abort("DoIsNull unimplemented."); 1174 Abort("DoIsNull unimplemented.");
1175 } 1175 }
1176 1176
1177 1177
1178 void LCodeGen::DoIsNullAndBranch(LIsNullAndBranch* instr) { 1178 void LCodeGen::DoIsNullAndBranch(LIsNullAndBranch* instr) {
1179 Register scratch = scratch0();
1179 Register reg = ToRegister(instr->input()); 1180 Register reg = ToRegister(instr->input());
1180 1181
1181 // TODO(fsc): If the expression is known to be a smi, then it's 1182 // TODO(fsc): If the expression is known to be a smi, then it's
1182 // definitely not null. Jump to the false block. 1183 // definitely not null. Jump to the false block.
1183 1184
1184 int true_block = chunk_->LookupDestination(instr->true_block_id()); 1185 int true_block = chunk_->LookupDestination(instr->true_block_id());
1185 int false_block = chunk_->LookupDestination(instr->false_block_id()); 1186 int false_block = chunk_->LookupDestination(instr->false_block_id());
1186 1187
1187 __ LoadRoot(ip, Heap::kNullValueRootIndex); 1188 __ LoadRoot(ip, Heap::kNullValueRootIndex);
1188 __ cmp(reg, ip); 1189 __ cmp(reg, ip);
1189 if (instr->is_strict()) { 1190 if (instr->is_strict()) {
1190 EmitBranch(true_block, false_block, eq); 1191 EmitBranch(true_block, false_block, eq);
1191 } else { 1192 } else {
1192 Label* true_label = chunk_->GetAssemblyLabel(true_block); 1193 Label* true_label = chunk_->GetAssemblyLabel(true_block);
1193 Label* false_label = chunk_->GetAssemblyLabel(false_block); 1194 Label* false_label = chunk_->GetAssemblyLabel(false_block);
1194 __ b(eq, true_label); 1195 __ b(eq, true_label);
1195 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); 1196 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
1196 __ cmp(reg, ip); 1197 __ cmp(reg, ip);
1197 __ b(eq, true_label); 1198 __ b(eq, true_label);
1198 __ tst(reg, Operand(kSmiTagMask)); 1199 __ tst(reg, Operand(kSmiTagMask));
1199 __ b(eq, false_label); 1200 __ b(eq, false_label);
1200 // Check for undetectable objects by looking in the bit field in 1201 // Check for undetectable objects by looking in the bit field in
1201 // the map. The object has already been smi checked. 1202 // the map. The object has already been smi checked.
1202 Register scratch = ToRegister(instr->temp());
1203 __ ldr(scratch, FieldMemOperand(reg, HeapObject::kMapOffset)); 1203 __ ldr(scratch, FieldMemOperand(reg, HeapObject::kMapOffset));
1204 __ ldrb(scratch, FieldMemOperand(scratch, Map::kBitFieldOffset)); 1204 __ ldrb(scratch, FieldMemOperand(scratch, Map::kBitFieldOffset));
1205 __ tst(scratch, Operand(1 << Map::kIsUndetectable)); 1205 __ tst(scratch, Operand(1 << Map::kIsUndetectable));
1206 EmitBranch(true_block, false_block, ne); 1206 EmitBranch(true_block, false_block, ne);
1207 } 1207 }
1208 } 1208 }
1209 1209
1210 1210
1211 Condition LCodeGen::EmitIsObject(Register input, 1211 Condition LCodeGen::EmitIsObject(Register input,
1212 Register temp1, 1212 Register temp1,
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
1270 return eq; 1270 return eq;
1271 } 1271 }
1272 1272
1273 1273
1274 void LCodeGen::DoHasInstanceType(LHasInstanceType* instr) { 1274 void LCodeGen::DoHasInstanceType(LHasInstanceType* instr) {
1275 Abort("DoHasInstanceType unimplemented."); 1275 Abort("DoHasInstanceType unimplemented.");
1276 } 1276 }
1277 1277
1278 1278
1279 void LCodeGen::DoHasInstanceTypeAndBranch(LHasInstanceTypeAndBranch* instr) { 1279 void LCodeGen::DoHasInstanceTypeAndBranch(LHasInstanceTypeAndBranch* instr) {
1280 Register scratch = scratch0();
1280 Register input = ToRegister(instr->input()); 1281 Register input = ToRegister(instr->input());
1281 Register temp = ToRegister(instr->temp());
1282 1282
1283 int true_block = chunk_->LookupDestination(instr->true_block_id()); 1283 int true_block = chunk_->LookupDestination(instr->true_block_id());
1284 int false_block = chunk_->LookupDestination(instr->false_block_id()); 1284 int false_block = chunk_->LookupDestination(instr->false_block_id());
1285 1285
1286 Label* false_label = chunk_->GetAssemblyLabel(false_block); 1286 Label* false_label = chunk_->GetAssemblyLabel(false_block);
1287 1287
1288 __ tst(input, Operand(kSmiTagMask)); 1288 __ tst(input, Operand(kSmiTagMask));
1289 __ b(eq, false_label); 1289 __ b(eq, false_label);
1290 1290
1291 __ CompareObjectType(input, temp, temp, instr->TestType()); 1291 __ CompareObjectType(input, scratch, scratch, instr->TestType());
1292 EmitBranch(true_block, false_block, instr->BranchCondition()); 1292 EmitBranch(true_block, false_block, instr->BranchCondition());
1293 } 1293 }
1294 1294
1295 1295
1296 void LCodeGen::DoHasCachedArrayIndex(LHasCachedArrayIndex* instr) { 1296 void LCodeGen::DoHasCachedArrayIndex(LHasCachedArrayIndex* instr) {
1297 Abort("DoHasCachedArrayIndex unimplemented."); 1297 Abort("DoHasCachedArrayIndex unimplemented.");
1298 } 1298 }
1299 1299
1300 1300
1301 void LCodeGen::DoHasCachedArrayIndexAndBranch( 1301 void LCodeGen::DoHasCachedArrayIndexAndBranch(
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after
1438 ASSERT(ToRegister(instr->result()).is(r0)); 1438 ASSERT(ToRegister(instr->result()).is(r0));
1439 1439
1440 // Name is always in r2. 1440 // Name is always in r2.
1441 __ mov(r2, Operand(instr->name())); 1441 __ mov(r2, Operand(instr->name()));
1442 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); 1442 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
1443 CallCode(ic, RelocInfo::CODE_TARGET, instr); 1443 CallCode(ic, RelocInfo::CODE_TARGET, instr);
1444 } 1444 }
1445 1445
1446 1446
1447 void LCodeGen::DoLoadFunctionPrototype(LLoadFunctionPrototype* instr) { 1447 void LCodeGen::DoLoadFunctionPrototype(LLoadFunctionPrototype* instr) {
1448 Register scratch = scratch0();
1448 Register function = ToRegister(instr->function()); 1449 Register function = ToRegister(instr->function());
1449 Register temp = ToRegister(instr->temporary());
1450 Register result = ToRegister(instr->result()); 1450 Register result = ToRegister(instr->result());
1451 1451
1452 // Check that the function really is a function. Load map into the 1452 // Check that the function really is a function. Load map into the
1453 // result register. 1453 // result register.
1454 __ CompareObjectType(function, result, temp, JS_FUNCTION_TYPE); 1454 __ CompareObjectType(function, result, scratch, JS_FUNCTION_TYPE);
1455 DeoptimizeIf(ne, instr->environment()); 1455 DeoptimizeIf(ne, instr->environment());
1456 1456
1457 // Make sure that the function has an instance prototype. 1457 // Make sure that the function has an instance prototype.
1458 Label non_instance; 1458 Label non_instance;
1459 __ ldrb(temp, FieldMemOperand(result, Map::kBitFieldOffset)); 1459 __ ldrb(scratch, FieldMemOperand(result, Map::kBitFieldOffset));
1460 __ tst(temp, Operand(1 << Map::kHasNonInstancePrototype)); 1460 __ tst(scratch, Operand(1 << Map::kHasNonInstancePrototype));
1461 __ b(ne, &non_instance); 1461 __ b(ne, &non_instance);
1462 1462
1463 // Get the prototype or initial map from the function. 1463 // Get the prototype or initial map from the function.
1464 __ ldr(result, 1464 __ ldr(result,
1465 FieldMemOperand(function, JSFunction::kPrototypeOrInitialMapOffset)); 1465 FieldMemOperand(function, JSFunction::kPrototypeOrInitialMapOffset));
1466 1466
1467 // Check that the function has a prototype or an initial map. 1467 // Check that the function has a prototype or an initial map.
1468 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); 1468 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
1469 __ cmp(result, ip); 1469 __ cmp(result, ip);
1470 DeoptimizeIf(eq, instr->environment()); 1470 DeoptimizeIf(eq, instr->environment());
1471 1471
1472 // If the function does not have an initial map, we're done. 1472 // If the function does not have an initial map, we're done.
1473 Label done; 1473 Label done;
1474 __ CompareObjectType(result, temp, temp, MAP_TYPE); 1474 __ CompareObjectType(result, scratch, scratch, MAP_TYPE);
1475 __ b(ne, &done); 1475 __ b(ne, &done);
1476 1476
1477 // Get the prototype from the initial map. 1477 // Get the prototype from the initial map.
1478 __ ldr(result, FieldMemOperand(result, Map::kPrototypeOffset)); 1478 __ ldr(result, FieldMemOperand(result, Map::kPrototypeOffset));
1479 __ jmp(&done); 1479 __ jmp(&done);
1480 1480
1481 // Non-instance prototype: Fetch prototype from constructor field 1481 // Non-instance prototype: Fetch prototype from constructor field
1482 // in initial map. 1482 // in initial map.
1483 __ bind(&non_instance); 1483 __ bind(&non_instance);
1484 __ ldr(result, FieldMemOperand(result, Map::kConstructorOffset)); 1484 __ ldr(result, FieldMemOperand(result, Map::kConstructorOffset));
(...skipping 306 matching lines...) Expand 10 before | Expand all | Expand 10 after
1791 class DeferredNumberTagD: public LDeferredCode { 1791 class DeferredNumberTagD: public LDeferredCode {
1792 public: 1792 public:
1793 DeferredNumberTagD(LCodeGen* codegen, LNumberTagD* instr) 1793 DeferredNumberTagD(LCodeGen* codegen, LNumberTagD* instr)
1794 : LDeferredCode(codegen), instr_(instr) { } 1794 : LDeferredCode(codegen), instr_(instr) { }
1795 virtual void Generate() { codegen()->DoDeferredNumberTagD(instr_); } 1795 virtual void Generate() { codegen()->DoDeferredNumberTagD(instr_); }
1796 private: 1796 private:
1797 LNumberTagD* instr_; 1797 LNumberTagD* instr_;
1798 }; 1798 };
1799 1799
1800 DoubleRegister input_reg = ToDoubleRegister(instr->input()); 1800 DoubleRegister input_reg = ToDoubleRegister(instr->input());
1801 Register scratch = scratch0();
1801 Register reg = ToRegister(instr->result()); 1802 Register reg = ToRegister(instr->result());
1802 Register temp1 = ToRegister(instr->temp1()); 1803 Register temp1 = ToRegister(instr->temp1());
1803 Register temp2 = ToRegister(instr->temp2()); 1804 Register temp2 = ToRegister(instr->temp2());
1804 Register scratch = r9;
1805 1805
1806 DeferredNumberTagD* deferred = new DeferredNumberTagD(this, instr); 1806 DeferredNumberTagD* deferred = new DeferredNumberTagD(this, instr);
1807 if (FLAG_inline_new) { 1807 if (FLAG_inline_new) {
1808 __ LoadRoot(scratch, Heap::kHeapNumberMapRootIndex); 1808 __ LoadRoot(scratch, Heap::kHeapNumberMapRootIndex);
1809 __ AllocateHeapNumber(reg, temp1, temp2, scratch, deferred->entry()); 1809 __ AllocateHeapNumber(reg, temp1, temp2, scratch, deferred->entry());
1810 } else { 1810 } else {
1811 __ jmp(deferred->entry()); 1811 __ jmp(deferred->entry());
1812 } 1812 }
1813 __ bind(deferred->exit()); 1813 __ bind(deferred->exit());
1814 __ sub(ip, reg, Operand(kHeapObjectTag)); 1814 __ sub(ip, reg, Operand(kHeapObjectTag));
(...skipping 27 matching lines...) Expand all
1842 1842
1843 1843
1844 void LCodeGen::DoSmiUntag(LSmiUntag* instr) { 1844 void LCodeGen::DoSmiUntag(LSmiUntag* instr) {
1845 Abort("DoSmiUntag unimplemented."); 1845 Abort("DoSmiUntag unimplemented.");
1846 } 1846 }
1847 1847
1848 1848
1849 void LCodeGen::EmitNumberUntagD(Register input_reg, 1849 void LCodeGen::EmitNumberUntagD(Register input_reg,
1850 DoubleRegister result_reg, 1850 DoubleRegister result_reg,
1851 LEnvironment* env) { 1851 LEnvironment* env) {
1852 Register core_scratch = r9; 1852 Register scratch = scratch0();
1853 ASSERT(!input_reg.is(core_scratch));
1854 SwVfpRegister flt_scratch = s0; 1853 SwVfpRegister flt_scratch = s0;
1855 ASSERT(!result_reg.is(d0)); 1854 ASSERT(!result_reg.is(d0));
1856 1855
1857 Label load_smi, heap_number, done; 1856 Label load_smi, heap_number, done;
1858 1857
1859 // Smi check. 1858 // Smi check.
1860 __ tst(input_reg, Operand(kSmiTagMask)); 1859 __ tst(input_reg, Operand(kSmiTagMask));
1861 __ b(eq, &load_smi); 1860 __ b(eq, &load_smi);
1862 1861
1863 // Heap number map check. 1862 // Heap number map check.
1864 __ ldr(core_scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset)); 1863 __ ldr(scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset));
1865 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex); 1864 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex);
1866 __ cmp(core_scratch, Operand(ip)); 1865 __ cmp(scratch, Operand(ip));
1867 __ b(eq, &heap_number); 1866 __ b(eq, &heap_number);
1868 1867
1869 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); 1868 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
1870 __ cmp(input_reg, Operand(ip)); 1869 __ cmp(input_reg, Operand(ip));
1871 DeoptimizeIf(ne, env); 1870 DeoptimizeIf(ne, env);
1872 1871
1873 // Convert undefined to NaN. 1872 // Convert undefined to NaN.
1874 __ LoadRoot(ip, Heap::kNanValueRootIndex); 1873 __ LoadRoot(ip, Heap::kNanValueRootIndex);
1875 __ sub(ip, ip, Operand(kHeapObjectTag)); 1874 __ sub(ip, ip, Operand(kHeapObjectTag));
1876 __ vldr(result_reg, ip, HeapNumber::kValueOffset); 1875 __ vldr(result_reg, ip, HeapNumber::kValueOffset);
(...skipping 21 matching lines...) Expand all
1898 : LDeferredCode(codegen), instr_(instr) { } 1897 : LDeferredCode(codegen), instr_(instr) { }
1899 virtual void Generate() { codegen()->DoDeferredTaggedToI(instr_); } 1898 virtual void Generate() { codegen()->DoDeferredTaggedToI(instr_); }
1900 private: 1899 private:
1901 LTaggedToI* instr_; 1900 LTaggedToI* instr_;
1902 }; 1901 };
1903 1902
1904 1903
1905 void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) { 1904 void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) {
1906 Label done; 1905 Label done;
1907 Register input_reg = ToRegister(instr->input()); 1906 Register input_reg = ToRegister(instr->input());
1908 Register core_scratch = r9; 1907 Register scratch = scratch0();
1909 ASSERT(!input_reg.is(core_scratch));
1910 DoubleRegister dbl_scratch = d0; 1908 DoubleRegister dbl_scratch = d0;
1911 SwVfpRegister flt_scratch = s0; 1909 SwVfpRegister flt_scratch = s0;
1912 DoubleRegister dbl_tmp = ToDoubleRegister(instr->temp()); 1910 DoubleRegister dbl_tmp = ToDoubleRegister(instr->temp());
1913 1911
1914 // Heap number map check. 1912 // Heap number map check.
1915 __ ldr(core_scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset)); 1913 __ ldr(scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset));
1916 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex); 1914 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex);
1917 __ cmp(core_scratch, Operand(ip)); 1915 __ cmp(scratch, Operand(ip));
1918 1916
1919 if (instr->truncating()) { 1917 if (instr->truncating()) {
1920 Label heap_number; 1918 Label heap_number;
1921 __ b(eq, &heap_number); 1919 __ b(eq, &heap_number);
1922 // Check for undefined. Undefined is converted to zero for truncating 1920 // Check for undefined. Undefined is converted to zero for truncating
1923 // conversions. 1921 // conversions.
1924 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); 1922 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
1925 __ cmp(input_reg, Operand(ip)); 1923 __ cmp(input_reg, Operand(ip));
1926 DeoptimizeIf(ne, instr->environment()); 1924 DeoptimizeIf(ne, instr->environment());
1927 __ mov(input_reg, Operand(0)); 1925 __ mov(input_reg, Operand(0));
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
2019 2017
2020 void LCodeGen::DoCheckFunction(LCheckFunction* instr) { 2018 void LCodeGen::DoCheckFunction(LCheckFunction* instr) {
2021 ASSERT(instr->input()->IsRegister()); 2019 ASSERT(instr->input()->IsRegister());
2022 Register reg = ToRegister(instr->input()); 2020 Register reg = ToRegister(instr->input());
2023 __ cmp(reg, Operand(instr->hydrogen()->target())); 2021 __ cmp(reg, Operand(instr->hydrogen()->target()));
2024 DeoptimizeIf(ne, instr->environment()); 2022 DeoptimizeIf(ne, instr->environment());
2025 } 2023 }
2026 2024
2027 2025
2028 void LCodeGen::DoCheckMap(LCheckMap* instr) { 2026 void LCodeGen::DoCheckMap(LCheckMap* instr) {
2027 Register scratch = scratch0();
2029 LOperand* input = instr->input(); 2028 LOperand* input = instr->input();
2030 ASSERT(input->IsRegister()); 2029 ASSERT(input->IsRegister());
2031 Register reg = ToRegister(input); 2030 Register reg = ToRegister(input);
2032 __ ldr(r9, FieldMemOperand(reg, HeapObject::kMapOffset)); 2031 __ ldr(scratch, FieldMemOperand(reg, HeapObject::kMapOffset));
2033 __ cmp(r9, Operand(instr->hydrogen()->map())); 2032 __ cmp(scratch, Operand(instr->hydrogen()->map()));
2034 DeoptimizeIf(ne, instr->environment()); 2033 DeoptimizeIf(ne, instr->environment());
2035 } 2034 }
2036 2035
2037 2036
2038 void LCodeGen::LoadPrototype(Register result, 2037 void LCodeGen::LoadPrototype(Register result,
2039 Handle<JSObject> prototype) { 2038 Handle<JSObject> prototype) {
2040 Abort("LoadPrototype unimplemented."); 2039 Abort("LoadPrototype unimplemented.");
2041 } 2040 }
2042 2041
2043 2042
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
2090 2089
2091 EmitBranch(true_block, false_block, final_branch_condition); 2090 EmitBranch(true_block, false_block, final_branch_condition);
2092 } 2091 }
2093 2092
2094 2093
2095 Condition LCodeGen::EmitTypeofIs(Label* true_label, 2094 Condition LCodeGen::EmitTypeofIs(Label* true_label,
2096 Label* false_label, 2095 Label* false_label,
2097 Register input, 2096 Register input,
2098 Handle<String> type_name) { 2097 Handle<String> type_name) {
2099 Condition final_branch_condition = no_condition; 2098 Condition final_branch_condition = no_condition;
2100 Register core_scratch = r9; 2099 Register scratch = scratch0();
2101 ASSERT(!input.is(core_scratch));
2102 if (type_name->Equals(Heap::number_symbol())) { 2100 if (type_name->Equals(Heap::number_symbol())) {
2103 __ tst(input, Operand(kSmiTagMask)); 2101 __ tst(input, Operand(kSmiTagMask));
2104 __ b(eq, true_label); 2102 __ b(eq, true_label);
2105 __ ldr(input, FieldMemOperand(input, HeapObject::kMapOffset)); 2103 __ ldr(input, FieldMemOperand(input, HeapObject::kMapOffset));
2106 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex); 2104 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex);
2107 __ cmp(input, Operand(ip)); 2105 __ cmp(input, Operand(ip));
2108 final_branch_condition = eq; 2106 final_branch_condition = eq;
2109 2107
2110 } else if (type_name->Equals(Heap::string_symbol())) { 2108 } else if (type_name->Equals(Heap::string_symbol())) {
2111 __ tst(input, Operand(kSmiTagMask)); 2109 __ tst(input, Operand(kSmiTagMask));
2112 __ b(eq, false_label); 2110 __ b(eq, false_label);
2113 __ ldr(input, FieldMemOperand(input, HeapObject::kMapOffset)); 2111 __ ldr(input, FieldMemOperand(input, HeapObject::kMapOffset));
2114 __ ldrb(ip, FieldMemOperand(input, Map::kBitFieldOffset)); 2112 __ ldrb(ip, FieldMemOperand(input, Map::kBitFieldOffset));
2115 __ tst(ip, Operand(1 << Map::kIsUndetectable)); 2113 __ tst(ip, Operand(1 << Map::kIsUndetectable));
2116 __ b(ne, false_label); 2114 __ b(ne, false_label);
2117 __ CompareInstanceType(input, core_scratch, FIRST_NONSTRING_TYPE); 2115 __ CompareInstanceType(input, scratch, FIRST_NONSTRING_TYPE);
2118 final_branch_condition = lo; 2116 final_branch_condition = lo;
2119 2117
2120 } else if (type_name->Equals(Heap::boolean_symbol())) { 2118 } else if (type_name->Equals(Heap::boolean_symbol())) {
2121 __ LoadRoot(ip, Heap::kTrueValueRootIndex); 2119 __ LoadRoot(ip, Heap::kTrueValueRootIndex);
2122 __ cmp(input, ip); 2120 __ cmp(input, ip);
2123 __ b(eq, true_label); 2121 __ b(eq, true_label);
2124 __ LoadRoot(ip, Heap::kFalseValueRootIndex); 2122 __ LoadRoot(ip, Heap::kFalseValueRootIndex);
2125 __ cmp(input, ip); 2123 __ cmp(input, ip);
2126 final_branch_condition = eq; 2124 final_branch_condition = eq;
2127 2125
2128 } else if (type_name->Equals(Heap::undefined_symbol())) { 2126 } else if (type_name->Equals(Heap::undefined_symbol())) {
2129 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); 2127 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
2130 __ cmp(input, ip); 2128 __ cmp(input, ip);
2131 __ b(eq, true_label); 2129 __ b(eq, true_label);
2132 __ tst(input, Operand(kSmiTagMask)); 2130 __ tst(input, Operand(kSmiTagMask));
2133 __ b(eq, false_label); 2131 __ b(eq, false_label);
2134 // Check for undetectable objects => true. 2132 // Check for undetectable objects => true.
2135 __ ldr(input, FieldMemOperand(input, HeapObject::kMapOffset)); 2133 __ ldr(input, FieldMemOperand(input, HeapObject::kMapOffset));
2136 __ ldrb(ip, FieldMemOperand(input, Map::kBitFieldOffset)); 2134 __ ldrb(ip, FieldMemOperand(input, Map::kBitFieldOffset));
2137 __ tst(ip, Operand(1 << Map::kIsUndetectable)); 2135 __ tst(ip, Operand(1 << Map::kIsUndetectable));
2138 final_branch_condition = ne; 2136 final_branch_condition = ne;
2139 2137
2140 } else if (type_name->Equals(Heap::function_symbol())) { 2138 } else if (type_name->Equals(Heap::function_symbol())) {
2141 __ tst(input, Operand(kSmiTagMask)); 2139 __ tst(input, Operand(kSmiTagMask));
2142 __ b(eq, false_label); 2140 __ b(eq, false_label);
2143 __ CompareObjectType(input, input, core_scratch, JS_FUNCTION_TYPE); 2141 __ CompareObjectType(input, input, scratch, JS_FUNCTION_TYPE);
2144 __ b(eq, true_label); 2142 __ b(eq, true_label);
2145 // Regular expressions => 'function' (they are callable). 2143 // Regular expressions => 'function' (they are callable).
2146 __ CompareInstanceType(input, core_scratch, JS_REGEXP_TYPE); 2144 __ CompareInstanceType(input, scratch, JS_REGEXP_TYPE);
2147 final_branch_condition = eq; 2145 final_branch_condition = eq;
2148 2146
2149 } else if (type_name->Equals(Heap::object_symbol())) { 2147 } else if (type_name->Equals(Heap::object_symbol())) {
2150 __ tst(input, Operand(kSmiTagMask)); 2148 __ tst(input, Operand(kSmiTagMask));
2151 __ b(eq, false_label); 2149 __ b(eq, false_label);
2152 __ LoadRoot(ip, Heap::kNullValueRootIndex); 2150 __ LoadRoot(ip, Heap::kNullValueRootIndex);
2153 __ cmp(input, ip); 2151 __ cmp(input, ip);
2154 __ b(eq, true_label); 2152 __ b(eq, true_label);
2155 // Regular expressions => 'function', not 'object'. 2153 // Regular expressions => 'function', not 'object'.
2156 __ CompareObjectType(input, input, core_scratch, JS_REGEXP_TYPE); 2154 __ CompareObjectType(input, input, scratch, JS_REGEXP_TYPE);
2157 __ b(eq, false_label); 2155 __ b(eq, false_label);
2158 // Check for undetectable objects => false. 2156 // Check for undetectable objects => false.
2159 __ ldrb(ip, FieldMemOperand(input, Map::kBitFieldOffset)); 2157 __ ldrb(ip, FieldMemOperand(input, Map::kBitFieldOffset));
2160 __ tst(ip, Operand(1 << Map::kIsUndetectable)); 2158 __ tst(ip, Operand(1 << Map::kIsUndetectable));
2161 __ b(ne, false_label); 2159 __ b(ne, false_label);
2162 // Check for JS objects => true. 2160 // Check for JS objects => true.
2163 __ CompareInstanceType(input, core_scratch, FIRST_JS_OBJECT_TYPE); 2161 __ CompareInstanceType(input, scratch, FIRST_JS_OBJECT_TYPE);
2164 __ b(lo, false_label); 2162 __ b(lo, false_label);
2165 __ CompareInstanceType(input, core_scratch, LAST_JS_OBJECT_TYPE); 2163 __ CompareInstanceType(input, scratch, LAST_JS_OBJECT_TYPE);
2166 final_branch_condition = ls; 2164 final_branch_condition = ls;
2167 2165
2168 } else { 2166 } else {
2169 final_branch_condition = ne; 2167 final_branch_condition = ne;
2170 __ b(false_label); 2168 __ b(false_label);
2171 // A dead branch instruction will be generated after this point. 2169 // A dead branch instruction will be generated after this point.
2172 } 2170 }
2173 2171
2174 return final_branch_condition; 2172 return final_branch_condition;
2175 } 2173 }
(...skipping 28 matching lines...) Expand all
2204 2202
2205 2203
2206 void LCodeGen::DoOsrEntry(LOsrEntry* instr) { 2204 void LCodeGen::DoOsrEntry(LOsrEntry* instr) {
2207 Abort("DoOsrEntry unimplemented."); 2205 Abort("DoOsrEntry unimplemented.");
2208 } 2206 }
2209 2207
2210 2208
2211 #undef __ 2209 #undef __
2212 2210
2213 } } // namespace v8::internal 2211 } } // namespace v8::internal
OLDNEW
« src/arm/assembler-arm.h ('K') | « src/arm/lithium-codegen-arm.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698