| 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 991 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1002 Register heap_number_map = r8; | 1002 Register heap_number_map = r8; |
| 1003 Register scratch1 = r9; | 1003 Register scratch1 = r9; |
| 1004 Register scratch2 = r10; | 1004 Register scratch2 = r10; |
| 1005 // HeapNumbers containing 32bit integer values are also allowed. | 1005 // HeapNumbers containing 32bit integer values are also allowed. |
| 1006 __ LoadRoot(heap_number_map, Heap::kHeapNumberMapRootIndex); | 1006 __ LoadRoot(heap_number_map, Heap::kHeapNumberMapRootIndex); |
| 1007 __ cmpq(FieldOperand(input, HeapObject::kMapOffset), heap_number_map); | 1007 __ cmpq(FieldOperand(input, HeapObject::kMapOffset), heap_number_map); |
| 1008 __ j(not_equal, fail); | 1008 __ j(not_equal, fail); |
| 1009 __ movsd(xmm0, FieldOperand(input, HeapNumber::kValueOffset)); | 1009 __ movsd(xmm0, FieldOperand(input, HeapNumber::kValueOffset)); |
| 1010 // Convert, convert back, and compare the two doubles' bits. | 1010 // Convert, convert back, and compare the two doubles' bits. |
| 1011 __ cvttsd2siq(scratch2, xmm0); | 1011 __ cvttsd2siq(scratch2, xmm0); |
| 1012 __ cvtlsi2sd(xmm1, scratch2); | 1012 __ Cvtlsi2sd(xmm1, scratch2); |
| 1013 __ movq(scratch1, xmm0); | 1013 __ movq(scratch1, xmm0); |
| 1014 __ movq(scratch2, xmm1); | 1014 __ movq(scratch2, xmm1); |
| 1015 __ cmpq(scratch1, scratch2); | 1015 __ cmpq(scratch1, scratch2); |
| 1016 __ j(not_equal, fail); | 1016 __ j(not_equal, fail); |
| 1017 __ bind(&ok); | 1017 __ bind(&ok); |
| 1018 } | 1018 } |
| 1019 | 1019 |
| 1020 | 1020 |
| 1021 void BinaryOpStub::GenerateNumberStub(MacroAssembler* masm) { | 1021 void BinaryOpStub::GenerateNumberStub(MacroAssembler* masm) { |
| 1022 Label gc_required, not_number; | 1022 Label gc_required, not_number; |
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1138 Label input_not_smi, loaded; | 1138 Label input_not_smi, loaded; |
| 1139 | 1139 |
| 1140 // Test that rax is a number. | 1140 // Test that rax is a number. |
| 1141 StackArgumentsAccessor args(rsp, 1, ARGUMENTS_DONT_CONTAIN_RECEIVER); | 1141 StackArgumentsAccessor args(rsp, 1, ARGUMENTS_DONT_CONTAIN_RECEIVER); |
| 1142 __ movq(rax, args.GetArgumentOperand(0)); | 1142 __ movq(rax, args.GetArgumentOperand(0)); |
| 1143 __ JumpIfNotSmi(rax, &input_not_smi, Label::kNear); | 1143 __ JumpIfNotSmi(rax, &input_not_smi, Label::kNear); |
| 1144 // Input is a smi. Untag and load it onto the FPU stack. | 1144 // Input is a smi. Untag and load it onto the FPU stack. |
| 1145 // Then load the bits of the double into rbx. | 1145 // Then load the bits of the double into rbx. |
| 1146 __ SmiToInteger32(rax, rax); | 1146 __ SmiToInteger32(rax, rax); |
| 1147 __ subq(rsp, Immediate(kDoubleSize)); | 1147 __ subq(rsp, Immediate(kDoubleSize)); |
| 1148 __ cvtlsi2sd(xmm1, rax); | 1148 __ Cvtlsi2sd(xmm1, rax); |
| 1149 __ movsd(Operand(rsp, 0), xmm1); | 1149 __ movsd(Operand(rsp, 0), xmm1); |
| 1150 __ movq(rbx, xmm1); | 1150 __ movq(rbx, xmm1); |
| 1151 __ movq(rdx, xmm1); | 1151 __ movq(rdx, xmm1); |
| 1152 __ fld_d(Operand(rsp, 0)); | 1152 __ fld_d(Operand(rsp, 0)); |
| 1153 __ addq(rsp, Immediate(kDoubleSize)); | 1153 __ addq(rsp, Immediate(kDoubleSize)); |
| 1154 __ jmp(&loaded, Label::kNear); | 1154 __ jmp(&loaded, Label::kNear); |
| 1155 | 1155 |
| 1156 __ bind(&input_not_smi); | 1156 __ bind(&input_not_smi); |
| 1157 // Check if input is a HeapNumber. | 1157 // Check if input is a HeapNumber. |
| 1158 __ LoadRoot(rbx, Heap::kHeapNumberMapRootIndex); | 1158 __ LoadRoot(rbx, Heap::kHeapNumberMapRootIndex); |
| (...skipping 311 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1470 // Get the untagged integer version of the rax heap number in rcx. | 1470 // Get the untagged integer version of the rax heap number in rcx. |
| 1471 __ TruncateHeapNumberToI(rcx, rax); | 1471 __ TruncateHeapNumberToI(rcx, rax); |
| 1472 | 1472 |
| 1473 __ bind(&done); | 1473 __ bind(&done); |
| 1474 __ movl(rax, r8); | 1474 __ movl(rax, r8); |
| 1475 } | 1475 } |
| 1476 | 1476 |
| 1477 | 1477 |
| 1478 void FloatingPointHelper::LoadSSE2SmiOperands(MacroAssembler* masm) { | 1478 void FloatingPointHelper::LoadSSE2SmiOperands(MacroAssembler* masm) { |
| 1479 __ SmiToInteger32(kScratchRegister, rdx); | 1479 __ SmiToInteger32(kScratchRegister, rdx); |
| 1480 __ cvtlsi2sd(xmm0, kScratchRegister); | 1480 __ Cvtlsi2sd(xmm0, kScratchRegister); |
| 1481 __ SmiToInteger32(kScratchRegister, rax); | 1481 __ SmiToInteger32(kScratchRegister, rax); |
| 1482 __ cvtlsi2sd(xmm1, kScratchRegister); | 1482 __ Cvtlsi2sd(xmm1, kScratchRegister); |
| 1483 } | 1483 } |
| 1484 | 1484 |
| 1485 | 1485 |
| 1486 void FloatingPointHelper::LoadSSE2UnknownOperands(MacroAssembler* masm, | 1486 void FloatingPointHelper::LoadSSE2UnknownOperands(MacroAssembler* masm, |
| 1487 Label* not_numbers) { | 1487 Label* not_numbers) { |
| 1488 Label load_smi_rdx, load_nonsmi_rax, load_smi_rax, load_float_rax, done; | 1488 Label load_smi_rdx, load_nonsmi_rax, load_smi_rax, load_float_rax, done; |
| 1489 // Load operand in rdx into xmm0, or branch to not_numbers. | 1489 // Load operand in rdx into xmm0, or branch to not_numbers. |
| 1490 __ LoadRoot(rcx, Heap::kHeapNumberMapRootIndex); | 1490 __ LoadRoot(rcx, Heap::kHeapNumberMapRootIndex); |
| 1491 __ JumpIfSmi(rdx, &load_smi_rdx); | 1491 __ JumpIfSmi(rdx, &load_smi_rdx); |
| 1492 __ cmpq(FieldOperand(rdx, HeapObject::kMapOffset), rcx); | 1492 __ cmpq(FieldOperand(rdx, HeapObject::kMapOffset), rcx); |
| 1493 __ j(not_equal, not_numbers); // Argument in rdx is not a number. | 1493 __ j(not_equal, not_numbers); // Argument in rdx is not a number. |
| 1494 __ movsd(xmm0, FieldOperand(rdx, HeapNumber::kValueOffset)); | 1494 __ movsd(xmm0, FieldOperand(rdx, HeapNumber::kValueOffset)); |
| 1495 // Load operand in rax into xmm1, or branch to not_numbers. | 1495 // Load operand in rax into xmm1, or branch to not_numbers. |
| 1496 __ JumpIfSmi(rax, &load_smi_rax); | 1496 __ JumpIfSmi(rax, &load_smi_rax); |
| 1497 | 1497 |
| 1498 __ bind(&load_nonsmi_rax); | 1498 __ bind(&load_nonsmi_rax); |
| 1499 __ cmpq(FieldOperand(rax, HeapObject::kMapOffset), rcx); | 1499 __ cmpq(FieldOperand(rax, HeapObject::kMapOffset), rcx); |
| 1500 __ j(not_equal, not_numbers); | 1500 __ j(not_equal, not_numbers); |
| 1501 __ movsd(xmm1, FieldOperand(rax, HeapNumber::kValueOffset)); | 1501 __ movsd(xmm1, FieldOperand(rax, HeapNumber::kValueOffset)); |
| 1502 __ jmp(&done); | 1502 __ jmp(&done); |
| 1503 | 1503 |
| 1504 __ bind(&load_smi_rdx); | 1504 __ bind(&load_smi_rdx); |
| 1505 __ SmiToInteger32(kScratchRegister, rdx); | 1505 __ SmiToInteger32(kScratchRegister, rdx); |
| 1506 __ cvtlsi2sd(xmm0, kScratchRegister); | 1506 __ Cvtlsi2sd(xmm0, kScratchRegister); |
| 1507 __ JumpIfNotSmi(rax, &load_nonsmi_rax); | 1507 __ JumpIfNotSmi(rax, &load_nonsmi_rax); |
| 1508 | 1508 |
| 1509 __ bind(&load_smi_rax); | 1509 __ bind(&load_smi_rax); |
| 1510 __ SmiToInteger32(kScratchRegister, rax); | 1510 __ SmiToInteger32(kScratchRegister, rax); |
| 1511 __ cvtlsi2sd(xmm1, kScratchRegister); | 1511 __ Cvtlsi2sd(xmm1, kScratchRegister); |
| 1512 __ bind(&done); | 1512 __ bind(&done); |
| 1513 } | 1513 } |
| 1514 | 1514 |
| 1515 | 1515 |
| 1516 void FloatingPointHelper::NumbersToSmis(MacroAssembler* masm, | 1516 void FloatingPointHelper::NumbersToSmis(MacroAssembler* masm, |
| 1517 Register first, | 1517 Register first, |
| 1518 Register second, | 1518 Register second, |
| 1519 Register scratch1, | 1519 Register scratch1, |
| 1520 Register scratch2, | 1520 Register scratch2, |
| 1521 Register scratch3, | 1521 Register scratch3, |
| (...skipping 12 matching lines...) Expand all Loading... |
| 1534 __ j(not_equal, | 1534 __ j(not_equal, |
| 1535 (convert_undefined == CONVERT_UNDEFINED_TO_ZERO) | 1535 (convert_undefined == CONVERT_UNDEFINED_TO_ZERO) |
| 1536 ? &maybe_undefined_first | 1536 ? &maybe_undefined_first |
| 1537 : on_not_smis); | 1537 : on_not_smis); |
| 1538 // Convert HeapNumber to smi if possible. | 1538 // Convert HeapNumber to smi if possible. |
| 1539 __ movsd(xmm0, FieldOperand(first, HeapNumber::kValueOffset)); | 1539 __ movsd(xmm0, FieldOperand(first, HeapNumber::kValueOffset)); |
| 1540 __ movq(scratch2, xmm0); | 1540 __ movq(scratch2, xmm0); |
| 1541 __ cvttsd2siq(smi_result, xmm0); | 1541 __ cvttsd2siq(smi_result, xmm0); |
| 1542 // Check if conversion was successful by converting back and | 1542 // Check if conversion was successful by converting back and |
| 1543 // comparing to the original double's bits. | 1543 // comparing to the original double's bits. |
| 1544 __ cvtlsi2sd(xmm1, smi_result); | 1544 __ Cvtlsi2sd(xmm1, smi_result); |
| 1545 __ movq(kScratchRegister, xmm1); | 1545 __ movq(kScratchRegister, xmm1); |
| 1546 __ cmpq(scratch2, kScratchRegister); | 1546 __ cmpq(scratch2, kScratchRegister); |
| 1547 __ j(not_equal, on_not_smis); | 1547 __ j(not_equal, on_not_smis); |
| 1548 __ Integer32ToSmi(first, smi_result); | 1548 __ Integer32ToSmi(first, smi_result); |
| 1549 | 1549 |
| 1550 __ bind(&first_done); | 1550 __ bind(&first_done); |
| 1551 __ JumpIfSmi(second, (on_success != NULL) ? on_success : &done); | 1551 __ JumpIfSmi(second, (on_success != NULL) ? on_success : &done); |
| 1552 __ bind(&first_smi); | 1552 __ bind(&first_smi); |
| 1553 __ AssertNotSmi(second); | 1553 __ AssertNotSmi(second); |
| 1554 __ cmpq(FieldOperand(second, HeapObject::kMapOffset), heap_number_map); | 1554 __ cmpq(FieldOperand(second, HeapObject::kMapOffset), heap_number_map); |
| 1555 __ j(not_equal, | 1555 __ j(not_equal, |
| 1556 (convert_undefined == CONVERT_UNDEFINED_TO_ZERO) | 1556 (convert_undefined == CONVERT_UNDEFINED_TO_ZERO) |
| 1557 ? &maybe_undefined_second | 1557 ? &maybe_undefined_second |
| 1558 : on_not_smis); | 1558 : on_not_smis); |
| 1559 // Convert second to smi, if possible. | 1559 // Convert second to smi, if possible. |
| 1560 __ movsd(xmm0, FieldOperand(second, HeapNumber::kValueOffset)); | 1560 __ movsd(xmm0, FieldOperand(second, HeapNumber::kValueOffset)); |
| 1561 __ movq(scratch2, xmm0); | 1561 __ movq(scratch2, xmm0); |
| 1562 __ cvttsd2siq(smi_result, xmm0); | 1562 __ cvttsd2siq(smi_result, xmm0); |
| 1563 __ cvtlsi2sd(xmm1, smi_result); | 1563 __ Cvtlsi2sd(xmm1, smi_result); |
| 1564 __ movq(kScratchRegister, xmm1); | 1564 __ movq(kScratchRegister, xmm1); |
| 1565 __ cmpq(scratch2, kScratchRegister); | 1565 __ cmpq(scratch2, kScratchRegister); |
| 1566 __ j(not_equal, on_not_smis); | 1566 __ j(not_equal, on_not_smis); |
| 1567 __ Integer32ToSmi(second, smi_result); | 1567 __ Integer32ToSmi(second, smi_result); |
| 1568 if (on_success != NULL) { | 1568 if (on_success != NULL) { |
| 1569 __ jmp(on_success); | 1569 __ jmp(on_success); |
| 1570 } else { | 1570 } else { |
| 1571 __ jmp(&done); | 1571 __ jmp(&done); |
| 1572 } | 1572 } |
| 1573 | 1573 |
| (...skipping 22 matching lines...) Expand all Loading... |
| 1596 const Register scratch = rcx; | 1596 const Register scratch = rcx; |
| 1597 const XMMRegister double_result = xmm3; | 1597 const XMMRegister double_result = xmm3; |
| 1598 const XMMRegister double_base = xmm2; | 1598 const XMMRegister double_base = xmm2; |
| 1599 const XMMRegister double_exponent = xmm1; | 1599 const XMMRegister double_exponent = xmm1; |
| 1600 const XMMRegister double_scratch = xmm4; | 1600 const XMMRegister double_scratch = xmm4; |
| 1601 | 1601 |
| 1602 Label call_runtime, done, exponent_not_smi, int_exponent; | 1602 Label call_runtime, done, exponent_not_smi, int_exponent; |
| 1603 | 1603 |
| 1604 // Save 1 in double_result - we need this several times later on. | 1604 // Save 1 in double_result - we need this several times later on. |
| 1605 __ movq(scratch, Immediate(1)); | 1605 __ movq(scratch, Immediate(1)); |
| 1606 __ cvtlsi2sd(double_result, scratch); | 1606 __ Cvtlsi2sd(double_result, scratch); |
| 1607 | 1607 |
| 1608 if (exponent_type_ == ON_STACK) { | 1608 if (exponent_type_ == ON_STACK) { |
| 1609 Label base_is_smi, unpack_exponent; | 1609 Label base_is_smi, unpack_exponent; |
| 1610 // The exponent and base are supplied as arguments on the stack. | 1610 // The exponent and base are supplied as arguments on the stack. |
| 1611 // This can only happen if the stub is called from non-optimized code. | 1611 // This can only happen if the stub is called from non-optimized code. |
| 1612 // Load input parameters from stack. | 1612 // Load input parameters from stack. |
| 1613 StackArgumentsAccessor args(rsp, 2, ARGUMENTS_DONT_CONTAIN_RECEIVER); | 1613 StackArgumentsAccessor args(rsp, 2, ARGUMENTS_DONT_CONTAIN_RECEIVER); |
| 1614 __ movq(base, args.GetArgumentOperand(0)); | 1614 __ movq(base, args.GetArgumentOperand(0)); |
| 1615 __ movq(exponent, args.GetArgumentOperand(1)); | 1615 __ movq(exponent, args.GetArgumentOperand(1)); |
| 1616 __ JumpIfSmi(base, &base_is_smi, Label::kNear); | 1616 __ JumpIfSmi(base, &base_is_smi, Label::kNear); |
| 1617 __ CompareRoot(FieldOperand(base, HeapObject::kMapOffset), | 1617 __ CompareRoot(FieldOperand(base, HeapObject::kMapOffset), |
| 1618 Heap::kHeapNumberMapRootIndex); | 1618 Heap::kHeapNumberMapRootIndex); |
| 1619 __ j(not_equal, &call_runtime); | 1619 __ j(not_equal, &call_runtime); |
| 1620 | 1620 |
| 1621 __ movsd(double_base, FieldOperand(base, HeapNumber::kValueOffset)); | 1621 __ movsd(double_base, FieldOperand(base, HeapNumber::kValueOffset)); |
| 1622 __ jmp(&unpack_exponent, Label::kNear); | 1622 __ jmp(&unpack_exponent, Label::kNear); |
| 1623 | 1623 |
| 1624 __ bind(&base_is_smi); | 1624 __ bind(&base_is_smi); |
| 1625 __ SmiToInteger32(base, base); | 1625 __ SmiToInteger32(base, base); |
| 1626 __ cvtlsi2sd(double_base, base); | 1626 __ Cvtlsi2sd(double_base, base); |
| 1627 __ bind(&unpack_exponent); | 1627 __ bind(&unpack_exponent); |
| 1628 | 1628 |
| 1629 __ JumpIfNotSmi(exponent, &exponent_not_smi, Label::kNear); | 1629 __ JumpIfNotSmi(exponent, &exponent_not_smi, Label::kNear); |
| 1630 __ SmiToInteger32(exponent, exponent); | 1630 __ SmiToInteger32(exponent, exponent); |
| 1631 __ jmp(&int_exponent); | 1631 __ jmp(&int_exponent); |
| 1632 | 1632 |
| 1633 __ bind(&exponent_not_smi); | 1633 __ bind(&exponent_not_smi); |
| 1634 __ CompareRoot(FieldOperand(exponent, HeapObject::kMapOffset), | 1634 __ CompareRoot(FieldOperand(exponent, HeapObject::kMapOffset), |
| 1635 Heap::kHeapNumberMapRootIndex); | 1635 Heap::kHeapNumberMapRootIndex); |
| 1636 __ j(not_equal, &call_runtime); | 1636 __ j(not_equal, &call_runtime); |
| (...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1805 __ divsd(double_scratch2, double_result); | 1805 __ divsd(double_scratch2, double_result); |
| 1806 __ movsd(double_result, double_scratch2); | 1806 __ movsd(double_result, double_scratch2); |
| 1807 // Test whether result is zero. Bail out to check for subnormal result. | 1807 // Test whether result is zero. Bail out to check for subnormal result. |
| 1808 // Due to subnormals, x^-y == (1/x)^y does not hold in all cases. | 1808 // Due to subnormals, x^-y == (1/x)^y does not hold in all cases. |
| 1809 __ xorps(double_scratch2, double_scratch2); | 1809 __ xorps(double_scratch2, double_scratch2); |
| 1810 __ ucomisd(double_scratch2, double_result); | 1810 __ ucomisd(double_scratch2, double_result); |
| 1811 // double_exponent aliased as double_scratch2 has already been overwritten | 1811 // double_exponent aliased as double_scratch2 has already been overwritten |
| 1812 // and may not have contained the exponent value in the first place when the | 1812 // and may not have contained the exponent value in the first place when the |
| 1813 // input was a smi. We reset it with exponent value before bailing out. | 1813 // input was a smi. We reset it with exponent value before bailing out. |
| 1814 __ j(not_equal, &done); | 1814 __ j(not_equal, &done); |
| 1815 __ cvtlsi2sd(double_exponent, exponent); | 1815 __ Cvtlsi2sd(double_exponent, exponent); |
| 1816 | 1816 |
| 1817 // Returning or bailing out. | 1817 // Returning or bailing out. |
| 1818 Counters* counters = masm->isolate()->counters(); | 1818 Counters* counters = masm->isolate()->counters(); |
| 1819 if (exponent_type_ == ON_STACK) { | 1819 if (exponent_type_ == ON_STACK) { |
| 1820 // The arguments are still on the stack. | 1820 // The arguments are still on the stack. |
| 1821 __ bind(&call_runtime); | 1821 __ bind(&call_runtime); |
| 1822 __ TailCallRuntime(Runtime::kMath_pow_cfunction, 2, 1); | 1822 __ TailCallRuntime(Runtime::kMath_pow_cfunction, 2, 1); |
| 1823 | 1823 |
| 1824 // The stub is called from non-optimized code, which expects the result | 1824 // The stub is called from non-optimized code, which expects the result |
| 1825 // as heap number in rax. | 1825 // as heap number in rax. |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1895 } else { | 1895 } else { |
| 1896 ASSERT(kind() == Code::LOAD_IC); | 1896 ASSERT(kind() == Code::LOAD_IC); |
| 1897 // ----------- S t a t e ------------- | 1897 // ----------- S t a t e ------------- |
| 1898 // -- rax : receiver | 1898 // -- rax : receiver |
| 1899 // -- rcx : name | 1899 // -- rcx : name |
| 1900 // -- rsp[0] : return address | 1900 // -- rsp[0] : return address |
| 1901 // ----------------------------------- | 1901 // ----------------------------------- |
| 1902 receiver = rax; | 1902 receiver = rax; |
| 1903 } | 1903 } |
| 1904 | 1904 |
| 1905 StubCompiler::GenerateLoadStringLength(masm, receiver, r8, r9, &miss, | 1905 StubCompiler::GenerateLoadStringLength(masm, receiver, r8, r9, &miss); |
| 1906 support_wrapper_); | |
| 1907 __ bind(&miss); | 1906 __ bind(&miss); |
| 1908 StubCompiler::TailCallBuiltin( | 1907 StubCompiler::TailCallBuiltin( |
| 1909 masm, BaseLoadStoreStubCompiler::MissBuiltin(kind())); | 1908 masm, BaseLoadStoreStubCompiler::MissBuiltin(kind())); |
| 1910 } | 1909 } |
| 1911 | 1910 |
| 1912 | 1911 |
| 1913 void StoreArrayLengthStub::Generate(MacroAssembler* masm) { | 1912 void StoreArrayLengthStub::Generate(MacroAssembler* masm) { |
| 1914 // ----------- S t a t e ------------- | 1913 // ----------- S t a t e ------------- |
| 1915 // -- rax : value | 1914 // -- rax : value |
| 1916 // -- rcx : key | 1915 // -- rcx : key |
| (...skipping 1695 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3612 // Check stack alignment. | 3611 // Check stack alignment. |
| 3613 if (FLAG_debug_code) { | 3612 if (FLAG_debug_code) { |
| 3614 __ CheckStackAlignment(); | 3613 __ CheckStackAlignment(); |
| 3615 } | 3614 } |
| 3616 | 3615 |
| 3617 if (do_gc) { | 3616 if (do_gc) { |
| 3618 // Pass failure code returned from last attempt as first argument to | 3617 // Pass failure code returned from last attempt as first argument to |
| 3619 // PerformGC. No need to use PrepareCallCFunction/CallCFunction here as the | 3618 // PerformGC. No need to use PrepareCallCFunction/CallCFunction here as the |
| 3620 // stack is known to be aligned. This function takes one argument which is | 3619 // stack is known to be aligned. This function takes one argument which is |
| 3621 // passed in register. | 3620 // passed in register. |
| 3621 __ movq(arg_reg_2, ExternalReference::isolate_address(masm->isolate())); |
| 3622 __ movq(arg_reg_1, rax); | 3622 __ movq(arg_reg_1, rax); |
| 3623 __ movq(kScratchRegister, | 3623 __ movq(kScratchRegister, |
| 3624 ExternalReference::perform_gc_function(masm->isolate())); | 3624 ExternalReference::perform_gc_function(masm->isolate())); |
| 3625 __ call(kScratchRegister); | 3625 __ call(kScratchRegister); |
| 3626 } | 3626 } |
| 3627 | 3627 |
| 3628 ExternalReference scope_depth = | 3628 ExternalReference scope_depth = |
| 3629 ExternalReference::heap_always_allocate_scope_depth(masm->isolate()); | 3629 ExternalReference::heap_always_allocate_scope_depth(masm->isolate()); |
| 3630 if (always_allocate_scope) { | 3630 if (always_allocate_scope) { |
| 3631 Operand scope_depth_operand = masm->ExternalOperand(scope_depth); | 3631 Operand scope_depth_operand = masm->ExternalOperand(scope_depth); |
| (...skipping 1005 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4637 Register scratch2, | 4637 Register scratch2, |
| 4638 Register scratch3, | 4638 Register scratch3, |
| 4639 Label* slow) { | 4639 Label* slow) { |
| 4640 // First check if the argument is already a string. | 4640 // First check if the argument is already a string. |
| 4641 Label not_string, done; | 4641 Label not_string, done; |
| 4642 __ JumpIfSmi(arg, ¬_string); | 4642 __ JumpIfSmi(arg, ¬_string); |
| 4643 __ CmpObjectType(arg, FIRST_NONSTRING_TYPE, scratch1); | 4643 __ CmpObjectType(arg, FIRST_NONSTRING_TYPE, scratch1); |
| 4644 __ j(below, &done); | 4644 __ j(below, &done); |
| 4645 | 4645 |
| 4646 // Check the number to string cache. | 4646 // Check the number to string cache. |
| 4647 Label not_cached; | |
| 4648 __ bind(¬_string); | 4647 __ bind(¬_string); |
| 4649 // Puts the cached result into scratch1. | 4648 // Puts the cached result into scratch1. |
| 4650 NumberToStringStub::GenerateLookupNumberStringCache(masm, | 4649 NumberToStringStub::GenerateLookupNumberStringCache(masm, |
| 4651 arg, | 4650 arg, |
| 4652 scratch1, | 4651 scratch1, |
| 4653 scratch2, | 4652 scratch2, |
| 4654 scratch3, | 4653 scratch3, |
| 4655 ¬_cached); | 4654 slow); |
| 4656 __ movq(arg, scratch1); | 4655 __ movq(arg, scratch1); |
| 4657 __ movq(Operand(rsp, stack_offset), arg); | 4656 __ movq(Operand(rsp, stack_offset), arg); |
| 4658 __ jmp(&done); | |
| 4659 | |
| 4660 // Check if the argument is a safe string wrapper. | |
| 4661 __ bind(¬_cached); | |
| 4662 __ JumpIfSmi(arg, slow); | |
| 4663 __ CmpObjectType(arg, JS_VALUE_TYPE, scratch1); // map -> scratch1. | |
| 4664 __ j(not_equal, slow); | |
| 4665 __ testb(FieldOperand(scratch1, Map::kBitField2Offset), | |
| 4666 Immediate(1 << Map::kStringWrapperSafeForDefaultValueOf)); | |
| 4667 __ j(zero, slow); | |
| 4668 __ movq(arg, FieldOperand(arg, JSValue::kValueOffset)); | |
| 4669 __ movq(Operand(rsp, stack_offset), arg); | |
| 4670 | |
| 4671 __ bind(&done); | 4657 __ bind(&done); |
| 4672 } | 4658 } |
| 4673 | 4659 |
| 4674 | 4660 |
| 4675 void StringHelper::GenerateCopyCharacters(MacroAssembler* masm, | 4661 void StringHelper::GenerateCopyCharacters(MacroAssembler* masm, |
| 4676 Register dest, | 4662 Register dest, |
| 4677 Register src, | 4663 Register src, |
| 4678 Register count, | 4664 Register count, |
| 4679 bool ascii) { | 4665 bool ascii) { |
| 4680 Label loop; | 4666 Label loop; |
| (...skipping 702 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5383 | 5369 |
| 5384 // Load left and right operand. | 5370 // Load left and right operand. |
| 5385 Label done, left, left_smi, right_smi; | 5371 Label done, left, left_smi, right_smi; |
| 5386 __ JumpIfSmi(rax, &right_smi, Label::kNear); | 5372 __ JumpIfSmi(rax, &right_smi, Label::kNear); |
| 5387 __ CompareMap(rax, masm->isolate()->factory()->heap_number_map(), NULL); | 5373 __ CompareMap(rax, masm->isolate()->factory()->heap_number_map(), NULL); |
| 5388 __ j(not_equal, &maybe_undefined1, Label::kNear); | 5374 __ j(not_equal, &maybe_undefined1, Label::kNear); |
| 5389 __ movsd(xmm1, FieldOperand(rax, HeapNumber::kValueOffset)); | 5375 __ movsd(xmm1, FieldOperand(rax, HeapNumber::kValueOffset)); |
| 5390 __ jmp(&left, Label::kNear); | 5376 __ jmp(&left, Label::kNear); |
| 5391 __ bind(&right_smi); | 5377 __ bind(&right_smi); |
| 5392 __ SmiToInteger32(rcx, rax); // Can't clobber rax yet. | 5378 __ SmiToInteger32(rcx, rax); // Can't clobber rax yet. |
| 5393 __ cvtlsi2sd(xmm1, rcx); | 5379 __ Cvtlsi2sd(xmm1, rcx); |
| 5394 | 5380 |
| 5395 __ bind(&left); | 5381 __ bind(&left); |
| 5396 __ JumpIfSmi(rdx, &left_smi, Label::kNear); | 5382 __ JumpIfSmi(rdx, &left_smi, Label::kNear); |
| 5397 __ CompareMap(rdx, masm->isolate()->factory()->heap_number_map(), NULL); | 5383 __ CompareMap(rdx, masm->isolate()->factory()->heap_number_map(), NULL); |
| 5398 __ j(not_equal, &maybe_undefined2, Label::kNear); | 5384 __ j(not_equal, &maybe_undefined2, Label::kNear); |
| 5399 __ movsd(xmm0, FieldOperand(rdx, HeapNumber::kValueOffset)); | 5385 __ movsd(xmm0, FieldOperand(rdx, HeapNumber::kValueOffset)); |
| 5400 __ jmp(&done); | 5386 __ jmp(&done); |
| 5401 __ bind(&left_smi); | 5387 __ bind(&left_smi); |
| 5402 __ SmiToInteger32(rcx, rdx); // Can't clobber rdx yet. | 5388 __ SmiToInteger32(rcx, rdx); // Can't clobber rdx yet. |
| 5403 __ cvtlsi2sd(xmm0, rcx); | 5389 __ Cvtlsi2sd(xmm0, rcx); |
| 5404 | 5390 |
| 5405 __ bind(&done); | 5391 __ bind(&done); |
| 5406 // Compare operands | 5392 // Compare operands |
| 5407 __ ucomisd(xmm0, xmm1); | 5393 __ ucomisd(xmm0, xmm1); |
| 5408 | 5394 |
| 5409 // Don't base result on EFLAGS when a NaN is involved. | 5395 // Don't base result on EFLAGS when a NaN is involved. |
| 5410 __ j(parity_even, &unordered, Label::kNear); | 5396 __ j(parity_even, &unordered, Label::kNear); |
| 5411 | 5397 |
| 5412 // Return a result of -1, 0, or 1, based on EFLAGS. | 5398 // Return a result of -1, 0, or 1, based on EFLAGS. |
| 5413 // Performing mov, because xor would destroy the flag register. | 5399 // Performing mov, because xor would destroy the flag register. |
| (...skipping 905 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6319 // Restore volatile regs. | 6305 // Restore volatile regs. |
| 6320 masm->PopCallerSaved(kSaveFPRegs, arg_reg_1, arg_reg_2); | 6306 masm->PopCallerSaved(kSaveFPRegs, arg_reg_1, arg_reg_2); |
| 6321 __ pop(arg_reg_2); | 6307 __ pop(arg_reg_2); |
| 6322 __ pop(arg_reg_1); | 6308 __ pop(arg_reg_1); |
| 6323 | 6309 |
| 6324 __ Ret(); | 6310 __ Ret(); |
| 6325 } | 6311 } |
| 6326 | 6312 |
| 6327 | 6313 |
| 6328 template<class T> | 6314 template<class T> |
| 6329 static void CreateArrayDispatch(MacroAssembler* masm) { | 6315 static void CreateArrayDispatch(MacroAssembler* masm, |
| 6330 int last_index = GetSequenceIndexFromFastElementsKind( | 6316 AllocationSiteOverrideMode mode) { |
| 6331 TERMINAL_FAST_ELEMENTS_KIND); | 6317 if (mode == DISABLE_ALLOCATION_SITES) { |
| 6332 for (int i = 0; i <= last_index; ++i) { | 6318 T stub(GetInitialFastElementsKind(), |
| 6333 Label next; | 6319 CONTEXT_CHECK_REQUIRED, |
| 6334 ElementsKind kind = GetFastElementsKindFromSequenceIndex(i); | 6320 mode); |
| 6335 __ cmpl(rdx, Immediate(kind)); | |
| 6336 __ j(not_equal, &next); | |
| 6337 T stub(kind); | |
| 6338 __ TailCallStub(&stub); | 6321 __ TailCallStub(&stub); |
| 6339 __ bind(&next); | 6322 } else if (mode == DONT_OVERRIDE) { |
| 6323 int last_index = GetSequenceIndexFromFastElementsKind( |
| 6324 TERMINAL_FAST_ELEMENTS_KIND); |
| 6325 for (int i = 0; i <= last_index; ++i) { |
| 6326 Label next; |
| 6327 ElementsKind kind = GetFastElementsKindFromSequenceIndex(i); |
| 6328 __ cmpl(rdx, Immediate(kind)); |
| 6329 __ j(not_equal, &next); |
| 6330 T stub(kind); |
| 6331 __ TailCallStub(&stub); |
| 6332 __ bind(&next); |
| 6333 } |
| 6334 |
| 6335 // If we reached this point there is a problem. |
| 6336 __ Abort(kUnexpectedElementsKindInArrayConstructor); |
| 6337 } else { |
| 6338 UNREACHABLE(); |
| 6340 } | 6339 } |
| 6341 | |
| 6342 // If we reached this point there is a problem. | |
| 6343 __ Abort(kUnexpectedElementsKindInArrayConstructor); | |
| 6344 } | 6340 } |
| 6345 | 6341 |
| 6346 | 6342 |
| 6347 static void CreateArrayDispatchOneArgument(MacroAssembler* masm) { | 6343 static void CreateArrayDispatchOneArgument(MacroAssembler* masm, |
| 6348 // rbx - type info cell | 6344 AllocationSiteOverrideMode mode) { |
| 6349 // rdx - kind | 6345 // rbx - type info cell (if mode != DISABLE_ALLOCATION_SITES) |
| 6346 // rdx - kind (if mode != DISABLE_ALLOCATION_SITES) |
| 6350 // rax - number of arguments | 6347 // rax - number of arguments |
| 6351 // rdi - constructor? | 6348 // rdi - constructor? |
| 6352 // rsp[0] - return address | 6349 // rsp[0] - return address |
| 6353 // rsp[8] - last argument | 6350 // rsp[8] - last argument |
| 6354 ASSERT(FAST_SMI_ELEMENTS == 0); | |
| 6355 ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1); | |
| 6356 ASSERT(FAST_ELEMENTS == 2); | |
| 6357 ASSERT(FAST_HOLEY_ELEMENTS == 3); | |
| 6358 ASSERT(FAST_DOUBLE_ELEMENTS == 4); | |
| 6359 ASSERT(FAST_HOLEY_DOUBLE_ELEMENTS == 5); | |
| 6360 | |
| 6361 Handle<Object> undefined_sentinel( | 6351 Handle<Object> undefined_sentinel( |
| 6362 masm->isolate()->heap()->undefined_value(), | 6352 masm->isolate()->heap()->undefined_value(), |
| 6363 masm->isolate()); | 6353 masm->isolate()); |
| 6364 | 6354 |
| 6365 // is the low bit set? If so, we are holey and that is good. | |
| 6366 __ testb(rdx, Immediate(1)); | |
| 6367 Label normal_sequence; | 6355 Label normal_sequence; |
| 6368 __ j(not_zero, &normal_sequence); | 6356 if (mode == DONT_OVERRIDE) { |
| 6357 ASSERT(FAST_SMI_ELEMENTS == 0); |
| 6358 ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1); |
| 6359 ASSERT(FAST_ELEMENTS == 2); |
| 6360 ASSERT(FAST_HOLEY_ELEMENTS == 3); |
| 6361 ASSERT(FAST_DOUBLE_ELEMENTS == 4); |
| 6362 ASSERT(FAST_HOLEY_DOUBLE_ELEMENTS == 5); |
| 6363 |
| 6364 // is the low bit set? If so, we are holey and that is good. |
| 6365 __ testb(rdx, Immediate(1)); |
| 6366 __ j(not_zero, &normal_sequence); |
| 6367 } |
| 6369 | 6368 |
| 6370 // look at the first argument | 6369 // look at the first argument |
| 6371 StackArgumentsAccessor args(rsp, 1, ARGUMENTS_DONT_CONTAIN_RECEIVER); | 6370 StackArgumentsAccessor args(rsp, 1, ARGUMENTS_DONT_CONTAIN_RECEIVER); |
| 6372 __ movq(rcx, args.GetArgumentOperand(0)); | 6371 __ movq(rcx, args.GetArgumentOperand(0)); |
| 6373 __ testq(rcx, rcx); | 6372 __ testq(rcx, rcx); |
| 6374 __ j(zero, &normal_sequence); | 6373 __ j(zero, &normal_sequence); |
| 6375 | 6374 |
| 6376 // We are going to create a holey array, but our kind is non-holey. | 6375 if (mode == DISABLE_ALLOCATION_SITES) { |
| 6377 // Fix kind and retry (only if we have an allocation site in the cell). | 6376 ElementsKind initial = GetInitialFastElementsKind(); |
| 6378 __ incl(rdx); | 6377 ElementsKind holey_initial = GetHoleyElementsKind(initial); |
| 6379 __ Cmp(rbx, undefined_sentinel); | |
| 6380 __ j(equal, &normal_sequence); | |
| 6381 __ movq(rcx, FieldOperand(rbx, Cell::kValueOffset)); | |
| 6382 Handle<Map> allocation_site_map( | |
| 6383 masm->isolate()->heap()->allocation_site_map(), | |
| 6384 masm->isolate()); | |
| 6385 __ Cmp(FieldOperand(rcx, 0), allocation_site_map); | |
| 6386 __ j(not_equal, &normal_sequence); | |
| 6387 | 6378 |
| 6388 // Save the resulting elements kind in type info | 6379 ArraySingleArgumentConstructorStub stub_holey(holey_initial, |
| 6389 __ Integer32ToSmi(rdx, rdx); | 6380 CONTEXT_CHECK_REQUIRED, |
| 6390 __ movq(FieldOperand(rcx, AllocationSite::kTransitionInfoOffset), rdx); | 6381 DISABLE_ALLOCATION_SITES); |
| 6391 __ SmiToInteger32(rdx, rdx); | 6382 __ TailCallStub(&stub_holey); |
| 6392 | 6383 |
| 6393 __ bind(&normal_sequence); | 6384 __ bind(&normal_sequence); |
| 6394 int last_index = GetSequenceIndexFromFastElementsKind( | 6385 ArraySingleArgumentConstructorStub stub(initial, |
| 6395 TERMINAL_FAST_ELEMENTS_KIND); | 6386 CONTEXT_CHECK_REQUIRED, |
| 6396 for (int i = 0; i <= last_index; ++i) { | 6387 DISABLE_ALLOCATION_SITES); |
| 6397 Label next; | |
| 6398 ElementsKind kind = GetFastElementsKindFromSequenceIndex(i); | |
| 6399 __ cmpl(rdx, Immediate(kind)); | |
| 6400 __ j(not_equal, &next); | |
| 6401 ArraySingleArgumentConstructorStub stub(kind); | |
| 6402 __ TailCallStub(&stub); | 6388 __ TailCallStub(&stub); |
| 6403 __ bind(&next); | 6389 } else if (mode == DONT_OVERRIDE) { |
| 6390 // We are going to create a holey array, but our kind is non-holey. |
| 6391 // Fix kind and retry (only if we have an allocation site in the cell). |
| 6392 __ incl(rdx); |
| 6393 __ movq(rcx, FieldOperand(rbx, Cell::kValueOffset)); |
| 6394 if (FLAG_debug_code) { |
| 6395 Handle<Map> allocation_site_map( |
| 6396 masm->isolate()->heap()->allocation_site_map(), |
| 6397 masm->isolate()); |
| 6398 __ Cmp(FieldOperand(rcx, 0), allocation_site_map); |
| 6399 __ Assert(equal, kExpectedAllocationSiteInCell); |
| 6400 } |
| 6401 |
| 6402 // Save the resulting elements kind in type info |
| 6403 __ Integer32ToSmi(rdx, rdx); |
| 6404 __ movq(FieldOperand(rcx, AllocationSite::kTransitionInfoOffset), rdx); |
| 6405 __ SmiToInteger32(rdx, rdx); |
| 6406 |
| 6407 __ bind(&normal_sequence); |
| 6408 int last_index = GetSequenceIndexFromFastElementsKind( |
| 6409 TERMINAL_FAST_ELEMENTS_KIND); |
| 6410 for (int i = 0; i <= last_index; ++i) { |
| 6411 Label next; |
| 6412 ElementsKind kind = GetFastElementsKindFromSequenceIndex(i); |
| 6413 __ cmpl(rdx, Immediate(kind)); |
| 6414 __ j(not_equal, &next); |
| 6415 ArraySingleArgumentConstructorStub stub(kind); |
| 6416 __ TailCallStub(&stub); |
| 6417 __ bind(&next); |
| 6418 } |
| 6419 |
| 6420 // If we reached this point there is a problem. |
| 6421 __ Abort(kUnexpectedElementsKindInArrayConstructor); |
| 6422 } else { |
| 6423 UNREACHABLE(); |
| 6404 } | 6424 } |
| 6405 | |
| 6406 // If we reached this point there is a problem. | |
| 6407 __ Abort(kUnexpectedElementsKindInArrayConstructor); | |
| 6408 } | 6425 } |
| 6409 | 6426 |
| 6410 | 6427 |
| 6411 template<class T> | 6428 template<class T> |
| 6412 static void ArrayConstructorStubAheadOfTimeHelper(Isolate* isolate) { | 6429 static void ArrayConstructorStubAheadOfTimeHelper(Isolate* isolate) { |
| 6430 ElementsKind initial_kind = GetInitialFastElementsKind(); |
| 6431 ElementsKind initial_holey_kind = GetHoleyElementsKind(initial_kind); |
| 6432 |
| 6413 int to_index = GetSequenceIndexFromFastElementsKind( | 6433 int to_index = GetSequenceIndexFromFastElementsKind( |
| 6414 TERMINAL_FAST_ELEMENTS_KIND); | 6434 TERMINAL_FAST_ELEMENTS_KIND); |
| 6415 for (int i = 0; i <= to_index; ++i) { | 6435 for (int i = 0; i <= to_index; ++i) { |
| 6416 ElementsKind kind = GetFastElementsKindFromSequenceIndex(i); | 6436 ElementsKind kind = GetFastElementsKindFromSequenceIndex(i); |
| 6417 T stub(kind); | 6437 T stub(kind); |
| 6418 stub.GetCode(isolate)->set_is_pregenerated(true); | 6438 stub.GetCode(isolate)->set_is_pregenerated(true); |
| 6419 if (AllocationSite::GetMode(kind) != DONT_TRACK_ALLOCATION_SITE) { | 6439 if (AllocationSite::GetMode(kind) != DONT_TRACK_ALLOCATION_SITE || |
| 6440 (!FLAG_track_allocation_sites && |
| 6441 (kind == initial_kind || kind == initial_holey_kind))) { |
| 6420 T stub1(kind, CONTEXT_CHECK_REQUIRED, DISABLE_ALLOCATION_SITES); | 6442 T stub1(kind, CONTEXT_CHECK_REQUIRED, DISABLE_ALLOCATION_SITES); |
| 6421 stub1.GetCode(isolate)->set_is_pregenerated(true); | 6443 stub1.GetCode(isolate)->set_is_pregenerated(true); |
| 6422 } | 6444 } |
| 6423 } | 6445 } |
| 6424 } | 6446 } |
| 6425 | 6447 |
| 6426 | 6448 |
| 6427 void ArrayConstructorStubBase::GenerateStubsAheadOfTime(Isolate* isolate) { | 6449 void ArrayConstructorStubBase::GenerateStubsAheadOfTime(Isolate* isolate) { |
| 6428 ArrayConstructorStubAheadOfTimeHelper<ArrayNoArgumentConstructorStub>( | 6450 ArrayConstructorStubAheadOfTimeHelper<ArrayNoArgumentConstructorStub>( |
| 6429 isolate); | 6451 isolate); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 6442 InternalArrayNoArgumentConstructorStub stubh1(kinds[i]); | 6464 InternalArrayNoArgumentConstructorStub stubh1(kinds[i]); |
| 6443 stubh1.GetCode(isolate)->set_is_pregenerated(true); | 6465 stubh1.GetCode(isolate)->set_is_pregenerated(true); |
| 6444 InternalArraySingleArgumentConstructorStub stubh2(kinds[i]); | 6466 InternalArraySingleArgumentConstructorStub stubh2(kinds[i]); |
| 6445 stubh2.GetCode(isolate)->set_is_pregenerated(true); | 6467 stubh2.GetCode(isolate)->set_is_pregenerated(true); |
| 6446 InternalArrayNArgumentsConstructorStub stubh3(kinds[i]); | 6468 InternalArrayNArgumentsConstructorStub stubh3(kinds[i]); |
| 6447 stubh3.GetCode(isolate)->set_is_pregenerated(true); | 6469 stubh3.GetCode(isolate)->set_is_pregenerated(true); |
| 6448 } | 6470 } |
| 6449 } | 6471 } |
| 6450 | 6472 |
| 6451 | 6473 |
| 6474 void ArrayConstructorStub::GenerateDispatchToArrayStub( |
| 6475 MacroAssembler* masm, |
| 6476 AllocationSiteOverrideMode mode) { |
| 6477 if (argument_count_ == ANY) { |
| 6478 Label not_zero_case, not_one_case; |
| 6479 __ testq(rax, rax); |
| 6480 __ j(not_zero, ¬_zero_case); |
| 6481 CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm, mode); |
| 6482 |
| 6483 __ bind(¬_zero_case); |
| 6484 __ cmpl(rax, Immediate(1)); |
| 6485 __ j(greater, ¬_one_case); |
| 6486 CreateArrayDispatchOneArgument(masm, mode); |
| 6487 |
| 6488 __ bind(¬_one_case); |
| 6489 CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm, mode); |
| 6490 } else if (argument_count_ == NONE) { |
| 6491 CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm, mode); |
| 6492 } else if (argument_count_ == ONE) { |
| 6493 CreateArrayDispatchOneArgument(masm, mode); |
| 6494 } else if (argument_count_ == MORE_THAN_ONE) { |
| 6495 CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm, mode); |
| 6496 } else { |
| 6497 UNREACHABLE(); |
| 6498 } |
| 6499 } |
| 6500 |
| 6501 |
| 6452 void ArrayConstructorStub::Generate(MacroAssembler* masm) { | 6502 void ArrayConstructorStub::Generate(MacroAssembler* masm) { |
| 6453 // ----------- S t a t e ------------- | 6503 // ----------- S t a t e ------------- |
| 6454 // -- rax : argc | 6504 // -- rax : argc |
| 6455 // -- rbx : type info cell | 6505 // -- rbx : type info cell |
| 6456 // -- rdi : constructor | 6506 // -- rdi : constructor |
| 6457 // -- rsp[0] : return address | 6507 // -- rsp[0] : return address |
| 6458 // -- rsp[8] : last argument | 6508 // -- rsp[8] : last argument |
| 6459 // ----------------------------------- | 6509 // ----------------------------------- |
| 6460 Handle<Object> undefined_sentinel( | 6510 Handle<Object> undefined_sentinel( |
| 6461 masm->isolate()->heap()->undefined_value(), | 6511 masm->isolate()->heap()->undefined_value(), |
| (...skipping 15 matching lines...) Expand all Loading... |
| 6477 // We should either have undefined in rbx or a valid cell | 6527 // We should either have undefined in rbx or a valid cell |
| 6478 Label okay_here; | 6528 Label okay_here; |
| 6479 Handle<Map> cell_map = masm->isolate()->factory()->cell_map(); | 6529 Handle<Map> cell_map = masm->isolate()->factory()->cell_map(); |
| 6480 __ Cmp(rbx, undefined_sentinel); | 6530 __ Cmp(rbx, undefined_sentinel); |
| 6481 __ j(equal, &okay_here); | 6531 __ j(equal, &okay_here); |
| 6482 __ Cmp(FieldOperand(rbx, 0), cell_map); | 6532 __ Cmp(FieldOperand(rbx, 0), cell_map); |
| 6483 __ Assert(equal, kExpectedPropertyCellInRegisterRbx); | 6533 __ Assert(equal, kExpectedPropertyCellInRegisterRbx); |
| 6484 __ bind(&okay_here); | 6534 __ bind(&okay_here); |
| 6485 } | 6535 } |
| 6486 | 6536 |
| 6487 Label no_info, switch_ready; | 6537 Label no_info; |
| 6488 // Get the elements kind and case on that. | 6538 // If the type cell is undefined, or contains anything other than an |
| 6539 // AllocationSite, call an array constructor that doesn't use AllocationSites. |
| 6489 __ Cmp(rbx, undefined_sentinel); | 6540 __ Cmp(rbx, undefined_sentinel); |
| 6490 __ j(equal, &no_info); | 6541 __ j(equal, &no_info); |
| 6491 __ movq(rdx, FieldOperand(rbx, Cell::kValueOffset)); | 6542 __ movq(rdx, FieldOperand(rbx, Cell::kValueOffset)); |
| 6492 | |
| 6493 // The type cell may have undefined in its value. | |
| 6494 __ Cmp(rdx, undefined_sentinel); | |
| 6495 __ j(equal, &no_info); | |
| 6496 | |
| 6497 // The type cell has either an AllocationSite or a JSFunction | |
| 6498 __ Cmp(FieldOperand(rdx, 0), | 6543 __ Cmp(FieldOperand(rdx, 0), |
| 6499 Handle<Map>(masm->isolate()->heap()->allocation_site_map())); | 6544 Handle<Map>(masm->isolate()->heap()->allocation_site_map())); |
| 6500 __ j(not_equal, &no_info); | 6545 __ j(not_equal, &no_info); |
| 6501 | 6546 |
| 6502 __ movq(rdx, FieldOperand(rdx, AllocationSite::kTransitionInfoOffset)); | 6547 __ movq(rdx, FieldOperand(rdx, AllocationSite::kTransitionInfoOffset)); |
| 6503 __ SmiToInteger32(rdx, rdx); | 6548 __ SmiToInteger32(rdx, rdx); |
| 6504 __ jmp(&switch_ready); | 6549 GenerateDispatchToArrayStub(masm, DONT_OVERRIDE); |
| 6550 |
| 6505 __ bind(&no_info); | 6551 __ bind(&no_info); |
| 6506 __ movq(rdx, Immediate(GetInitialFastElementsKind())); | 6552 GenerateDispatchToArrayStub(masm, DISABLE_ALLOCATION_SITES); |
| 6507 __ bind(&switch_ready); | |
| 6508 | |
| 6509 if (argument_count_ == ANY) { | |
| 6510 Label not_zero_case, not_one_case; | |
| 6511 __ testq(rax, rax); | |
| 6512 __ j(not_zero, ¬_zero_case); | |
| 6513 CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm); | |
| 6514 | |
| 6515 __ bind(¬_zero_case); | |
| 6516 __ cmpl(rax, Immediate(1)); | |
| 6517 __ j(greater, ¬_one_case); | |
| 6518 CreateArrayDispatchOneArgument(masm); | |
| 6519 | |
| 6520 __ bind(¬_one_case); | |
| 6521 CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm); | |
| 6522 } else if (argument_count_ == NONE) { | |
| 6523 CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm); | |
| 6524 } else if (argument_count_ == ONE) { | |
| 6525 CreateArrayDispatchOneArgument(masm); | |
| 6526 } else if (argument_count_ == MORE_THAN_ONE) { | |
| 6527 CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm); | |
| 6528 } else { | |
| 6529 UNREACHABLE(); | |
| 6530 } | |
| 6531 } | 6553 } |
| 6532 | 6554 |
| 6533 | 6555 |
| 6534 void InternalArrayConstructorStub::GenerateCase( | 6556 void InternalArrayConstructorStub::GenerateCase( |
| 6535 MacroAssembler* masm, ElementsKind kind) { | 6557 MacroAssembler* masm, ElementsKind kind) { |
| 6536 Label not_zero_case, not_one_case; | 6558 Label not_zero_case, not_one_case; |
| 6537 Label normal_sequence; | 6559 Label normal_sequence; |
| 6538 | 6560 |
| 6539 __ testq(rax, rax); | 6561 __ testq(rax, rax); |
| 6540 __ j(not_zero, ¬_zero_case); | 6562 __ j(not_zero, ¬_zero_case); |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6619 __ bind(&fast_elements_case); | 6641 __ bind(&fast_elements_case); |
| 6620 GenerateCase(masm, FAST_ELEMENTS); | 6642 GenerateCase(masm, FAST_ELEMENTS); |
| 6621 } | 6643 } |
| 6622 | 6644 |
| 6623 | 6645 |
| 6624 #undef __ | 6646 #undef __ |
| 6625 | 6647 |
| 6626 } } // namespace v8::internal | 6648 } } // namespace v8::internal |
| 6627 | 6649 |
| 6628 #endif // V8_TARGET_ARCH_X64 | 6650 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |