OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |