| 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 |