OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
89 code->set_stack_slots(GetStackSlotCount()); | 89 code->set_stack_slots(GetStackSlotCount()); |
90 code->set_safepoint_table_offset(safepoints_.GetCodeOffset()); | 90 code->set_safepoint_table_offset(safepoints_.GetCodeOffset()); |
91 if (FLAG_weak_embedded_maps_in_optimized_code) { | 91 if (FLAG_weak_embedded_maps_in_optimized_code) { |
92 RegisterDependentCodeForEmbeddedMaps(code); | 92 RegisterDependentCodeForEmbeddedMaps(code); |
93 } | 93 } |
94 PopulateDeoptimizationData(code); | 94 PopulateDeoptimizationData(code); |
95 info()->CommitDependencies(code); | 95 info()->CommitDependencies(code); |
96 } | 96 } |
97 | 97 |
98 | 98 |
99 void LChunkBuilder::Abort(BailoutReason reason) { | 99 void LChunkBuilder::Abort(const char* reason) { |
100 info()->set_bailout_reason(reason); | 100 info()->set_bailout_reason(reason); |
101 status_ = ABORTED; | 101 status_ = ABORTED; |
102 } | 102 } |
103 | 103 |
104 | 104 |
105 void LCodeGen::Comment(const char* format, ...) { | 105 void LCodeGen::Comment(const char* format, ...) { |
106 if (!FLAG_code_comments) return; | 106 if (!FLAG_code_comments) return; |
107 char buffer[4 * KB]; | 107 char buffer[4 * KB]; |
108 StringBuilder builder(buffer, ARRAY_SIZE(buffer)); | 108 StringBuilder builder(buffer, ARRAY_SIZE(buffer)); |
109 va_list arguments; | 109 va_list arguments; |
(...skipping 544 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
654 void LCodeGen::DeoptimizeIf(Condition cc, | 654 void LCodeGen::DeoptimizeIf(Condition cc, |
655 LEnvironment* environment, | 655 LEnvironment* environment, |
656 Deoptimizer::BailoutType bailout_type) { | 656 Deoptimizer::BailoutType bailout_type) { |
657 RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt); | 657 RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt); |
658 ASSERT(environment->HasBeenRegistered()); | 658 ASSERT(environment->HasBeenRegistered()); |
659 int id = environment->deoptimization_index(); | 659 int id = environment->deoptimization_index(); |
660 ASSERT(info()->IsOptimizing() || info()->IsStub()); | 660 ASSERT(info()->IsOptimizing() || info()->IsStub()); |
661 Address entry = | 661 Address entry = |
662 Deoptimizer::GetDeoptimizationEntry(isolate(), id, bailout_type); | 662 Deoptimizer::GetDeoptimizationEntry(isolate(), id, bailout_type); |
663 if (entry == NULL) { | 663 if (entry == NULL) { |
664 Abort(kBailoutWasNotPrepared); | 664 Abort("bailout was not prepared"); |
665 return; | 665 return; |
666 } | 666 } |
667 | 667 |
668 ASSERT(FLAG_deopt_every_n_times == 0); // Not yet implemented on x64. | 668 ASSERT(FLAG_deopt_every_n_times == 0); // Not yet implemented on x64. |
669 | 669 |
670 if (FLAG_trap_on_deopt && info()->IsOptimizing()) { | 670 if (FLAG_trap_on_deopt && info()->IsOptimizing()) { |
671 Label done; | 671 Label done; |
672 if (cc != no_condition) { | 672 if (cc != no_condition) { |
673 __ j(NegateCondition(cc), &done, Label::kNear); | 673 __ j(NegateCondition(cc), &done, Label::kNear); |
674 } | 674 } |
(...skipping 588 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1263 Register left = ToRegister(instr->left()); | 1263 Register left = ToRegister(instr->left()); |
1264 LOperand* right = instr->right(); | 1264 LOperand* right = instr->right(); |
1265 | 1265 |
1266 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1266 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
1267 __ movl(kScratchRegister, left); | 1267 __ movl(kScratchRegister, left); |
1268 } | 1268 } |
1269 | 1269 |
1270 bool can_overflow = | 1270 bool can_overflow = |
1271 instr->hydrogen()->CheckFlag(HValue::kCanOverflow); | 1271 instr->hydrogen()->CheckFlag(HValue::kCanOverflow); |
1272 if (right->IsConstantOperand()) { | 1272 if (right->IsConstantOperand()) { |
1273 int32_t right_value = ToInteger32(LConstantOperand::cast(right)); | 1273 int right_value = ToInteger32(LConstantOperand::cast(right)); |
1274 if (right_value == -1) { | 1274 if (right_value == -1) { |
1275 __ negl(left); | 1275 __ negl(left); |
1276 } else if (right_value == 0) { | 1276 } else if (right_value == 0) { |
1277 __ xorl(left, left); | 1277 __ xorl(left, left); |
1278 } else if (right_value == 2) { | 1278 } else if (right_value == 2) { |
1279 __ addl(left, left); | 1279 __ addl(left, left); |
1280 } else if (!can_overflow) { | 1280 } else if (!can_overflow) { |
1281 // If the multiplication is known to not overflow, we | 1281 // If the multiplication is known to not overflow, we |
1282 // can use operations that don't set the overflow flag | 1282 // can use operations that don't set the overflow flag |
1283 // correctly. | 1283 // correctly. |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1355 } | 1355 } |
1356 | 1356 |
1357 | 1357 |
1358 void LCodeGen::DoBitI(LBitI* instr) { | 1358 void LCodeGen::DoBitI(LBitI* instr) { |
1359 LOperand* left = instr->left(); | 1359 LOperand* left = instr->left(); |
1360 LOperand* right = instr->right(); | 1360 LOperand* right = instr->right(); |
1361 ASSERT(left->Equals(instr->result())); | 1361 ASSERT(left->Equals(instr->result())); |
1362 ASSERT(left->IsRegister()); | 1362 ASSERT(left->IsRegister()); |
1363 | 1363 |
1364 if (right->IsConstantOperand()) { | 1364 if (right->IsConstantOperand()) { |
1365 int32_t right_operand = ToInteger32(LConstantOperand::cast(right)); | 1365 int right_operand = ToInteger32(LConstantOperand::cast(right)); |
1366 switch (instr->op()) { | 1366 switch (instr->op()) { |
1367 case Token::BIT_AND: | 1367 case Token::BIT_AND: |
1368 __ andl(ToRegister(left), Immediate(right_operand)); | 1368 __ andl(ToRegister(left), Immediate(right_operand)); |
1369 break; | 1369 break; |
1370 case Token::BIT_OR: | 1370 case Token::BIT_OR: |
1371 __ orl(ToRegister(left), Immediate(right_operand)); | 1371 __ orl(ToRegister(left), Immediate(right_operand)); |
1372 break; | 1372 break; |
1373 case Token::BIT_XOR: | 1373 case Token::BIT_XOR: |
1374 if (right_operand == int32_t(~0)) { | 1374 __ xorl(ToRegister(left), Immediate(right_operand)); |
1375 __ not_(ToRegister(left)); | |
1376 } else { | |
1377 __ xorl(ToRegister(left), Immediate(right_operand)); | |
1378 } | |
1379 break; | 1375 break; |
1380 default: | 1376 default: |
1381 UNREACHABLE(); | 1377 UNREACHABLE(); |
1382 break; | 1378 break; |
1383 } | 1379 } |
1384 } else if (right->IsStackSlot()) { | 1380 } else if (right->IsStackSlot()) { |
1385 switch (instr->op()) { | 1381 switch (instr->op()) { |
1386 case Token::BIT_AND: | 1382 case Token::BIT_AND: |
1387 __ and_(ToRegister(left), ToOperand(right)); | 1383 __ and_(ToRegister(left), ToOperand(right)); |
1388 break; | 1384 break; |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1439 } | 1435 } |
1440 break; | 1436 break; |
1441 case Token::SHL: | 1437 case Token::SHL: |
1442 __ shll_cl(ToRegister(left)); | 1438 __ shll_cl(ToRegister(left)); |
1443 break; | 1439 break; |
1444 default: | 1440 default: |
1445 UNREACHABLE(); | 1441 UNREACHABLE(); |
1446 break; | 1442 break; |
1447 } | 1443 } |
1448 } else { | 1444 } else { |
1449 int32_t value = ToInteger32(LConstantOperand::cast(right)); | 1445 int value = ToInteger32(LConstantOperand::cast(right)); |
1450 uint8_t shift_count = static_cast<uint8_t>(value & 0x1F); | 1446 uint8_t shift_count = static_cast<uint8_t>(value & 0x1F); |
1451 switch (instr->op()) { | 1447 switch (instr->op()) { |
1452 case Token::ROR: | 1448 case Token::ROR: |
1453 if (shift_count != 0) { | 1449 if (shift_count != 0) { |
1454 __ rorl(ToRegister(left), Immediate(shift_count)); | 1450 __ rorl(ToRegister(left), Immediate(shift_count)); |
1455 } | 1451 } |
1456 break; | 1452 break; |
1457 case Token::SAR: | 1453 case Token::SAR: |
1458 if (shift_count != 0) { | 1454 if (shift_count != 0) { |
1459 __ sarl(ToRegister(left), Immediate(shift_count)); | 1455 __ sarl(ToRegister(left), Immediate(shift_count)); |
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1639 if (FLAG_debug_code) { | 1635 if (FLAG_debug_code) { |
1640 __ push(value); | 1636 __ push(value); |
1641 __ movq(value, FieldOperand(string, HeapObject::kMapOffset)); | 1637 __ movq(value, FieldOperand(string, HeapObject::kMapOffset)); |
1642 __ movzxbq(value, FieldOperand(value, Map::kInstanceTypeOffset)); | 1638 __ movzxbq(value, FieldOperand(value, Map::kInstanceTypeOffset)); |
1643 | 1639 |
1644 __ andb(value, Immediate(kStringRepresentationMask | kStringEncodingMask)); | 1640 __ andb(value, Immediate(kStringRepresentationMask | kStringEncodingMask)); |
1645 static const uint32_t one_byte_seq_type = kSeqStringTag | kOneByteStringTag; | 1641 static const uint32_t one_byte_seq_type = kSeqStringTag | kOneByteStringTag; |
1646 static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag; | 1642 static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag; |
1647 __ cmpq(value, Immediate(encoding == String::ONE_BYTE_ENCODING | 1643 __ cmpq(value, Immediate(encoding == String::ONE_BYTE_ENCODING |
1648 ? one_byte_seq_type : two_byte_seq_type)); | 1644 ? one_byte_seq_type : two_byte_seq_type)); |
1649 __ Check(equal, kUnexpectedStringType); | 1645 __ Check(equal, "Unexpected string type"); |
1650 __ pop(value); | 1646 __ pop(value); |
1651 } | 1647 } |
1652 | 1648 |
1653 if (encoding == String::ONE_BYTE_ENCODING) { | 1649 if (encoding == String::ONE_BYTE_ENCODING) { |
1654 __ movb(FieldOperand(string, index, times_1, SeqString::kHeaderSize), | 1650 __ movb(FieldOperand(string, index, times_1, SeqString::kHeaderSize), |
1655 value); | 1651 value); |
1656 } else { | 1652 } else { |
1657 __ movw(FieldOperand(string, index, times_2, SeqString::kHeaderSize), | 1653 __ movw(FieldOperand(string, index, times_2, SeqString::kHeaderSize), |
1658 value); | 1654 value); |
1659 } | 1655 } |
1660 } | 1656 } |
1661 | 1657 |
1662 | 1658 |
| 1659 void LCodeGen::DoBitNotI(LBitNotI* instr) { |
| 1660 LOperand* input = instr->value(); |
| 1661 ASSERT(input->Equals(instr->result())); |
| 1662 __ not_(ToRegister(input)); |
| 1663 } |
| 1664 |
| 1665 |
1663 void LCodeGen::DoThrow(LThrow* instr) { | 1666 void LCodeGen::DoThrow(LThrow* instr) { |
1664 __ push(ToRegister(instr->value())); | 1667 __ push(ToRegister(instr->value())); |
1665 CallRuntime(Runtime::kThrow, 1, instr); | 1668 CallRuntime(Runtime::kThrow, 1, instr); |
1666 | 1669 |
1667 if (FLAG_debug_code) { | 1670 if (FLAG_debug_code) { |
1668 Comment("Unreachable code."); | 1671 Comment("Unreachable code."); |
1669 __ int3(); | 1672 __ int3(); |
1670 } | 1673 } |
1671 } | 1674 } |
1672 | 1675 |
(...skipping 885 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2558 no_frame_start = masm_->pc_offset(); | 2561 no_frame_start = masm_->pc_offset(); |
2559 } | 2562 } |
2560 if (instr->has_constant_parameter_count()) { | 2563 if (instr->has_constant_parameter_count()) { |
2561 __ Ret((ToInteger32(instr->constant_parameter_count()) + 1) * kPointerSize, | 2564 __ Ret((ToInteger32(instr->constant_parameter_count()) + 1) * kPointerSize, |
2562 rcx); | 2565 rcx); |
2563 } else { | 2566 } else { |
2564 Register reg = ToRegister(instr->parameter_count()); | 2567 Register reg = ToRegister(instr->parameter_count()); |
2565 // The argument count parameter is a smi | 2568 // The argument count parameter is a smi |
2566 __ SmiToInteger32(reg, reg); | 2569 __ SmiToInteger32(reg, reg); |
2567 Register return_addr_reg = reg.is(rcx) ? rbx : rcx; | 2570 Register return_addr_reg = reg.is(rcx) ? rbx : rcx; |
2568 __ PopReturnAddressTo(return_addr_reg); | 2571 __ pop(return_addr_reg); |
2569 __ shl(reg, Immediate(kPointerSizeLog2)); | 2572 __ shl(reg, Immediate(kPointerSizeLog2)); |
2570 __ addq(rsp, reg); | 2573 __ addq(rsp, reg); |
2571 __ jmp(return_addr_reg); | 2574 __ jmp(return_addr_reg); |
2572 } | 2575 } |
2573 if (no_frame_start != -1) { | 2576 if (no_frame_start != -1) { |
2574 info_->AddNoFrameRange(no_frame_start, masm_->pc_offset()); | 2577 info_->AddNoFrameRange(no_frame_start, masm_->pc_offset()); |
2575 } | 2578 } |
2576 } | 2579 } |
2577 | 2580 |
2578 | 2581 |
(...skipping 309 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2888 ExternalPixelArray::kExternalPointerOffset)); | 2891 ExternalPixelArray::kExternalPointerOffset)); |
2889 } | 2892 } |
2890 | 2893 |
2891 | 2894 |
2892 void LCodeGen::DoAccessArgumentsAt(LAccessArgumentsAt* instr) { | 2895 void LCodeGen::DoAccessArgumentsAt(LAccessArgumentsAt* instr) { |
2893 Register arguments = ToRegister(instr->arguments()); | 2896 Register arguments = ToRegister(instr->arguments()); |
2894 Register result = ToRegister(instr->result()); | 2897 Register result = ToRegister(instr->result()); |
2895 | 2898 |
2896 if (instr->length()->IsConstantOperand() && | 2899 if (instr->length()->IsConstantOperand() && |
2897 instr->index()->IsConstantOperand()) { | 2900 instr->index()->IsConstantOperand()) { |
2898 int32_t const_index = ToInteger32(LConstantOperand::cast(instr->index())); | 2901 int const_index = ToInteger32(LConstantOperand::cast(instr->index())); |
2899 int32_t const_length = ToInteger32(LConstantOperand::cast(instr->length())); | 2902 int const_length = ToInteger32(LConstantOperand::cast(instr->length())); |
2900 int index = (const_length - const_index) + 1; | 2903 int index = (const_length - const_index) + 1; |
2901 __ movq(result, Operand(arguments, index * kPointerSize)); | 2904 __ movq(result, Operand(arguments, index * kPointerSize)); |
2902 } else { | 2905 } else { |
2903 Register length = ToRegister(instr->length()); | 2906 Register length = ToRegister(instr->length()); |
2904 // There are two words between the frame pointer and the last argument. | 2907 // There are two words between the frame pointer and the last argument. |
2905 // Subtracting from length accounts for one of them add one more. | 2908 // Subtracting from length accounts for one of them add one more. |
2906 if (instr->index()->IsRegister()) { | 2909 if (instr->index()->IsRegister()) { |
2907 __ subl(length, ToRegister(instr->index())); | 2910 __ subl(length, ToRegister(instr->index())); |
2908 } else { | 2911 } else { |
2909 __ subl(length, ToOperand(instr->index())); | 2912 __ subl(length, ToOperand(instr->index())); |
(...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3076 | 3079 |
3077 Operand LCodeGen::BuildFastArrayOperand( | 3080 Operand LCodeGen::BuildFastArrayOperand( |
3078 LOperand* elements_pointer, | 3081 LOperand* elements_pointer, |
3079 LOperand* key, | 3082 LOperand* key, |
3080 ElementsKind elements_kind, | 3083 ElementsKind elements_kind, |
3081 uint32_t offset, | 3084 uint32_t offset, |
3082 uint32_t additional_index) { | 3085 uint32_t additional_index) { |
3083 Register elements_pointer_reg = ToRegister(elements_pointer); | 3086 Register elements_pointer_reg = ToRegister(elements_pointer); |
3084 int shift_size = ElementsKindToShiftSize(elements_kind); | 3087 int shift_size = ElementsKindToShiftSize(elements_kind); |
3085 if (key->IsConstantOperand()) { | 3088 if (key->IsConstantOperand()) { |
3086 int32_t constant_value = ToInteger32(LConstantOperand::cast(key)); | 3089 int constant_value = ToInteger32(LConstantOperand::cast(key)); |
3087 if (constant_value & 0xF0000000) { | 3090 if (constant_value & 0xF0000000) { |
3088 Abort(kArrayIndexConstantValueTooBig); | 3091 Abort("array index constant value too big"); |
3089 } | 3092 } |
3090 return Operand(elements_pointer_reg, | 3093 return Operand(elements_pointer_reg, |
3091 ((constant_value + additional_index) << shift_size) | 3094 ((constant_value + additional_index) << shift_size) |
3092 + offset); | 3095 + offset); |
3093 } else { | 3096 } else { |
3094 ScaleFactor scale_factor = static_cast<ScaleFactor>(shift_size); | 3097 ScaleFactor scale_factor = static_cast<ScaleFactor>(shift_size); |
3095 return Operand(elements_pointer_reg, | 3098 return Operand(elements_pointer_reg, |
3096 ToRegister(key), | 3099 ToRegister(key), |
3097 scale_factor, | 3100 scale_factor, |
3098 offset + (additional_index << shift_size)); | 3101 offset + (additional_index << shift_size)); |
(...skipping 317 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3416 Register input_reg = ToRegister(instr->value()); | 3419 Register input_reg = ToRegister(instr->value()); |
3417 __ testl(input_reg, input_reg); | 3420 __ testl(input_reg, input_reg); |
3418 Label is_positive; | 3421 Label is_positive; |
3419 __ j(not_sign, &is_positive, Label::kNear); | 3422 __ j(not_sign, &is_positive, Label::kNear); |
3420 __ negl(input_reg); // Sets flags. | 3423 __ negl(input_reg); // Sets flags. |
3421 DeoptimizeIf(negative, instr->environment()); | 3424 DeoptimizeIf(negative, instr->environment()); |
3422 __ bind(&is_positive); | 3425 __ bind(&is_positive); |
3423 } | 3426 } |
3424 | 3427 |
3425 | 3428 |
3426 void LCodeGen::EmitInteger64MathAbs(LMathAbs* instr) { | |
3427 Register input_reg = ToRegister(instr->value()); | |
3428 __ testq(input_reg, input_reg); | |
3429 Label is_positive; | |
3430 __ j(not_sign, &is_positive, Label::kNear); | |
3431 __ neg(input_reg); // Sets flags. | |
3432 DeoptimizeIf(negative, instr->environment()); | |
3433 __ bind(&is_positive); | |
3434 } | |
3435 | |
3436 | |
3437 void LCodeGen::DoMathAbs(LMathAbs* instr) { | 3429 void LCodeGen::DoMathAbs(LMathAbs* instr) { |
3438 // Class for deferred case. | 3430 // Class for deferred case. |
3439 class DeferredMathAbsTaggedHeapNumber: public LDeferredCode { | 3431 class DeferredMathAbsTaggedHeapNumber: public LDeferredCode { |
3440 public: | 3432 public: |
3441 DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen, LMathAbs* instr) | 3433 DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen, LMathAbs* instr) |
3442 : LDeferredCode(codegen), instr_(instr) { } | 3434 : LDeferredCode(codegen), instr_(instr) { } |
3443 virtual void Generate() { | 3435 virtual void Generate() { |
3444 codegen()->DoDeferredMathAbsTaggedHeapNumber(instr_); | 3436 codegen()->DoDeferredMathAbsTaggedHeapNumber(instr_); |
3445 } | 3437 } |
3446 virtual LInstruction* instr() { return instr_; } | 3438 virtual LInstruction* instr() { return instr_; } |
3447 private: | 3439 private: |
3448 LMathAbs* instr_; | 3440 LMathAbs* instr_; |
3449 }; | 3441 }; |
3450 | 3442 |
3451 ASSERT(instr->value()->Equals(instr->result())); | 3443 ASSERT(instr->value()->Equals(instr->result())); |
3452 Representation r = instr->hydrogen()->value()->representation(); | 3444 Representation r = instr->hydrogen()->value()->representation(); |
3453 | 3445 |
3454 if (r.IsDouble()) { | 3446 if (r.IsDouble()) { |
3455 XMMRegister scratch = xmm0; | 3447 XMMRegister scratch = xmm0; |
3456 XMMRegister input_reg = ToDoubleRegister(instr->value()); | 3448 XMMRegister input_reg = ToDoubleRegister(instr->value()); |
3457 __ xorps(scratch, scratch); | 3449 __ xorps(scratch, scratch); |
3458 __ subsd(scratch, input_reg); | 3450 __ subsd(scratch, input_reg); |
3459 __ andpd(input_reg, scratch); | 3451 __ andpd(input_reg, scratch); |
3460 } else if (r.IsInteger32()) { | 3452 } else if (r.IsInteger32()) { |
3461 EmitIntegerMathAbs(instr); | 3453 EmitIntegerMathAbs(instr); |
3462 } else if (r.IsSmi()) { | |
3463 EmitInteger64MathAbs(instr); | |
3464 } else { // Tagged case. | 3454 } else { // Tagged case. |
3465 DeferredMathAbsTaggedHeapNumber* deferred = | 3455 DeferredMathAbsTaggedHeapNumber* deferred = |
3466 new(zone()) DeferredMathAbsTaggedHeapNumber(this, instr); | 3456 new(zone()) DeferredMathAbsTaggedHeapNumber(this, instr); |
3467 Register input_reg = ToRegister(instr->value()); | 3457 Register input_reg = ToRegister(instr->value()); |
3468 // Smi check. | 3458 // Smi check. |
3469 __ JumpIfNotSmi(input_reg, deferred->entry()); | 3459 __ JumpIfNotSmi(input_reg, deferred->entry()); |
3470 __ SmiToInteger32(input_reg, input_reg); | 3460 __ SmiToInteger32(input_reg, input_reg); |
3471 EmitIntegerMathAbs(instr); | 3461 EmitIntegerMathAbs(instr); |
3472 __ Integer32ToSmi(input_reg, input_reg); | 3462 __ Integer32ToSmi(input_reg, input_reg); |
3473 __ bind(deferred->exit()); | 3463 __ bind(deferred->exit()); |
(...skipping 612 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4086 | 4076 |
4087 void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) { | 4077 void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) { |
4088 if (instr->hydrogen()->skip_check()) return; | 4078 if (instr->hydrogen()->skip_check()) return; |
4089 | 4079 |
4090 if (instr->length()->IsRegister()) { | 4080 if (instr->length()->IsRegister()) { |
4091 Register reg = ToRegister(instr->length()); | 4081 Register reg = ToRegister(instr->length()); |
4092 if (!instr->hydrogen()->length()->representation().IsSmi()) { | 4082 if (!instr->hydrogen()->length()->representation().IsSmi()) { |
4093 __ AssertZeroExtended(reg); | 4083 __ AssertZeroExtended(reg); |
4094 } | 4084 } |
4095 if (instr->index()->IsConstantOperand()) { | 4085 if (instr->index()->IsConstantOperand()) { |
4096 int32_t constant_index = | 4086 int constant_index = |
4097 ToInteger32(LConstantOperand::cast(instr->index())); | 4087 ToInteger32(LConstantOperand::cast(instr->index())); |
4098 if (instr->hydrogen()->length()->representation().IsSmi()) { | 4088 if (instr->hydrogen()->length()->representation().IsSmi()) { |
4099 __ Cmp(reg, Smi::FromInt(constant_index)); | 4089 __ Cmp(reg, Smi::FromInt(constant_index)); |
4100 } else { | 4090 } else { |
4101 __ cmpq(reg, Immediate(constant_index)); | 4091 __ cmpq(reg, Immediate(constant_index)); |
4102 } | 4092 } |
4103 } else { | 4093 } else { |
4104 Register reg2 = ToRegister(instr->index()); | 4094 Register reg2 = ToRegister(instr->index()); |
4105 if (!instr->hydrogen()->index()->representation().IsSmi()) { | 4095 if (!instr->hydrogen()->index()->representation().IsSmi()) { |
4106 __ AssertZeroExtended(reg2); | 4096 __ AssertZeroExtended(reg2); |
4107 } | 4097 } |
4108 __ cmpq(reg, reg2); | 4098 __ cmpq(reg, reg2); |
4109 } | 4099 } |
4110 } else { | 4100 } else { |
4111 Operand length = ToOperand(instr->length()); | 4101 Operand length = ToOperand(instr->length()); |
4112 if (instr->index()->IsConstantOperand()) { | 4102 if (instr->index()->IsConstantOperand()) { |
4113 int32_t constant_index = | 4103 int constant_index = |
4114 ToInteger32(LConstantOperand::cast(instr->index())); | 4104 ToInteger32(LConstantOperand::cast(instr->index())); |
4115 if (instr->hydrogen()->length()->representation().IsSmi()) { | 4105 if (instr->hydrogen()->length()->representation().IsSmi()) { |
4116 __ Cmp(length, Smi::FromInt(constant_index)); | 4106 __ Cmp(length, Smi::FromInt(constant_index)); |
4117 } else { | 4107 } else { |
4118 __ cmpq(length, Immediate(constant_index)); | 4108 __ cmpq(length, Immediate(constant_index)); |
4119 } | 4109 } |
4120 } else { | 4110 } else { |
4121 __ cmpq(length, ToRegister(instr->index())); | 4111 __ cmpq(length, ToRegister(instr->index())); |
4122 } | 4112 } |
4123 } | 4113 } |
(...skipping 266 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4390 // result register contain a valid pointer because it is already | 4380 // result register contain a valid pointer because it is already |
4391 // contained in the register pointer map. | 4381 // contained in the register pointer map. |
4392 __ Set(result, 0); | 4382 __ Set(result, 0); |
4393 | 4383 |
4394 PushSafepointRegistersScope scope(this); | 4384 PushSafepointRegistersScope scope(this); |
4395 __ push(string); | 4385 __ push(string); |
4396 // Push the index as a smi. This is safe because of the checks in | 4386 // Push the index as a smi. This is safe because of the checks in |
4397 // DoStringCharCodeAt above. | 4387 // DoStringCharCodeAt above. |
4398 STATIC_ASSERT(String::kMaxLength <= Smi::kMaxValue); | 4388 STATIC_ASSERT(String::kMaxLength <= Smi::kMaxValue); |
4399 if (instr->index()->IsConstantOperand()) { | 4389 if (instr->index()->IsConstantOperand()) { |
4400 int32_t const_index = ToInteger32(LConstantOperand::cast(instr->index())); | 4390 int const_index = ToInteger32(LConstantOperand::cast(instr->index())); |
4401 __ Push(Smi::FromInt(const_index)); | 4391 __ Push(Smi::FromInt(const_index)); |
4402 } else { | 4392 } else { |
4403 Register index = ToRegister(instr->index()); | 4393 Register index = ToRegister(instr->index()); |
4404 __ Integer32ToSmi(index, index); | 4394 __ Integer32ToSmi(index, index); |
4405 __ push(index); | 4395 __ push(index); |
4406 } | 4396 } |
4407 CallRuntimeFromDeferred(Runtime::kStringCharCodeAt, 2, instr); | 4397 CallRuntimeFromDeferred(Runtime::kStringCharCodeAt, 2, instr); |
4408 __ AssertSmi(rax); | 4398 __ AssertSmi(rax); |
4409 __ SmiToInteger32(rax, rax); | 4399 __ SmiToInteger32(rax, rax); |
4410 __ StoreToSafepointRegisterSlot(result, rax); | 4400 __ StoreToSafepointRegisterSlot(result, rax); |
(...skipping 553 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4964 | 4954 |
4965 | 4955 |
4966 void LCodeGen::DoCheckFunction(LCheckFunction* instr) { | 4956 void LCodeGen::DoCheckFunction(LCheckFunction* instr) { |
4967 Register reg = ToRegister(instr->value()); | 4957 Register reg = ToRegister(instr->value()); |
4968 Handle<JSFunction> target = instr->hydrogen()->target(); | 4958 Handle<JSFunction> target = instr->hydrogen()->target(); |
4969 __ CmpHeapObject(reg, target); | 4959 __ CmpHeapObject(reg, target); |
4970 DeoptimizeIf(not_equal, instr->environment()); | 4960 DeoptimizeIf(not_equal, instr->environment()); |
4971 } | 4961 } |
4972 | 4962 |
4973 | 4963 |
4974 void LCodeGen::DoDeferredInstanceMigration(LCheckMaps* instr, Register object) { | 4964 void LCodeGen::DoCheckMapCommon(Register reg, |
4975 { | 4965 Handle<Map> map, |
4976 PushSafepointRegistersScope scope(this); | 4966 LInstruction* instr) { |
4977 __ push(object); | 4967 Label success; |
4978 CallRuntimeFromDeferred(Runtime::kMigrateInstance, 1, instr); | 4968 __ CompareMap(reg, map, &success); |
4979 __ testq(rax, Immediate(kSmiTagMask)); | 4969 DeoptimizeIf(not_equal, instr->environment()); |
4980 } | 4970 __ bind(&success); |
4981 DeoptimizeIf(zero, instr->environment()); | |
4982 } | 4971 } |
4983 | 4972 |
4984 | 4973 |
4985 void LCodeGen::DoCheckMaps(LCheckMaps* instr) { | 4974 void LCodeGen::DoCheckMaps(LCheckMaps* instr) { |
4986 class DeferredCheckMaps: public LDeferredCode { | |
4987 public: | |
4988 DeferredCheckMaps(LCodeGen* codegen, LCheckMaps* instr, Register object) | |
4989 : LDeferredCode(codegen), instr_(instr), object_(object) { | |
4990 SetExit(check_maps()); | |
4991 } | |
4992 virtual void Generate() { | |
4993 codegen()->DoDeferredInstanceMigration(instr_, object_); | |
4994 } | |
4995 Label* check_maps() { return &check_maps_; } | |
4996 virtual LInstruction* instr() { return instr_; } | |
4997 private: | |
4998 LCheckMaps* instr_; | |
4999 Label check_maps_; | |
5000 Register object_; | |
5001 }; | |
5002 | |
5003 if (instr->hydrogen()->CanOmitMapChecks()) return; | 4975 if (instr->hydrogen()->CanOmitMapChecks()) return; |
5004 | |
5005 LOperand* input = instr->value(); | 4976 LOperand* input = instr->value(); |
5006 ASSERT(input->IsRegister()); | 4977 ASSERT(input->IsRegister()); |
5007 Register reg = ToRegister(input); | 4978 Register reg = ToRegister(input); |
5008 | 4979 |
| 4980 Label success; |
5009 SmallMapList* map_set = instr->hydrogen()->map_set(); | 4981 SmallMapList* map_set = instr->hydrogen()->map_set(); |
5010 | |
5011 DeferredCheckMaps* deferred = NULL; | |
5012 if (instr->hydrogen()->has_migration_target()) { | |
5013 deferred = new(zone()) DeferredCheckMaps(this, instr, reg); | |
5014 __ bind(deferred->check_maps()); | |
5015 } | |
5016 | |
5017 Label success; | |
5018 for (int i = 0; i < map_set->length() - 1; i++) { | 4982 for (int i = 0; i < map_set->length() - 1; i++) { |
5019 Handle<Map> map = map_set->at(i); | 4983 Handle<Map> map = map_set->at(i); |
5020 __ CompareMap(reg, map, &success); | 4984 __ CompareMap(reg, map, &success); |
5021 __ j(equal, &success); | 4985 __ j(equal, &success); |
5022 } | 4986 } |
5023 | |
5024 Handle<Map> map = map_set->last(); | 4987 Handle<Map> map = map_set->last(); |
5025 __ CompareMap(reg, map, &success); | 4988 DoCheckMapCommon(reg, map, instr); |
5026 if (instr->hydrogen()->has_migration_target()) { | |
5027 __ j(not_equal, deferred->entry()); | |
5028 } else { | |
5029 DeoptimizeIf(not_equal, instr->environment()); | |
5030 } | |
5031 | |
5032 __ bind(&success); | 4989 __ bind(&success); |
5033 } | 4990 } |
5034 | 4991 |
5035 | 4992 |
5036 void LCodeGen::DoClampDToUint8(LClampDToUint8* instr) { | 4993 void LCodeGen::DoClampDToUint8(LClampDToUint8* instr) { |
5037 XMMRegister value_reg = ToDoubleRegister(instr->unclamped()); | 4994 XMMRegister value_reg = ToDoubleRegister(instr->unclamped()); |
5038 Register result_reg = ToRegister(instr->result()); | 4995 Register result_reg = ToRegister(instr->result()); |
5039 __ ClampDoubleToUint8(value_reg, xmm0, result_reg); | 4996 __ ClampDoubleToUint8(value_reg, xmm0, result_reg); |
5040 } | 4997 } |
5041 | 4998 |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5075 | 5032 |
5076 // smi | 5033 // smi |
5077 __ bind(&is_smi); | 5034 __ bind(&is_smi); |
5078 __ SmiToInteger32(input_reg, input_reg); | 5035 __ SmiToInteger32(input_reg, input_reg); |
5079 __ ClampUint8(input_reg); | 5036 __ ClampUint8(input_reg); |
5080 | 5037 |
5081 __ bind(&done); | 5038 __ bind(&done); |
5082 } | 5039 } |
5083 | 5040 |
5084 | 5041 |
| 5042 void LCodeGen::DoCheckPrototypeMaps(LCheckPrototypeMaps* instr) { |
| 5043 if (instr->hydrogen()->CanOmitPrototypeChecks()) return; |
| 5044 Register reg = ToRegister(instr->temp()); |
| 5045 |
| 5046 ZoneList<Handle<JSObject> >* prototypes = instr->prototypes(); |
| 5047 ZoneList<Handle<Map> >* maps = instr->maps(); |
| 5048 |
| 5049 ASSERT(prototypes->length() == maps->length()); |
| 5050 |
| 5051 for (int i = 0; i < prototypes->length(); i++) { |
| 5052 __ LoadHeapObject(reg, prototypes->at(i)); |
| 5053 DoCheckMapCommon(reg, maps->at(i), instr); |
| 5054 } |
| 5055 } |
| 5056 |
| 5057 |
5085 void LCodeGen::DoAllocate(LAllocate* instr) { | 5058 void LCodeGen::DoAllocate(LAllocate* instr) { |
5086 class DeferredAllocate: public LDeferredCode { | 5059 class DeferredAllocate: public LDeferredCode { |
5087 public: | 5060 public: |
5088 DeferredAllocate(LCodeGen* codegen, LAllocate* instr) | 5061 DeferredAllocate(LCodeGen* codegen, LAllocate* instr) |
5089 : LDeferredCode(codegen), instr_(instr) { } | 5062 : LDeferredCode(codegen), instr_(instr) { } |
5090 virtual void Generate() { codegen()->DoDeferredAllocate(instr_); } | 5063 virtual void Generate() { codegen()->DoDeferredAllocate(instr_); } |
5091 virtual LInstruction* instr() { return instr_; } | 5064 virtual LInstruction* instr() { return instr_; } |
5092 private: | 5065 private: |
5093 LAllocate* instr_; | 5066 LAllocate* instr_; |
5094 }; | 5067 }; |
(...skipping 496 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5591 FixedArray::kHeaderSize - kPointerSize)); | 5564 FixedArray::kHeaderSize - kPointerSize)); |
5592 __ bind(&done); | 5565 __ bind(&done); |
5593 } | 5566 } |
5594 | 5567 |
5595 | 5568 |
5596 #undef __ | 5569 #undef __ |
5597 | 5570 |
5598 } } // namespace v8::internal | 5571 } } // namespace v8::internal |
5599 | 5572 |
5600 #endif // V8_TARGET_ARCH_X64 | 5573 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |