OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 25 matching lines...) Expand all Loading... |
36 #include "regexp-macro-assembler.h" | 36 #include "regexp-macro-assembler.h" |
37 | 37 |
38 namespace v8 { | 38 namespace v8 { |
39 namespace internal { | 39 namespace internal { |
40 | 40 |
41 #define __ ACCESS_MASM(masm) | 41 #define __ ACCESS_MASM(masm) |
42 | 42 |
43 void ToNumberStub::Generate(MacroAssembler* masm) { | 43 void ToNumberStub::Generate(MacroAssembler* masm) { |
44 // The ToNumber stub takes one argument in eax. | 44 // The ToNumber stub takes one argument in eax. |
45 Label check_heap_number, call_builtin; | 45 Label check_heap_number, call_builtin; |
46 __ test(eax, Immediate(kSmiTagMask)); | 46 __ JumpIfNotSmi(eax, &check_heap_number, Label::kNear); |
47 __ j(not_zero, &check_heap_number, Label::kNear); | |
48 __ ret(0); | 47 __ ret(0); |
49 | 48 |
50 __ bind(&check_heap_number); | 49 __ bind(&check_heap_number); |
51 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); | 50 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); |
52 Factory* factory = masm->isolate()->factory(); | 51 Factory* factory = masm->isolate()->factory(); |
53 __ cmp(Operand(ebx), Immediate(factory->heap_number_map())); | 52 __ cmp(Operand(ebx), Immediate(factory->heap_number_map())); |
54 __ j(not_equal, &call_builtin, Label::kNear); | 53 __ j(not_equal, &call_builtin, Label::kNear); |
55 __ ret(0); | 54 __ ret(0); |
56 | 55 |
57 __ bind(&call_builtin); | 56 __ bind(&call_builtin); |
(...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
250 | 249 |
251 // Boolean -> its value | 250 // Boolean -> its value |
252 __ cmp(eax, factory->true_value()); | 251 __ cmp(eax, factory->true_value()); |
253 __ j(equal, &true_result); | 252 __ j(equal, &true_result); |
254 __ cmp(eax, factory->false_value()); | 253 __ cmp(eax, factory->false_value()); |
255 __ j(equal, &false_result); | 254 __ j(equal, &false_result); |
256 | 255 |
257 // Smis: 0 -> false, all other -> true | 256 // Smis: 0 -> false, all other -> true |
258 __ test(eax, Operand(eax)); | 257 __ test(eax, Operand(eax)); |
259 __ j(zero, &false_result); | 258 __ j(zero, &false_result); |
260 __ test(eax, Immediate(kSmiTagMask)); | 259 __ JumpIfSmi(eax, &true_result); |
261 __ j(zero, &true_result); | |
262 | 260 |
263 // 'null' => false. | 261 // 'null' => false. |
264 __ cmp(eax, factory->null_value()); | 262 __ cmp(eax, factory->null_value()); |
265 __ j(equal, &false_result, Label::kNear); | 263 __ j(equal, &false_result, Label::kNear); |
266 | 264 |
267 // Get the map and type of the heap object. | 265 // Get the map and type of the heap object. |
268 __ mov(edx, FieldOperand(eax, HeapObject::kMapOffset)); | 266 __ mov(edx, FieldOperand(eax, HeapObject::kMapOffset)); |
269 __ movzx_b(ecx, FieldOperand(edx, Map::kInstanceTypeOffset)); | 267 __ movzx_b(ecx, FieldOperand(edx, Map::kInstanceTypeOffset)); |
270 | 268 |
271 // Undetectable => false. | 269 // Undetectable => false. |
(...skipping 339 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
611 | 609 |
612 | 610 |
613 void UnaryOpStub::GenerateSmiCodeSub(MacroAssembler* masm, | 611 void UnaryOpStub::GenerateSmiCodeSub(MacroAssembler* masm, |
614 Label* non_smi, | 612 Label* non_smi, |
615 Label* undo, | 613 Label* undo, |
616 Label* slow, | 614 Label* slow, |
617 Label::Distance non_smi_near, | 615 Label::Distance non_smi_near, |
618 Label::Distance undo_near, | 616 Label::Distance undo_near, |
619 Label::Distance slow_near) { | 617 Label::Distance slow_near) { |
620 // Check whether the value is a smi. | 618 // Check whether the value is a smi. |
621 __ test(eax, Immediate(kSmiTagMask)); | 619 __ JumpIfNotSmi(eax, non_smi, non_smi_near); |
622 __ j(not_zero, non_smi, non_smi_near); | |
623 | 620 |
624 // We can't handle -0 with smis, so use a type transition for that case. | 621 // We can't handle -0 with smis, so use a type transition for that case. |
625 __ test(eax, Operand(eax)); | 622 __ test(eax, Operand(eax)); |
626 __ j(zero, slow, slow_near); | 623 __ j(zero, slow, slow_near); |
627 | 624 |
628 // Try optimistic subtraction '0 - value', saving operand in eax for undo. | 625 // Try optimistic subtraction '0 - value', saving operand in eax for undo. |
629 __ mov(edx, Operand(eax)); | 626 __ mov(edx, Operand(eax)); |
630 __ Set(eax, Immediate(0)); | 627 __ Set(eax, Immediate(0)); |
631 __ sub(eax, Operand(edx)); | 628 __ sub(eax, Operand(edx)); |
632 __ j(overflow, undo, undo_near); | 629 __ j(overflow, undo, undo_near); |
633 __ ret(0); | 630 __ ret(0); |
634 } | 631 } |
635 | 632 |
636 | 633 |
637 void UnaryOpStub::GenerateSmiCodeBitNot( | 634 void UnaryOpStub::GenerateSmiCodeBitNot( |
638 MacroAssembler* masm, | 635 MacroAssembler* masm, |
639 Label* non_smi, | 636 Label* non_smi, |
640 Label::Distance non_smi_near) { | 637 Label::Distance non_smi_near) { |
641 // Check whether the value is a smi. | 638 // Check whether the value is a smi. |
642 __ test(eax, Immediate(kSmiTagMask)); | 639 __ JumpIfNotSmi(eax, non_smi, non_smi_near); |
643 __ j(not_zero, non_smi, non_smi_near); | |
644 | 640 |
645 // Flip bits and revert inverted smi-tag. | 641 // Flip bits and revert inverted smi-tag. |
646 __ not_(eax); | 642 __ not_(eax); |
647 __ and_(eax, ~kSmiTagMask); | 643 __ and_(eax, ~kSmiTagMask); |
648 __ ret(0); | 644 __ ret(0); |
649 } | 645 } |
650 | 646 |
651 | 647 |
652 void UnaryOpStub::GenerateSmiCodeUndo(MacroAssembler* masm) { | 648 void UnaryOpStub::GenerateSmiCodeUndo(MacroAssembler* masm) { |
653 __ mov(eax, Operand(edx)); | 649 __ mov(eax, Operand(edx)); |
(...skipping 345 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
999 __ or_(right, Operand(left)); | 995 __ or_(right, Operand(left)); |
1000 combined = right; | 996 combined = right; |
1001 break; | 997 break; |
1002 | 998 |
1003 default: | 999 default: |
1004 break; | 1000 break; |
1005 } | 1001 } |
1006 | 1002 |
1007 // 3. Perform the smi check of the operands. | 1003 // 3. Perform the smi check of the operands. |
1008 STATIC_ASSERT(kSmiTag == 0); // Adjust zero check if not the case. | 1004 STATIC_ASSERT(kSmiTag == 0); // Adjust zero check if not the case. |
1009 __ test(combined, Immediate(kSmiTagMask)); | 1005 __ JumpIfNotSmi(combined, ¬_smis); |
1010 __ j(not_zero, ¬_smis); | |
1011 | 1006 |
1012 // 4. Operands are both smis, perform the operation leaving the result in | 1007 // 4. Operands are both smis, perform the operation leaving the result in |
1013 // eax and check the result if necessary. | 1008 // eax and check the result if necessary. |
1014 Comment perform_smi(masm, "-- Perform smi operation"); | 1009 Comment perform_smi(masm, "-- Perform smi operation"); |
1015 Label use_fp_on_smis; | 1010 Label use_fp_on_smis; |
1016 switch (op_) { | 1011 switch (op_) { |
1017 case Token::BIT_OR: | 1012 case Token::BIT_OR: |
1018 // Nothing to do. | 1013 // Nothing to do. |
1019 break; | 1014 break; |
1020 | 1015 |
(...skipping 367 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1388 ASSERT(operands_type_ == BinaryOpIC::BOTH_STRING); | 1383 ASSERT(operands_type_ == BinaryOpIC::BOTH_STRING); |
1389 ASSERT(op_ == Token::ADD); | 1384 ASSERT(op_ == Token::ADD); |
1390 // If both arguments are strings, call the string add stub. | 1385 // If both arguments are strings, call the string add stub. |
1391 // Otherwise, do a transition. | 1386 // Otherwise, do a transition. |
1392 | 1387 |
1393 // Registers containing left and right operands respectively. | 1388 // Registers containing left and right operands respectively. |
1394 Register left = edx; | 1389 Register left = edx; |
1395 Register right = eax; | 1390 Register right = eax; |
1396 | 1391 |
1397 // Test if left operand is a string. | 1392 // Test if left operand is a string. |
1398 __ test(left, Immediate(kSmiTagMask)); | 1393 __ JumpIfSmi(left, &call_runtime); |
1399 __ j(zero, &call_runtime); | |
1400 __ CmpObjectType(left, FIRST_NONSTRING_TYPE, ecx); | 1394 __ CmpObjectType(left, FIRST_NONSTRING_TYPE, ecx); |
1401 __ j(above_equal, &call_runtime); | 1395 __ j(above_equal, &call_runtime); |
1402 | 1396 |
1403 // Test if right operand is a string. | 1397 // Test if right operand is a string. |
1404 __ test(right, Immediate(kSmiTagMask)); | 1398 __ JumpIfSmi(right, &call_runtime); |
1405 __ j(zero, &call_runtime); | |
1406 __ CmpObjectType(right, FIRST_NONSTRING_TYPE, ecx); | 1399 __ CmpObjectType(right, FIRST_NONSTRING_TYPE, ecx); |
1407 __ j(above_equal, &call_runtime); | 1400 __ j(above_equal, &call_runtime); |
1408 | 1401 |
1409 StringAddStub string_add_stub(NO_STRING_CHECK_IN_STUB); | 1402 StringAddStub string_add_stub(NO_STRING_CHECK_IN_STUB); |
1410 GenerateRegisterArgsPush(masm); | 1403 GenerateRegisterArgsPush(masm); |
1411 __ TailCallStub(&string_add_stub); | 1404 __ TailCallStub(&string_add_stub); |
1412 | 1405 |
1413 __ bind(&call_runtime); | 1406 __ bind(&call_runtime); |
1414 GenerateTypeTransition(masm); | 1407 GenerateTypeTransition(masm); |
1415 } | 1408 } |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1531 // Allocate a heap number if needed. | 1524 // Allocate a heap number if needed. |
1532 __ mov(ebx, Operand(eax)); // ebx: result | 1525 __ mov(ebx, Operand(eax)); // ebx: result |
1533 Label skip_allocation; | 1526 Label skip_allocation; |
1534 switch (mode_) { | 1527 switch (mode_) { |
1535 case OVERWRITE_LEFT: | 1528 case OVERWRITE_LEFT: |
1536 case OVERWRITE_RIGHT: | 1529 case OVERWRITE_RIGHT: |
1537 // If the operand was an object, we skip the | 1530 // If the operand was an object, we skip the |
1538 // allocation of a heap number. | 1531 // allocation of a heap number. |
1539 __ mov(eax, Operand(esp, mode_ == OVERWRITE_RIGHT ? | 1532 __ mov(eax, Operand(esp, mode_ == OVERWRITE_RIGHT ? |
1540 1 * kPointerSize : 2 * kPointerSize)); | 1533 1 * kPointerSize : 2 * kPointerSize)); |
1541 __ test(eax, Immediate(kSmiTagMask)); | 1534 __ JumpIfNotSmi(eax, &skip_allocation, Label::kNear); |
1542 __ j(not_zero, &skip_allocation, Label::kNear); | |
1543 // Fall through! | 1535 // Fall through! |
1544 case NO_OVERWRITE: | 1536 case NO_OVERWRITE: |
1545 __ AllocateHeapNumber(eax, ecx, edx, &call_runtime); | 1537 __ AllocateHeapNumber(eax, ecx, edx, &call_runtime); |
1546 __ bind(&skip_allocation); | 1538 __ bind(&skip_allocation); |
1547 break; | 1539 break; |
1548 default: UNREACHABLE(); | 1540 default: UNREACHABLE(); |
1549 } | 1541 } |
1550 // Store the result in the HeapNumber and return. | 1542 // Store the result in the HeapNumber and return. |
1551 if (CpuFeatures::IsSupported(SSE2)) { | 1543 if (CpuFeatures::IsSupported(SSE2)) { |
1552 CpuFeatures::Scope use_sse2(SSE2); | 1544 CpuFeatures::Scope use_sse2(SSE2); |
(...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1746 // Allocate a heap number if needed. | 1738 // Allocate a heap number if needed. |
1747 __ mov(ebx, Operand(eax)); // ebx: result | 1739 __ mov(ebx, Operand(eax)); // ebx: result |
1748 Label skip_allocation; | 1740 Label skip_allocation; |
1749 switch (mode_) { | 1741 switch (mode_) { |
1750 case OVERWRITE_LEFT: | 1742 case OVERWRITE_LEFT: |
1751 case OVERWRITE_RIGHT: | 1743 case OVERWRITE_RIGHT: |
1752 // If the operand was an object, we skip the | 1744 // If the operand was an object, we skip the |
1753 // allocation of a heap number. | 1745 // allocation of a heap number. |
1754 __ mov(eax, Operand(esp, mode_ == OVERWRITE_RIGHT ? | 1746 __ mov(eax, Operand(esp, mode_ == OVERWRITE_RIGHT ? |
1755 1 * kPointerSize : 2 * kPointerSize)); | 1747 1 * kPointerSize : 2 * kPointerSize)); |
1756 __ test(eax, Immediate(kSmiTagMask)); | 1748 __ JumpIfNotSmi(eax, &skip_allocation, Label::kNear); |
1757 __ j(not_zero, &skip_allocation, Label::kNear); | |
1758 // Fall through! | 1749 // Fall through! |
1759 case NO_OVERWRITE: | 1750 case NO_OVERWRITE: |
1760 __ AllocateHeapNumber(eax, ecx, edx, &call_runtime); | 1751 __ AllocateHeapNumber(eax, ecx, edx, &call_runtime); |
1761 __ bind(&skip_allocation); | 1752 __ bind(&skip_allocation); |
1762 break; | 1753 break; |
1763 default: UNREACHABLE(); | 1754 default: UNREACHABLE(); |
1764 } | 1755 } |
1765 // Store the result in the HeapNumber and return. | 1756 // Store the result in the HeapNumber and return. |
1766 if (CpuFeatures::IsSupported(SSE2)) { | 1757 if (CpuFeatures::IsSupported(SSE2)) { |
1767 CpuFeatures::Scope use_sse2(SSE2); | 1758 CpuFeatures::Scope use_sse2(SSE2); |
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1946 // Allocate a heap number if needed. | 1937 // Allocate a heap number if needed. |
1947 __ mov(ebx, Operand(eax)); // ebx: result | 1938 __ mov(ebx, Operand(eax)); // ebx: result |
1948 Label skip_allocation; | 1939 Label skip_allocation; |
1949 switch (mode_) { | 1940 switch (mode_) { |
1950 case OVERWRITE_LEFT: | 1941 case OVERWRITE_LEFT: |
1951 case OVERWRITE_RIGHT: | 1942 case OVERWRITE_RIGHT: |
1952 // If the operand was an object, we skip the | 1943 // If the operand was an object, we skip the |
1953 // allocation of a heap number. | 1944 // allocation of a heap number. |
1954 __ mov(eax, Operand(esp, mode_ == OVERWRITE_RIGHT ? | 1945 __ mov(eax, Operand(esp, mode_ == OVERWRITE_RIGHT ? |
1955 1 * kPointerSize : 2 * kPointerSize)); | 1946 1 * kPointerSize : 2 * kPointerSize)); |
1956 __ test(eax, Immediate(kSmiTagMask)); | 1947 __ JumpIfNotSmi(eax, &skip_allocation, Label::kNear); |
1957 __ j(not_zero, &skip_allocation, Label::kNear); | |
1958 // Fall through! | 1948 // Fall through! |
1959 case NO_OVERWRITE: | 1949 case NO_OVERWRITE: |
1960 __ AllocateHeapNumber(eax, ecx, edx, &call_runtime); | 1950 __ AllocateHeapNumber(eax, ecx, edx, &call_runtime); |
1961 __ bind(&skip_allocation); | 1951 __ bind(&skip_allocation); |
1962 break; | 1952 break; |
1963 default: UNREACHABLE(); | 1953 default: UNREACHABLE(); |
1964 } | 1954 } |
1965 // Store the result in the HeapNumber and return. | 1955 // Store the result in the HeapNumber and return. |
1966 if (CpuFeatures::IsSupported(SSE2)) { | 1956 if (CpuFeatures::IsSupported(SSE2)) { |
1967 CpuFeatures::Scope use_sse2(SSE2); | 1957 CpuFeatures::Scope use_sse2(SSE2); |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2030 | 2020 |
2031 void BinaryOpStub::GenerateAddStrings(MacroAssembler* masm) { | 2021 void BinaryOpStub::GenerateAddStrings(MacroAssembler* masm) { |
2032 ASSERT(op_ == Token::ADD); | 2022 ASSERT(op_ == Token::ADD); |
2033 Label left_not_string, call_runtime; | 2023 Label left_not_string, call_runtime; |
2034 | 2024 |
2035 // Registers containing left and right operands respectively. | 2025 // Registers containing left and right operands respectively. |
2036 Register left = edx; | 2026 Register left = edx; |
2037 Register right = eax; | 2027 Register right = eax; |
2038 | 2028 |
2039 // Test if left operand is a string. | 2029 // Test if left operand is a string. |
2040 __ test(left, Immediate(kSmiTagMask)); | 2030 __ JumpIfSmi(left, &left_not_string, Label::kNear); |
2041 __ j(zero, &left_not_string, Label::kNear); | |
2042 __ CmpObjectType(left, FIRST_NONSTRING_TYPE, ecx); | 2031 __ CmpObjectType(left, FIRST_NONSTRING_TYPE, ecx); |
2043 __ j(above_equal, &left_not_string, Label::kNear); | 2032 __ j(above_equal, &left_not_string, Label::kNear); |
2044 | 2033 |
2045 StringAddStub string_add_left_stub(NO_STRING_CHECK_LEFT_IN_STUB); | 2034 StringAddStub string_add_left_stub(NO_STRING_CHECK_LEFT_IN_STUB); |
2046 GenerateRegisterArgsPush(masm); | 2035 GenerateRegisterArgsPush(masm); |
2047 __ TailCallStub(&string_add_left_stub); | 2036 __ TailCallStub(&string_add_left_stub); |
2048 | 2037 |
2049 // Left operand is not a string, test right. | 2038 // Left operand is not a string, test right. |
2050 __ bind(&left_not_string); | 2039 __ bind(&left_not_string); |
2051 __ test(right, Immediate(kSmiTagMask)); | 2040 __ JumpIfSmi(right, &call_runtime, Label::kNear); |
2052 __ j(zero, &call_runtime, Label::kNear); | |
2053 __ CmpObjectType(right, FIRST_NONSTRING_TYPE, ecx); | 2041 __ CmpObjectType(right, FIRST_NONSTRING_TYPE, ecx); |
2054 __ j(above_equal, &call_runtime, Label::kNear); | 2042 __ j(above_equal, &call_runtime, Label::kNear); |
2055 | 2043 |
2056 StringAddStub string_add_right_stub(NO_STRING_CHECK_RIGHT_IN_STUB); | 2044 StringAddStub string_add_right_stub(NO_STRING_CHECK_RIGHT_IN_STUB); |
2057 GenerateRegisterArgsPush(masm); | 2045 GenerateRegisterArgsPush(masm); |
2058 __ TailCallStub(&string_add_right_stub); | 2046 __ TailCallStub(&string_add_right_stub); |
2059 | 2047 |
2060 // Neither argument is a string. | 2048 // Neither argument is a string. |
2061 __ bind(&call_runtime); | 2049 __ bind(&call_runtime); |
2062 } | 2050 } |
2063 | 2051 |
2064 | 2052 |
2065 void BinaryOpStub::GenerateHeapResultAllocation( | 2053 void BinaryOpStub::GenerateHeapResultAllocation( |
2066 MacroAssembler* masm, | 2054 MacroAssembler* masm, |
2067 Label* alloc_failure) { | 2055 Label* alloc_failure) { |
2068 Label skip_allocation; | 2056 Label skip_allocation; |
2069 OverwriteMode mode = mode_; | 2057 OverwriteMode mode = mode_; |
2070 switch (mode) { | 2058 switch (mode) { |
2071 case OVERWRITE_LEFT: { | 2059 case OVERWRITE_LEFT: { |
2072 // If the argument in edx is already an object, we skip the | 2060 // If the argument in edx is already an object, we skip the |
2073 // allocation of a heap number. | 2061 // allocation of a heap number. |
2074 __ test(edx, Immediate(kSmiTagMask)); | 2062 __ JumpIfNotSmi(edx, &skip_allocation, Label::kNear); |
2075 __ j(not_zero, &skip_allocation); | |
2076 // Allocate a heap number for the result. Keep eax and edx intact | 2063 // Allocate a heap number for the result. Keep eax and edx intact |
2077 // for the possible runtime call. | 2064 // for the possible runtime call. |
2078 __ AllocateHeapNumber(ebx, ecx, no_reg, alloc_failure); | 2065 __ AllocateHeapNumber(ebx, ecx, no_reg, alloc_failure); |
2079 // Now edx can be overwritten losing one of the arguments as we are | 2066 // Now edx can be overwritten losing one of the arguments as we are |
2080 // now done and will not need it any more. | 2067 // now done and will not need it any more. |
2081 __ mov(edx, Operand(ebx)); | 2068 __ mov(edx, Operand(ebx)); |
2082 __ bind(&skip_allocation); | 2069 __ bind(&skip_allocation); |
2083 // Use object in edx as a result holder | 2070 // Use object in edx as a result holder |
2084 __ mov(eax, Operand(edx)); | 2071 __ mov(eax, Operand(edx)); |
2085 break; | 2072 break; |
2086 } | 2073 } |
2087 case OVERWRITE_RIGHT: | 2074 case OVERWRITE_RIGHT: |
2088 // If the argument in eax is already an object, we skip the | 2075 // If the argument in eax is already an object, we skip the |
2089 // allocation of a heap number. | 2076 // allocation of a heap number. |
2090 __ test(eax, Immediate(kSmiTagMask)); | 2077 __ JumpIfNotSmi(eax, &skip_allocation, Label::kNear); |
2091 __ j(not_zero, &skip_allocation); | |
2092 // Fall through! | 2078 // Fall through! |
2093 case NO_OVERWRITE: | 2079 case NO_OVERWRITE: |
2094 // Allocate a heap number for the result. Keep eax and edx intact | 2080 // Allocate a heap number for the result. Keep eax and edx intact |
2095 // for the possible runtime call. | 2081 // for the possible runtime call. |
2096 __ AllocateHeapNumber(ebx, ecx, no_reg, alloc_failure); | 2082 __ AllocateHeapNumber(ebx, ecx, no_reg, alloc_failure); |
2097 // Now eax can be overwritten losing one of the arguments as we are | 2083 // Now eax can be overwritten losing one of the arguments as we are |
2098 // now done and will not need it any more. | 2084 // now done and will not need it any more. |
2099 __ mov(eax, ebx); | 2085 __ mov(eax, ebx); |
2100 __ bind(&skip_allocation); | 2086 __ bind(&skip_allocation); |
2101 break; | 2087 break; |
(...skipping 26 matching lines...) Expand all Loading... |
2128 | 2114 |
2129 Label runtime_call; | 2115 Label runtime_call; |
2130 Label runtime_call_clear_stack; | 2116 Label runtime_call_clear_stack; |
2131 Label skip_cache; | 2117 Label skip_cache; |
2132 const bool tagged = (argument_type_ == TAGGED); | 2118 const bool tagged = (argument_type_ == TAGGED); |
2133 if (tagged) { | 2119 if (tagged) { |
2134 // Test that eax is a number. | 2120 // Test that eax is a number. |
2135 Label input_not_smi; | 2121 Label input_not_smi; |
2136 Label loaded; | 2122 Label loaded; |
2137 __ mov(eax, Operand(esp, kPointerSize)); | 2123 __ mov(eax, Operand(esp, kPointerSize)); |
2138 __ test(eax, Immediate(kSmiTagMask)); | 2124 __ JumpIfNotSmi(eax, &input_not_smi, Label::kNear); |
2139 __ j(not_zero, &input_not_smi, Label::kNear); | |
2140 // Input is a smi. Untag and load it onto the FPU stack. | 2125 // Input is a smi. Untag and load it onto the FPU stack. |
2141 // Then load the low and high words of the double into ebx, edx. | 2126 // Then load the low and high words of the double into ebx, edx. |
2142 STATIC_ASSERT(kSmiTagSize == 1); | 2127 STATIC_ASSERT(kSmiTagSize == 1); |
2143 __ sar(eax, 1); | 2128 __ sar(eax, 1); |
2144 __ sub(Operand(esp), Immediate(2 * kPointerSize)); | 2129 __ sub(Operand(esp), Immediate(2 * kPointerSize)); |
2145 __ mov(Operand(esp, 0), eax); | 2130 __ mov(Operand(esp, 0), eax); |
2146 __ fild_s(Operand(esp, 0)); | 2131 __ fild_s(Operand(esp, 0)); |
2147 __ fst_d(Operand(esp, 0)); | 2132 __ fst_d(Operand(esp, 0)); |
2148 __ pop(edx); | 2133 __ pop(edx); |
2149 __ pop(ebx); | 2134 __ pop(ebx); |
(...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2407 // Output: eax, ecx are left and right integers for a bit op. | 2392 // Output: eax, ecx are left and right integers for a bit op. |
2408 void FloatingPointHelper::LoadUnknownsAsIntegers(MacroAssembler* masm, | 2393 void FloatingPointHelper::LoadUnknownsAsIntegers(MacroAssembler* masm, |
2409 bool use_sse3, | 2394 bool use_sse3, |
2410 Label* conversion_failure) { | 2395 Label* conversion_failure) { |
2411 // Check float operands. | 2396 // Check float operands. |
2412 Label arg1_is_object, check_undefined_arg1; | 2397 Label arg1_is_object, check_undefined_arg1; |
2413 Label arg2_is_object, check_undefined_arg2; | 2398 Label arg2_is_object, check_undefined_arg2; |
2414 Label load_arg2, done; | 2399 Label load_arg2, done; |
2415 | 2400 |
2416 // Test if arg1 is a Smi. | 2401 // Test if arg1 is a Smi. |
2417 __ test(edx, Immediate(kSmiTagMask)); | 2402 __ JumpIfNotSmi(edx, &arg1_is_object); |
2418 __ j(not_zero, &arg1_is_object); | |
2419 | 2403 |
2420 __ SmiUntag(edx); | 2404 __ SmiUntag(edx); |
2421 __ jmp(&load_arg2); | 2405 __ jmp(&load_arg2); |
2422 | 2406 |
2423 // If the argument is undefined it converts to zero (ECMA-262, section 9.5). | 2407 // If the argument is undefined it converts to zero (ECMA-262, section 9.5). |
2424 __ bind(&check_undefined_arg1); | 2408 __ bind(&check_undefined_arg1); |
2425 Factory* factory = masm->isolate()->factory(); | 2409 Factory* factory = masm->isolate()->factory(); |
2426 __ cmp(edx, factory->undefined_value()); | 2410 __ cmp(edx, factory->undefined_value()); |
2427 __ j(not_equal, conversion_failure); | 2411 __ j(not_equal, conversion_failure); |
2428 __ mov(edx, Immediate(0)); | 2412 __ mov(edx, Immediate(0)); |
2429 __ jmp(&load_arg2); | 2413 __ jmp(&load_arg2); |
2430 | 2414 |
2431 __ bind(&arg1_is_object); | 2415 __ bind(&arg1_is_object); |
2432 __ mov(ebx, FieldOperand(edx, HeapObject::kMapOffset)); | 2416 __ mov(ebx, FieldOperand(edx, HeapObject::kMapOffset)); |
2433 __ cmp(ebx, factory->heap_number_map()); | 2417 __ cmp(ebx, factory->heap_number_map()); |
2434 __ j(not_equal, &check_undefined_arg1); | 2418 __ j(not_equal, &check_undefined_arg1); |
2435 | 2419 |
2436 // Get the untagged integer version of the edx heap number in ecx. | 2420 // Get the untagged integer version of the edx heap number in ecx. |
2437 IntegerConvert(masm, edx, use_sse3, conversion_failure); | 2421 IntegerConvert(masm, edx, use_sse3, conversion_failure); |
2438 __ mov(edx, ecx); | 2422 __ mov(edx, ecx); |
2439 | 2423 |
2440 // Here edx has the untagged integer, eax has a Smi or a heap number. | 2424 // Here edx has the untagged integer, eax has a Smi or a heap number. |
2441 __ bind(&load_arg2); | 2425 __ bind(&load_arg2); |
2442 | 2426 |
2443 // Test if arg2 is a Smi. | 2427 // Test if arg2 is a Smi. |
2444 __ test(eax, Immediate(kSmiTagMask)); | 2428 __ JumpIfNotSmi(eax, &arg2_is_object); |
2445 __ j(not_zero, &arg2_is_object); | |
2446 | 2429 |
2447 __ SmiUntag(eax); | 2430 __ SmiUntag(eax); |
2448 __ mov(ecx, eax); | 2431 __ mov(ecx, eax); |
2449 __ jmp(&done); | 2432 __ jmp(&done); |
2450 | 2433 |
2451 // If the argument is undefined it converts to zero (ECMA-262, section 9.5). | 2434 // If the argument is undefined it converts to zero (ECMA-262, section 9.5). |
2452 __ bind(&check_undefined_arg2); | 2435 __ bind(&check_undefined_arg2); |
2453 __ cmp(eax, factory->undefined_value()); | 2436 __ cmp(eax, factory->undefined_value()); |
2454 __ j(not_equal, conversion_failure); | 2437 __ j(not_equal, conversion_failure); |
2455 __ mov(ecx, Immediate(0)); | 2438 __ mov(ecx, Immediate(0)); |
(...skipping 15 matching lines...) Expand all Loading... |
2471 bool use_sse3, | 2454 bool use_sse3, |
2472 Label* not_int32) { | 2455 Label* not_int32) { |
2473 return; | 2456 return; |
2474 } | 2457 } |
2475 | 2458 |
2476 | 2459 |
2477 void FloatingPointHelper::LoadFloatOperand(MacroAssembler* masm, | 2460 void FloatingPointHelper::LoadFloatOperand(MacroAssembler* masm, |
2478 Register number) { | 2461 Register number) { |
2479 Label load_smi, done; | 2462 Label load_smi, done; |
2480 | 2463 |
2481 __ test(number, Immediate(kSmiTagMask)); | 2464 __ JumpIfSmi(number, &load_smi, Label::kNear); |
2482 __ j(zero, &load_smi, Label::kNear); | |
2483 __ fld_d(FieldOperand(number, HeapNumber::kValueOffset)); | 2465 __ fld_d(FieldOperand(number, HeapNumber::kValueOffset)); |
2484 __ jmp(&done, Label::kNear); | 2466 __ jmp(&done, Label::kNear); |
2485 | 2467 |
2486 __ bind(&load_smi); | 2468 __ bind(&load_smi); |
2487 __ SmiUntag(number); | 2469 __ SmiUntag(number); |
2488 __ push(number); | 2470 __ push(number); |
2489 __ fild_s(Operand(esp, 0)); | 2471 __ fild_s(Operand(esp, 0)); |
2490 __ pop(number); | 2472 __ pop(number); |
2491 | 2473 |
2492 __ bind(&done); | 2474 __ bind(&done); |
2493 } | 2475 } |
2494 | 2476 |
2495 | 2477 |
2496 void FloatingPointHelper::LoadSSE2Operands(MacroAssembler* masm) { | 2478 void FloatingPointHelper::LoadSSE2Operands(MacroAssembler* masm) { |
2497 Label load_smi_edx, load_eax, load_smi_eax, done; | 2479 Label load_smi_edx, load_eax, load_smi_eax, done; |
2498 // Load operand in edx into xmm0. | 2480 // Load operand in edx into xmm0. |
2499 __ test(edx, Immediate(kSmiTagMask)); | 2481 __ JumpIfSmi(edx, &load_smi_edx, Label::kNear); |
2500 // Argument in edx is a smi. | |
2501 __ j(zero, &load_smi_edx, Label::kNear); | |
2502 __ movdbl(xmm0, FieldOperand(edx, HeapNumber::kValueOffset)); | 2482 __ movdbl(xmm0, FieldOperand(edx, HeapNumber::kValueOffset)); |
2503 | 2483 |
2504 __ bind(&load_eax); | 2484 __ bind(&load_eax); |
2505 // Load operand in eax into xmm1. | 2485 // Load operand in eax into xmm1. |
2506 __ test(eax, Immediate(kSmiTagMask)); | 2486 __ JumpIfSmi(eax, &load_smi_eax, Label::kNear); |
2507 // Argument in eax is a smi. | |
2508 __ j(zero, &load_smi_eax, Label::kNear); | |
2509 __ movdbl(xmm1, FieldOperand(eax, HeapNumber::kValueOffset)); | 2487 __ movdbl(xmm1, FieldOperand(eax, HeapNumber::kValueOffset)); |
2510 __ jmp(&done, Label::kNear); | 2488 __ jmp(&done, Label::kNear); |
2511 | 2489 |
2512 __ bind(&load_smi_edx); | 2490 __ bind(&load_smi_edx); |
2513 __ SmiUntag(edx); // Untag smi before converting to float. | 2491 __ SmiUntag(edx); // Untag smi before converting to float. |
2514 __ cvtsi2sd(xmm0, Operand(edx)); | 2492 __ cvtsi2sd(xmm0, Operand(edx)); |
2515 __ SmiTag(edx); // Retag smi for heap number overwriting test. | 2493 __ SmiTag(edx); // Retag smi for heap number overwriting test. |
2516 __ jmp(&load_eax); | 2494 __ jmp(&load_eax); |
2517 | 2495 |
2518 __ bind(&load_smi_eax); | 2496 __ bind(&load_smi_eax); |
2519 __ SmiUntag(eax); // Untag smi before converting to float. | 2497 __ SmiUntag(eax); // Untag smi before converting to float. |
2520 __ cvtsi2sd(xmm1, Operand(eax)); | 2498 __ cvtsi2sd(xmm1, Operand(eax)); |
2521 __ SmiTag(eax); // Retag smi for heap number overwriting test. | 2499 __ SmiTag(eax); // Retag smi for heap number overwriting test. |
2522 | 2500 |
2523 __ bind(&done); | 2501 __ bind(&done); |
2524 } | 2502 } |
2525 | 2503 |
2526 | 2504 |
2527 void FloatingPointHelper::LoadSSE2Operands(MacroAssembler* masm, | 2505 void FloatingPointHelper::LoadSSE2Operands(MacroAssembler* masm, |
2528 Label* not_numbers) { | 2506 Label* not_numbers) { |
2529 Label load_smi_edx, load_eax, load_smi_eax, load_float_eax, done; | 2507 Label load_smi_edx, load_eax, load_smi_eax, load_float_eax, done; |
2530 // Load operand in edx into xmm0, or branch to not_numbers. | 2508 // Load operand in edx into xmm0, or branch to not_numbers. |
2531 __ test(edx, Immediate(kSmiTagMask)); | 2509 __ JumpIfSmi(edx, &load_smi_edx, Label::kNear); |
2532 // Argument in edx is a smi. | |
2533 __ j(zero, &load_smi_edx, Label::kNear); | |
2534 Factory* factory = masm->isolate()->factory(); | 2510 Factory* factory = masm->isolate()->factory(); |
2535 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), factory->heap_number_map()); | 2511 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), factory->heap_number_map()); |
2536 __ j(not_equal, not_numbers); // Argument in edx is not a number. | 2512 __ j(not_equal, not_numbers); // Argument in edx is not a number. |
2537 __ movdbl(xmm0, FieldOperand(edx, HeapNumber::kValueOffset)); | 2513 __ movdbl(xmm0, FieldOperand(edx, HeapNumber::kValueOffset)); |
2538 __ bind(&load_eax); | 2514 __ bind(&load_eax); |
2539 // Load operand in eax into xmm1, or branch to not_numbers. | 2515 // Load operand in eax into xmm1, or branch to not_numbers. |
2540 __ test(eax, Immediate(kSmiTagMask)); | 2516 __ JumpIfSmi(eax, &load_smi_eax, Label::kNear); |
2541 // Argument in eax is a smi. | |
2542 __ j(zero, &load_smi_eax, Label::kNear); | |
2543 __ cmp(FieldOperand(eax, HeapObject::kMapOffset), factory->heap_number_map()); | 2517 __ cmp(FieldOperand(eax, HeapObject::kMapOffset), factory->heap_number_map()); |
2544 __ j(equal, &load_float_eax, Label::kNear); | 2518 __ j(equal, &load_float_eax, Label::kNear); |
2545 __ jmp(not_numbers); // Argument in eax is not a number. | 2519 __ jmp(not_numbers); // Argument in eax is not a number. |
2546 __ bind(&load_smi_edx); | 2520 __ bind(&load_smi_edx); |
2547 __ SmiUntag(edx); // Untag smi before converting to float. | 2521 __ SmiUntag(edx); // Untag smi before converting to float. |
2548 __ cvtsi2sd(xmm0, Operand(edx)); | 2522 __ cvtsi2sd(xmm0, Operand(edx)); |
2549 __ SmiTag(edx); // Retag smi for heap number overwriting test. | 2523 __ SmiTag(edx); // Retag smi for heap number overwriting test. |
2550 __ jmp(&load_eax); | 2524 __ jmp(&load_eax); |
2551 __ bind(&load_smi_eax); | 2525 __ bind(&load_smi_eax); |
2552 __ SmiUntag(eax); // Untag smi before converting to float. | 2526 __ SmiUntag(eax); // Untag smi before converting to float. |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2592 | 2566 |
2593 void FloatingPointHelper::LoadFloatOperands(MacroAssembler* masm, | 2567 void FloatingPointHelper::LoadFloatOperands(MacroAssembler* masm, |
2594 Register scratch, | 2568 Register scratch, |
2595 ArgLocation arg_location) { | 2569 ArgLocation arg_location) { |
2596 Label load_smi_1, load_smi_2, done_load_1, done; | 2570 Label load_smi_1, load_smi_2, done_load_1, done; |
2597 if (arg_location == ARGS_IN_REGISTERS) { | 2571 if (arg_location == ARGS_IN_REGISTERS) { |
2598 __ mov(scratch, edx); | 2572 __ mov(scratch, edx); |
2599 } else { | 2573 } else { |
2600 __ mov(scratch, Operand(esp, 2 * kPointerSize)); | 2574 __ mov(scratch, Operand(esp, 2 * kPointerSize)); |
2601 } | 2575 } |
2602 __ test(scratch, Immediate(kSmiTagMask)); | 2576 __ JumpIfSmi(scratch, &load_smi_1, Label::kNear); |
2603 __ j(zero, &load_smi_1, Label::kNear); | |
2604 __ fld_d(FieldOperand(scratch, HeapNumber::kValueOffset)); | 2577 __ fld_d(FieldOperand(scratch, HeapNumber::kValueOffset)); |
2605 __ bind(&done_load_1); | 2578 __ bind(&done_load_1); |
2606 | 2579 |
2607 if (arg_location == ARGS_IN_REGISTERS) { | 2580 if (arg_location == ARGS_IN_REGISTERS) { |
2608 __ mov(scratch, eax); | 2581 __ mov(scratch, eax); |
2609 } else { | 2582 } else { |
2610 __ mov(scratch, Operand(esp, 1 * kPointerSize)); | 2583 __ mov(scratch, Operand(esp, 1 * kPointerSize)); |
2611 } | 2584 } |
2612 __ test(scratch, Immediate(kSmiTagMask)); | 2585 __ JumpIfSmi(scratch, &load_smi_2, Label::kNear); |
2613 __ j(zero, &load_smi_2, Label::kNear); | |
2614 __ fld_d(FieldOperand(scratch, HeapNumber::kValueOffset)); | 2586 __ fld_d(FieldOperand(scratch, HeapNumber::kValueOffset)); |
2615 __ jmp(&done, Label::kNear); | 2587 __ jmp(&done, Label::kNear); |
2616 | 2588 |
2617 __ bind(&load_smi_1); | 2589 __ bind(&load_smi_1); |
2618 __ SmiUntag(scratch); | 2590 __ SmiUntag(scratch); |
2619 __ push(scratch); | 2591 __ push(scratch); |
2620 __ fild_s(Operand(esp, 0)); | 2592 __ fild_s(Operand(esp, 0)); |
2621 __ pop(scratch); | 2593 __ pop(scratch); |
2622 __ jmp(&done_load_1); | 2594 __ jmp(&done_load_1); |
2623 | 2595 |
(...skipping 24 matching lines...) Expand all Loading... |
2648 __ pop(scratch); | 2620 __ pop(scratch); |
2649 } | 2621 } |
2650 | 2622 |
2651 | 2623 |
2652 void FloatingPointHelper::CheckFloatOperands(MacroAssembler* masm, | 2624 void FloatingPointHelper::CheckFloatOperands(MacroAssembler* masm, |
2653 Label* non_float, | 2625 Label* non_float, |
2654 Register scratch) { | 2626 Register scratch) { |
2655 Label test_other, done; | 2627 Label test_other, done; |
2656 // Test if both operands are floats or smi -> scratch=k_is_float; | 2628 // Test if both operands are floats or smi -> scratch=k_is_float; |
2657 // Otherwise scratch = k_not_float. | 2629 // Otherwise scratch = k_not_float. |
2658 __ test(edx, Immediate(kSmiTagMask)); | 2630 __ JumpIfSmi(edx, &test_other, Label::kNear); |
2659 __ j(zero, &test_other, Label::kNear); // argument in edx is OK | |
2660 __ mov(scratch, FieldOperand(edx, HeapObject::kMapOffset)); | 2631 __ mov(scratch, FieldOperand(edx, HeapObject::kMapOffset)); |
2661 Factory* factory = masm->isolate()->factory(); | 2632 Factory* factory = masm->isolate()->factory(); |
2662 __ cmp(scratch, factory->heap_number_map()); | 2633 __ cmp(scratch, factory->heap_number_map()); |
2663 __ j(not_equal, non_float); // argument in edx is not a number -> NaN | 2634 __ j(not_equal, non_float); // argument in edx is not a number -> NaN |
2664 | 2635 |
2665 __ bind(&test_other); | 2636 __ bind(&test_other); |
2666 __ test(eax, Immediate(kSmiTagMask)); | 2637 __ JumpIfSmi(eax, &done, Label::kNear); |
2667 __ j(zero, &done, Label::kNear); // argument in eax is OK | |
2668 __ mov(scratch, FieldOperand(eax, HeapObject::kMapOffset)); | 2638 __ mov(scratch, FieldOperand(eax, HeapObject::kMapOffset)); |
2669 __ cmp(scratch, factory->heap_number_map()); | 2639 __ cmp(scratch, factory->heap_number_map()); |
2670 __ j(not_equal, non_float); // argument in eax is not a number -> NaN | 2640 __ j(not_equal, non_float); // argument in eax is not a number -> NaN |
2671 | 2641 |
2672 // Fall-through: Both operands are numbers. | 2642 // Fall-through: Both operands are numbers. |
2673 __ bind(&done); | 2643 __ bind(&done); |
2674 } | 2644 } |
2675 | 2645 |
2676 | 2646 |
2677 void FloatingPointHelper::CheckFloatOperandsAreInt32(MacroAssembler* masm, | 2647 void FloatingPointHelper::CheckFloatOperandsAreInt32(MacroAssembler* masm, |
(...skipping 15 matching lines...) Expand all Loading... |
2693 __ mov(edx, Operand(esp, 2 * kPointerSize)); | 2663 __ mov(edx, Operand(esp, 2 * kPointerSize)); |
2694 __ mov(eax, Operand(esp, 1 * kPointerSize)); | 2664 __ mov(eax, Operand(esp, 1 * kPointerSize)); |
2695 | 2665 |
2696 // Save 1 in xmm3 - we need this several times later on. | 2666 // Save 1 in xmm3 - we need this several times later on. |
2697 __ mov(ecx, Immediate(1)); | 2667 __ mov(ecx, Immediate(1)); |
2698 __ cvtsi2sd(xmm3, Operand(ecx)); | 2668 __ cvtsi2sd(xmm3, Operand(ecx)); |
2699 | 2669 |
2700 Label exponent_nonsmi; | 2670 Label exponent_nonsmi; |
2701 Label base_nonsmi; | 2671 Label base_nonsmi; |
2702 // If the exponent is a heap number go to that specific case. | 2672 // If the exponent is a heap number go to that specific case. |
2703 __ test(eax, Immediate(kSmiTagMask)); | 2673 __ JumpIfNotSmi(eax, &exponent_nonsmi); |
2704 __ j(not_zero, &exponent_nonsmi); | 2674 __ JumpIfNotSmi(edx, &base_nonsmi); |
2705 __ test(edx, Immediate(kSmiTagMask)); | |
2706 __ j(not_zero, &base_nonsmi); | |
2707 | 2675 |
2708 // Optimized version when both exponent and base are smis. | 2676 // Optimized version when both exponent and base are smis. |
2709 Label powi; | 2677 Label powi; |
2710 __ SmiUntag(edx); | 2678 __ SmiUntag(edx); |
2711 __ cvtsi2sd(xmm0, Operand(edx)); | 2679 __ cvtsi2sd(xmm0, Operand(edx)); |
2712 __ jmp(&powi); | 2680 __ jmp(&powi); |
2713 // exponent is smi and base is a heapnumber. | 2681 // exponent is smi and base is a heapnumber. |
2714 __ bind(&base_nonsmi); | 2682 __ bind(&base_nonsmi); |
2715 Factory* factory = masm->isolate()->factory(); | 2683 Factory* factory = masm->isolate()->factory(); |
2716 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), | 2684 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2768 __ cmp(FieldOperand(eax, HeapObject::kMapOffset), | 2736 __ cmp(FieldOperand(eax, HeapObject::kMapOffset), |
2769 factory->heap_number_map()); | 2737 factory->heap_number_map()); |
2770 __ j(not_equal, &call_runtime); | 2738 __ j(not_equal, &call_runtime); |
2771 __ movdbl(xmm1, FieldOperand(eax, HeapNumber::kValueOffset)); | 2739 __ movdbl(xmm1, FieldOperand(eax, HeapNumber::kValueOffset)); |
2772 // Test if exponent is nan. | 2740 // Test if exponent is nan. |
2773 __ ucomisd(xmm1, xmm1); | 2741 __ ucomisd(xmm1, xmm1); |
2774 __ j(parity_even, &call_runtime); | 2742 __ j(parity_even, &call_runtime); |
2775 | 2743 |
2776 Label base_not_smi; | 2744 Label base_not_smi; |
2777 Label handle_special_cases; | 2745 Label handle_special_cases; |
2778 __ test(edx, Immediate(kSmiTagMask)); | 2746 __ JumpIfNotSmi(edx, &base_not_smi, Label::kNear); |
2779 __ j(not_zero, &base_not_smi, Label::kNear); | |
2780 __ SmiUntag(edx); | 2747 __ SmiUntag(edx); |
2781 __ cvtsi2sd(xmm0, Operand(edx)); | 2748 __ cvtsi2sd(xmm0, Operand(edx)); |
2782 __ jmp(&handle_special_cases, Label::kNear); | 2749 __ jmp(&handle_special_cases, Label::kNear); |
2783 | 2750 |
2784 __ bind(&base_not_smi); | 2751 __ bind(&base_not_smi); |
2785 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), | 2752 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), |
2786 factory->heap_number_map()); | 2753 factory->heap_number_map()); |
2787 __ j(not_equal, &call_runtime); | 2754 __ j(not_equal, &call_runtime); |
2788 __ mov(ecx, FieldOperand(edx, HeapNumber::kExponentOffset)); | 2755 __ mov(ecx, FieldOperand(edx, HeapNumber::kExponentOffset)); |
2789 __ and_(ecx, HeapNumber::kExponentMask); | 2756 __ and_(ecx, HeapNumber::kExponentMask); |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2841 void ArgumentsAccessStub::GenerateReadElement(MacroAssembler* masm) { | 2808 void ArgumentsAccessStub::GenerateReadElement(MacroAssembler* masm) { |
2842 // The key is in edx and the parameter count is in eax. | 2809 // The key is in edx and the parameter count is in eax. |
2843 | 2810 |
2844 // The displacement is used for skipping the frame pointer on the | 2811 // The displacement is used for skipping the frame pointer on the |
2845 // stack. It is the offset of the last parameter (if any) relative | 2812 // stack. It is the offset of the last parameter (if any) relative |
2846 // to the frame pointer. | 2813 // to the frame pointer. |
2847 static const int kDisplacement = 1 * kPointerSize; | 2814 static const int kDisplacement = 1 * kPointerSize; |
2848 | 2815 |
2849 // Check that the key is a smi. | 2816 // Check that the key is a smi. |
2850 Label slow; | 2817 Label slow; |
2851 __ test(edx, Immediate(kSmiTagMask)); | 2818 __ JumpIfNotSmi(edx, &slow); |
2852 __ j(not_zero, &slow); | |
2853 | 2819 |
2854 // Check if the calling frame is an arguments adaptor frame. | 2820 // Check if the calling frame is an arguments adaptor frame. |
2855 Label adaptor; | 2821 Label adaptor; |
2856 __ mov(ebx, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); | 2822 __ mov(ebx, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); |
2857 __ mov(ecx, Operand(ebx, StandardFrameConstants::kContextOffset)); | 2823 __ mov(ecx, Operand(ebx, StandardFrameConstants::kContextOffset)); |
2858 __ cmp(Operand(ecx), Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); | 2824 __ cmp(Operand(ecx), Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); |
2859 __ j(equal, &adaptor, Label::kNear); | 2825 __ j(equal, &adaptor, Label::kNear); |
2860 | 2826 |
2861 // Check index against formal parameters count limit passed in | 2827 // Check index against formal parameters count limit passed in |
2862 // through register eax. Use unsigned comparison to get negative | 2828 // through register eax. Use unsigned comparison to get negative |
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3039 masm->isolate()); | 3005 masm->isolate()); |
3040 ExternalReference address_of_regexp_stack_memory_size = | 3006 ExternalReference address_of_regexp_stack_memory_size = |
3041 ExternalReference::address_of_regexp_stack_memory_size(masm->isolate()); | 3007 ExternalReference::address_of_regexp_stack_memory_size(masm->isolate()); |
3042 __ mov(ebx, Operand::StaticVariable(address_of_regexp_stack_memory_size)); | 3008 __ mov(ebx, Operand::StaticVariable(address_of_regexp_stack_memory_size)); |
3043 __ test(ebx, Operand(ebx)); | 3009 __ test(ebx, Operand(ebx)); |
3044 __ j(zero, &runtime); | 3010 __ j(zero, &runtime); |
3045 | 3011 |
3046 // Check that the first argument is a JSRegExp object. | 3012 // Check that the first argument is a JSRegExp object. |
3047 __ mov(eax, Operand(esp, kJSRegExpOffset)); | 3013 __ mov(eax, Operand(esp, kJSRegExpOffset)); |
3048 STATIC_ASSERT(kSmiTag == 0); | 3014 STATIC_ASSERT(kSmiTag == 0); |
3049 __ test(eax, Immediate(kSmiTagMask)); | 3015 __ JumpIfSmi(eax, &runtime); |
3050 __ j(zero, &runtime); | |
3051 __ CmpObjectType(eax, JS_REGEXP_TYPE, ecx); | 3016 __ CmpObjectType(eax, JS_REGEXP_TYPE, ecx); |
3052 __ j(not_equal, &runtime); | 3017 __ j(not_equal, &runtime); |
3053 // Check that the RegExp has been compiled (data contains a fixed array). | 3018 // Check that the RegExp has been compiled (data contains a fixed array). |
3054 __ mov(ecx, FieldOperand(eax, JSRegExp::kDataOffset)); | 3019 __ mov(ecx, FieldOperand(eax, JSRegExp::kDataOffset)); |
3055 if (FLAG_debug_code) { | 3020 if (FLAG_debug_code) { |
3056 __ test(ecx, Immediate(kSmiTagMask)); | 3021 __ test(ecx, Immediate(kSmiTagMask)); |
3057 __ Check(not_zero, "Unexpected type for RegExp data, FixedArray expected"); | 3022 __ Check(not_zero, "Unexpected type for RegExp data, FixedArray expected"); |
3058 __ CmpObjectType(ecx, FIXED_ARRAY_TYPE, ebx); | 3023 __ CmpObjectType(ecx, FIXED_ARRAY_TYPE, ebx); |
3059 __ Check(equal, "Unexpected type for RegExp data, FixedArray expected"); | 3024 __ Check(equal, "Unexpected type for RegExp data, FixedArray expected"); |
3060 } | 3025 } |
(...skipping 13 matching lines...) Expand all Loading... |
3074 STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 1); | 3039 STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 1); |
3075 __ add(Operand(edx), Immediate(2)); // edx was a smi. | 3040 __ add(Operand(edx), Immediate(2)); // edx was a smi. |
3076 // Check that the static offsets vector buffer is large enough. | 3041 // Check that the static offsets vector buffer is large enough. |
3077 __ cmp(edx, OffsetsVector::kStaticOffsetsVectorSize); | 3042 __ cmp(edx, OffsetsVector::kStaticOffsetsVectorSize); |
3078 __ j(above, &runtime); | 3043 __ j(above, &runtime); |
3079 | 3044 |
3080 // ecx: RegExp data (FixedArray) | 3045 // ecx: RegExp data (FixedArray) |
3081 // edx: Number of capture registers | 3046 // edx: Number of capture registers |
3082 // Check that the second argument is a string. | 3047 // Check that the second argument is a string. |
3083 __ mov(eax, Operand(esp, kSubjectOffset)); | 3048 __ mov(eax, Operand(esp, kSubjectOffset)); |
3084 __ test(eax, Immediate(kSmiTagMask)); | 3049 __ JumpIfSmi(eax, &runtime); |
3085 __ j(zero, &runtime); | |
3086 Condition is_string = masm->IsObjectStringType(eax, ebx, ebx); | 3050 Condition is_string = masm->IsObjectStringType(eax, ebx, ebx); |
3087 __ j(NegateCondition(is_string), &runtime); | 3051 __ j(NegateCondition(is_string), &runtime); |
3088 // Get the length of the string to ebx. | 3052 // Get the length of the string to ebx. |
3089 __ mov(ebx, FieldOperand(eax, String::kLengthOffset)); | 3053 __ mov(ebx, FieldOperand(eax, String::kLengthOffset)); |
3090 | 3054 |
3091 // ebx: Length of subject string as a smi | 3055 // ebx: Length of subject string as a smi |
3092 // ecx: RegExp data (FixedArray) | 3056 // ecx: RegExp data (FixedArray) |
3093 // edx: Number of capture registers | 3057 // edx: Number of capture registers |
3094 // Check that the third argument is a positive smi less than the subject | 3058 // Check that the third argument is a positive smi less than the subject |
3095 // string length. A negative value will be greater (unsigned comparison). | 3059 // string length. A negative value will be greater (unsigned comparison). |
3096 __ mov(eax, Operand(esp, kPreviousIndexOffset)); | 3060 __ mov(eax, Operand(esp, kPreviousIndexOffset)); |
3097 __ test(eax, Immediate(kSmiTagMask)); | 3061 __ JumpIfNotSmi(eax, &runtime); |
3098 __ j(not_zero, &runtime); | |
3099 __ cmp(eax, Operand(ebx)); | 3062 __ cmp(eax, Operand(ebx)); |
3100 __ j(above_equal, &runtime); | 3063 __ j(above_equal, &runtime); |
3101 | 3064 |
3102 // ecx: RegExp data (FixedArray) | 3065 // ecx: RegExp data (FixedArray) |
3103 // edx: Number of capture registers | 3066 // edx: Number of capture registers |
3104 // Check that the fourth object is a JSArray object. | 3067 // Check that the fourth object is a JSArray object. |
3105 __ mov(eax, Operand(esp, kLastMatchInfoOffset)); | 3068 __ mov(eax, Operand(esp, kLastMatchInfoOffset)); |
3106 __ test(eax, Immediate(kSmiTagMask)); | 3069 __ JumpIfSmi(eax, &runtime); |
3107 __ j(zero, &runtime); | |
3108 __ CmpObjectType(eax, JS_ARRAY_TYPE, ebx); | 3070 __ CmpObjectType(eax, JS_ARRAY_TYPE, ebx); |
3109 __ j(not_equal, &runtime); | 3071 __ j(not_equal, &runtime); |
3110 // Check that the JSArray is in fast case. | 3072 // Check that the JSArray is in fast case. |
3111 __ mov(ebx, FieldOperand(eax, JSArray::kElementsOffset)); | 3073 __ mov(ebx, FieldOperand(eax, JSArray::kElementsOffset)); |
3112 __ mov(eax, FieldOperand(ebx, HeapObject::kMapOffset)); | 3074 __ mov(eax, FieldOperand(ebx, HeapObject::kMapOffset)); |
3113 Factory* factory = masm->isolate()->factory(); | 3075 Factory* factory = masm->isolate()->factory(); |
3114 __ cmp(eax, factory->fixed_array_map()); | 3076 __ cmp(eax, factory->fixed_array_map()); |
3115 __ j(not_equal, &runtime); | 3077 __ j(not_equal, &runtime); |
3116 // Check that the last match info has space for the capture registers and the | 3078 // Check that the last match info has space for the capture registers and the |
3117 // additional information. | 3079 // additional information. |
(...skipping 251 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3369 __ TailCallRuntime(Runtime::kRegExpExec, 4, 1); | 3331 __ TailCallRuntime(Runtime::kRegExpExec, 4, 1); |
3370 #endif // V8_INTERPRETED_REGEXP | 3332 #endif // V8_INTERPRETED_REGEXP |
3371 } | 3333 } |
3372 | 3334 |
3373 | 3335 |
3374 void RegExpConstructResultStub::Generate(MacroAssembler* masm) { | 3336 void RegExpConstructResultStub::Generate(MacroAssembler* masm) { |
3375 const int kMaxInlineLength = 100; | 3337 const int kMaxInlineLength = 100; |
3376 Label slowcase; | 3338 Label slowcase; |
3377 Label done; | 3339 Label done; |
3378 __ mov(ebx, Operand(esp, kPointerSize * 3)); | 3340 __ mov(ebx, Operand(esp, kPointerSize * 3)); |
3379 __ test(ebx, Immediate(kSmiTagMask)); | 3341 __ JumpIfNotSmi(ebx, &slowcase); |
3380 __ j(not_zero, &slowcase); | |
3381 __ cmp(Operand(ebx), Immediate(Smi::FromInt(kMaxInlineLength))); | 3342 __ cmp(Operand(ebx), Immediate(Smi::FromInt(kMaxInlineLength))); |
3382 __ j(above, &slowcase); | 3343 __ j(above, &slowcase); |
3383 // Smi-tagging is equivalent to multiplying by 2. | 3344 // Smi-tagging is equivalent to multiplying by 2. |
3384 STATIC_ASSERT(kSmiTag == 0); | 3345 STATIC_ASSERT(kSmiTag == 0); |
3385 STATIC_ASSERT(kSmiTagSize == 1); | 3346 STATIC_ASSERT(kSmiTagSize == 1); |
3386 // Allocate RegExpResult followed by FixedArray with size in ebx. | 3347 // Allocate RegExpResult followed by FixedArray with size in ebx. |
3387 // JSArray: [Map][empty properties][Elements][Length-smi][index][input] | 3348 // JSArray: [Map][empty properties][Elements][Length-smi][index][input] |
3388 // Elements: [Map][Length][..elements..] | 3349 // Elements: [Map][Length][..elements..] |
3389 __ AllocateInNewSpace(JSRegExpResult::kSize + FixedArray::kHeaderSize, | 3350 __ AllocateInNewSpace(JSRegExpResult::kSize + FixedArray::kHeaderSize, |
3390 times_half_pointer_size, | 3351 times_half_pointer_size, |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3482 // doubles is the xor of the upper and lower words. See | 3443 // doubles is the xor of the upper and lower words. See |
3483 // Heap::GetNumberStringCache. | 3444 // Heap::GetNumberStringCache. |
3484 Label smi_hash_calculated; | 3445 Label smi_hash_calculated; |
3485 Label load_result_from_cache; | 3446 Label load_result_from_cache; |
3486 if (object_is_smi) { | 3447 if (object_is_smi) { |
3487 __ mov(scratch, object); | 3448 __ mov(scratch, object); |
3488 __ SmiUntag(scratch); | 3449 __ SmiUntag(scratch); |
3489 } else { | 3450 } else { |
3490 Label not_smi; | 3451 Label not_smi; |
3491 STATIC_ASSERT(kSmiTag == 0); | 3452 STATIC_ASSERT(kSmiTag == 0); |
3492 __ test(object, Immediate(kSmiTagMask)); | 3453 __ JumpIfNotSmi(object, ¬_smi, Label::kNear); |
3493 __ j(not_zero, ¬_smi, Label::kNear); | |
3494 __ mov(scratch, object); | 3454 __ mov(scratch, object); |
3495 __ SmiUntag(scratch); | 3455 __ SmiUntag(scratch); |
3496 __ jmp(&smi_hash_calculated, Label::kNear); | 3456 __ jmp(&smi_hash_calculated, Label::kNear); |
3497 __ bind(¬_smi); | 3457 __ bind(¬_smi); |
3498 __ cmp(FieldOperand(object, HeapObject::kMapOffset), | 3458 __ cmp(FieldOperand(object, HeapObject::kMapOffset), |
3499 masm->isolate()->factory()->heap_number_map()); | 3459 masm->isolate()->factory()->heap_number_map()); |
3500 __ j(not_equal, not_found); | 3460 __ j(not_equal, not_found); |
3501 STATIC_ASSERT(8 == kDoubleSize); | 3461 STATIC_ASSERT(8 == kDoubleSize); |
3502 __ mov(scratch, FieldOperand(object, HeapNumber::kValueOffset)); | 3462 __ mov(scratch, FieldOperand(object, HeapNumber::kValueOffset)); |
3503 __ xor_(scratch, FieldOperand(object, HeapNumber::kValueOffset + 4)); | 3463 __ xor_(scratch, FieldOperand(object, HeapNumber::kValueOffset + 4)); |
3504 // Object is heap number and hash is now in scratch. Calculate cache index. | 3464 // Object is heap number and hash is now in scratch. Calculate cache index. |
3505 __ and_(scratch, Operand(mask)); | 3465 __ and_(scratch, Operand(mask)); |
3506 Register index = scratch; | 3466 Register index = scratch; |
3507 Register probe = mask; | 3467 Register probe = mask; |
3508 __ mov(probe, | 3468 __ mov(probe, |
3509 FieldOperand(number_string_cache, | 3469 FieldOperand(number_string_cache, |
3510 index, | 3470 index, |
3511 times_twice_pointer_size, | 3471 times_twice_pointer_size, |
3512 FixedArray::kHeaderSize)); | 3472 FixedArray::kHeaderSize)); |
3513 __ test(probe, Immediate(kSmiTagMask)); | 3473 __ JumpIfSmi(probe, not_found); |
3514 __ j(zero, not_found); | |
3515 if (CpuFeatures::IsSupported(SSE2)) { | 3474 if (CpuFeatures::IsSupported(SSE2)) { |
3516 CpuFeatures::Scope fscope(SSE2); | 3475 CpuFeatures::Scope fscope(SSE2); |
3517 __ movdbl(xmm0, FieldOperand(object, HeapNumber::kValueOffset)); | 3476 __ movdbl(xmm0, FieldOperand(object, HeapNumber::kValueOffset)); |
3518 __ movdbl(xmm1, FieldOperand(probe, HeapNumber::kValueOffset)); | 3477 __ movdbl(xmm1, FieldOperand(probe, HeapNumber::kValueOffset)); |
3519 __ ucomisd(xmm0, xmm1); | 3478 __ ucomisd(xmm0, xmm1); |
3520 } else { | 3479 } else { |
3521 __ fld_d(FieldOperand(object, HeapNumber::kValueOffset)); | 3480 __ fld_d(FieldOperand(object, HeapNumber::kValueOffset)); |
3522 __ fld_d(FieldOperand(probe, HeapNumber::kValueOffset)); | 3481 __ fld_d(FieldOperand(probe, HeapNumber::kValueOffset)); |
3523 __ FCmp(); | 3482 __ FCmp(); |
3524 } | 3483 } |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3576 void CompareStub::Generate(MacroAssembler* masm) { | 3535 void CompareStub::Generate(MacroAssembler* masm) { |
3577 ASSERT(lhs_.is(no_reg) && rhs_.is(no_reg)); | 3536 ASSERT(lhs_.is(no_reg) && rhs_.is(no_reg)); |
3578 | 3537 |
3579 Label check_unequal_objects, done; | 3538 Label check_unequal_objects, done; |
3580 | 3539 |
3581 // Compare two smis if required. | 3540 // Compare two smis if required. |
3582 if (include_smi_compare_) { | 3541 if (include_smi_compare_) { |
3583 Label non_smi, smi_done; | 3542 Label non_smi, smi_done; |
3584 __ mov(ecx, Operand(edx)); | 3543 __ mov(ecx, Operand(edx)); |
3585 __ or_(ecx, Operand(eax)); | 3544 __ or_(ecx, Operand(eax)); |
3586 __ test(ecx, Immediate(kSmiTagMask)); | 3545 __ JumpIfNotSmi(ecx, &non_smi); |
3587 __ j(not_zero, &non_smi); | |
3588 __ sub(edx, Operand(eax)); // Return on the result of the subtraction. | 3546 __ sub(edx, Operand(eax)); // Return on the result of the subtraction. |
3589 __ j(no_overflow, &smi_done); | 3547 __ j(no_overflow, &smi_done); |
3590 __ not_(edx); // Correct sign in case of overflow. edx is never 0 here. | 3548 __ not_(edx); // Correct sign in case of overflow. edx is never 0 here. |
3591 __ bind(&smi_done); | 3549 __ bind(&smi_done); |
3592 __ mov(eax, edx); | 3550 __ mov(eax, edx); |
3593 __ ret(0); | 3551 __ ret(0); |
3594 __ bind(&non_smi); | 3552 __ bind(&non_smi); |
3595 } else if (FLAG_debug_code) { | 3553 } else if (FLAG_debug_code) { |
3596 __ mov(ecx, Operand(edx)); | 3554 __ mov(ecx, Operand(edx)); |
3597 __ or_(ecx, Operand(eax)); | 3555 __ or_(ecx, Operand(eax)); |
(...skipping 305 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3903 // Call the native; it returns -1 (less), 0 (equal), or 1 (greater) | 3861 // Call the native; it returns -1 (less), 0 (equal), or 1 (greater) |
3904 // tagged as a small integer. | 3862 // tagged as a small integer. |
3905 __ InvokeBuiltin(builtin, JUMP_FUNCTION); | 3863 __ InvokeBuiltin(builtin, JUMP_FUNCTION); |
3906 } | 3864 } |
3907 | 3865 |
3908 | 3866 |
3909 void CompareStub::BranchIfNonSymbol(MacroAssembler* masm, | 3867 void CompareStub::BranchIfNonSymbol(MacroAssembler* masm, |
3910 Label* label, | 3868 Label* label, |
3911 Register object, | 3869 Register object, |
3912 Register scratch) { | 3870 Register scratch) { |
3913 __ test(object, Immediate(kSmiTagMask)); | 3871 __ JumpIfSmi(object, label); |
3914 __ j(zero, label); | |
3915 __ mov(scratch, FieldOperand(object, HeapObject::kMapOffset)); | 3872 __ mov(scratch, FieldOperand(object, HeapObject::kMapOffset)); |
3916 __ movzx_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset)); | 3873 __ movzx_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset)); |
3917 __ and_(scratch, kIsSymbolMask | kIsNotStringMask); | 3874 __ and_(scratch, kIsSymbolMask | kIsNotStringMask); |
3918 __ cmp(scratch, kSymbolTag | kStringTag); | 3875 __ cmp(scratch, kSymbolTag | kStringTag); |
3919 __ j(not_equal, label); | 3876 __ j(not_equal, label); |
3920 } | 3877 } |
3921 | 3878 |
3922 | 3879 |
3923 void StackCheckStub::Generate(MacroAssembler* masm) { | 3880 void StackCheckStub::Generate(MacroAssembler* masm) { |
3924 __ TailCallRuntime(Runtime::kStackGuard, 0, 1); | 3881 __ TailCallRuntime(Runtime::kStackGuard, 0, 1); |
(...skipping 19 matching lines...) Expand all Loading... |
3944 __ mov(ebx, FieldOperand(ebx, GlobalObject::kGlobalReceiverOffset)); | 3901 __ mov(ebx, FieldOperand(ebx, GlobalObject::kGlobalReceiverOffset)); |
3945 __ mov(Operand(esp, (argc_ + 1) * kPointerSize), ebx); | 3902 __ mov(Operand(esp, (argc_ + 1) * kPointerSize), ebx); |
3946 __ bind(&call); | 3903 __ bind(&call); |
3947 } | 3904 } |
3948 | 3905 |
3949 // Get the function to call from the stack. | 3906 // Get the function to call from the stack. |
3950 // +2 ~ receiver, return address | 3907 // +2 ~ receiver, return address |
3951 __ mov(edi, Operand(esp, (argc_ + 2) * kPointerSize)); | 3908 __ mov(edi, Operand(esp, (argc_ + 2) * kPointerSize)); |
3952 | 3909 |
3953 // Check that the function really is a JavaScript function. | 3910 // Check that the function really is a JavaScript function. |
3954 __ test(edi, Immediate(kSmiTagMask)); | 3911 __ JumpIfSmi(edi, &slow); |
3955 __ j(zero, &slow); | |
3956 // Goto slow case if we do not have a function. | 3912 // Goto slow case if we do not have a function. |
3957 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx); | 3913 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx); |
3958 __ j(not_equal, &slow); | 3914 __ j(not_equal, &slow); |
3959 | 3915 |
3960 // Fast-case: Just invoke the function. | 3916 // Fast-case: Just invoke the function. |
3961 ParameterCount actual(argc_); | 3917 ParameterCount actual(argc_); |
3962 | 3918 |
3963 if (ReceiverMightBeImplicit()) { | 3919 if (ReceiverMightBeImplicit()) { |
3964 Label call_as_function; | 3920 Label call_as_function; |
3965 __ cmp(eax, masm->isolate()->factory()->the_hole_value()); | 3921 __ cmp(eax, masm->isolate()->factory()->the_hole_value()); |
(...skipping 378 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4344 ASSERT_EQ(function.code(), InstanceofStub::right().code()); | 4300 ASSERT_EQ(function.code(), InstanceofStub::right().code()); |
4345 | 4301 |
4346 // Get the object and function - they are always both needed. | 4302 // Get the object and function - they are always both needed. |
4347 Label slow, not_js_object; | 4303 Label slow, not_js_object; |
4348 if (!HasArgsInRegisters()) { | 4304 if (!HasArgsInRegisters()) { |
4349 __ mov(object, Operand(esp, 2 * kPointerSize)); | 4305 __ mov(object, Operand(esp, 2 * kPointerSize)); |
4350 __ mov(function, Operand(esp, 1 * kPointerSize)); | 4306 __ mov(function, Operand(esp, 1 * kPointerSize)); |
4351 } | 4307 } |
4352 | 4308 |
4353 // Check that the left hand is a JS object. | 4309 // Check that the left hand is a JS object. |
4354 __ test(object, Immediate(kSmiTagMask)); | 4310 __ JumpIfSmi(object, ¬_js_object); |
4355 __ j(zero, ¬_js_object); | |
4356 __ IsObjectJSObjectType(object, map, scratch, ¬_js_object); | 4311 __ IsObjectJSObjectType(object, map, scratch, ¬_js_object); |
4357 | 4312 |
4358 // If there is a call site cache don't look in the global cache, but do the | 4313 // If there is a call site cache don't look in the global cache, but do the |
4359 // real lookup and update the call site cache. | 4314 // real lookup and update the call site cache. |
4360 if (!HasCallSiteInlineCheck()) { | 4315 if (!HasCallSiteInlineCheck()) { |
4361 // Look up the function and the map in the instanceof cache. | 4316 // Look up the function and the map in the instanceof cache. |
4362 Label miss; | 4317 Label miss; |
4363 __ mov(scratch, Immediate(Heap::kInstanceofCacheFunctionRootIndex)); | 4318 __ mov(scratch, Immediate(Heap::kInstanceofCacheFunctionRootIndex)); |
4364 __ cmp(function, | 4319 __ cmp(function, |
4365 Operand::StaticArray(scratch, times_pointer_size, roots_address)); | 4320 Operand::StaticArray(scratch, times_pointer_size, roots_address)); |
4366 __ j(not_equal, &miss, Label::kNear); | 4321 __ j(not_equal, &miss, Label::kNear); |
4367 __ mov(scratch, Immediate(Heap::kInstanceofCacheMapRootIndex)); | 4322 __ mov(scratch, Immediate(Heap::kInstanceofCacheMapRootIndex)); |
4368 __ cmp(map, Operand::StaticArray( | 4323 __ cmp(map, Operand::StaticArray( |
4369 scratch, times_pointer_size, roots_address)); | 4324 scratch, times_pointer_size, roots_address)); |
4370 __ j(not_equal, &miss, Label::kNear); | 4325 __ j(not_equal, &miss, Label::kNear); |
4371 __ mov(scratch, Immediate(Heap::kInstanceofCacheAnswerRootIndex)); | 4326 __ mov(scratch, Immediate(Heap::kInstanceofCacheAnswerRootIndex)); |
4372 __ mov(eax, Operand::StaticArray( | 4327 __ mov(eax, Operand::StaticArray( |
4373 scratch, times_pointer_size, roots_address)); | 4328 scratch, times_pointer_size, roots_address)); |
4374 __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize); | 4329 __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize); |
4375 __ bind(&miss); | 4330 __ bind(&miss); |
4376 } | 4331 } |
4377 | 4332 |
4378 // Get the prototype of the function. | 4333 // Get the prototype of the function. |
4379 __ TryGetFunctionPrototype(function, prototype, scratch, &slow); | 4334 __ TryGetFunctionPrototype(function, prototype, scratch, &slow); |
4380 | 4335 |
4381 // Check that the function prototype is a JS object. | 4336 // Check that the function prototype is a JS object. |
4382 __ test(prototype, Immediate(kSmiTagMask)); | 4337 __ JumpIfSmi(prototype, &slow); |
4383 __ j(zero, &slow); | |
4384 __ IsObjectJSObjectType(prototype, scratch, scratch, &slow); | 4338 __ IsObjectJSObjectType(prototype, scratch, scratch, &slow); |
4385 | 4339 |
4386 // Update the global instanceof or call site inlined cache with the current | 4340 // Update the global instanceof or call site inlined cache with the current |
4387 // map and function. The cached answer will be set when it is known below. | 4341 // map and function. The cached answer will be set when it is known below. |
4388 if (!HasCallSiteInlineCheck()) { | 4342 if (!HasCallSiteInlineCheck()) { |
4389 __ mov(scratch, Immediate(Heap::kInstanceofCacheMapRootIndex)); | 4343 __ mov(scratch, Immediate(Heap::kInstanceofCacheMapRootIndex)); |
4390 __ mov(Operand::StaticArray(scratch, times_pointer_size, roots_address), map); | 4344 __ mov(Operand::StaticArray(scratch, times_pointer_size, roots_address), map); |
4391 __ mov(scratch, Immediate(Heap::kInstanceofCacheFunctionRootIndex)); | 4345 __ mov(scratch, Immediate(Heap::kInstanceofCacheFunctionRootIndex)); |
4392 __ mov(Operand::StaticArray(scratch, times_pointer_size, roots_address), | 4346 __ mov(Operand::StaticArray(scratch, times_pointer_size, roots_address), |
4393 function); | 4347 function); |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4462 if (!ReturnTrueFalseObject()) { | 4416 if (!ReturnTrueFalseObject()) { |
4463 __ Set(eax, Immediate(Smi::FromInt(1))); | 4417 __ Set(eax, Immediate(Smi::FromInt(1))); |
4464 } | 4418 } |
4465 } | 4419 } |
4466 __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize); | 4420 __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize); |
4467 | 4421 |
4468 Label object_not_null, object_not_null_or_smi; | 4422 Label object_not_null, object_not_null_or_smi; |
4469 __ bind(¬_js_object); | 4423 __ bind(¬_js_object); |
4470 // Before null, smi and string value checks, check that the rhs is a function | 4424 // Before null, smi and string value checks, check that the rhs is a function |
4471 // as for a non-function rhs an exception needs to be thrown. | 4425 // as for a non-function rhs an exception needs to be thrown. |
4472 __ test(function, Immediate(kSmiTagMask)); | 4426 __ JumpIfSmi(function, &slow); |
4473 __ j(zero, &slow); | |
4474 __ CmpObjectType(function, JS_FUNCTION_TYPE, scratch); | 4427 __ CmpObjectType(function, JS_FUNCTION_TYPE, scratch); |
4475 __ j(not_equal, &slow); | 4428 __ j(not_equal, &slow); |
4476 | 4429 |
4477 // Null is not instance of anything. | 4430 // Null is not instance of anything. |
4478 __ cmp(object, factory->null_value()); | 4431 __ cmp(object, factory->null_value()); |
4479 __ j(not_equal, &object_not_null); | 4432 __ j(not_equal, &object_not_null); |
4480 __ Set(eax, Immediate(Smi::FromInt(1))); | 4433 __ Set(eax, Immediate(Smi::FromInt(1))); |
4481 __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize); | 4434 __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize); |
4482 | 4435 |
4483 __ bind(&object_not_null); | 4436 __ bind(&object_not_null); |
4484 // Smi values is not instance of anything. | 4437 // Smi values is not instance of anything. |
4485 __ test(object, Immediate(kSmiTagMask)); | 4438 __ JumpIfNotSmi(object, &object_not_null_or_smi); |
4486 __ j(not_zero, &object_not_null_or_smi); | |
4487 __ Set(eax, Immediate(Smi::FromInt(1))); | 4439 __ Set(eax, Immediate(Smi::FromInt(1))); |
4488 __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize); | 4440 __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize); |
4489 | 4441 |
4490 __ bind(&object_not_null_or_smi); | 4442 __ bind(&object_not_null_or_smi); |
4491 // String values is not instance of anything. | 4443 // String values is not instance of anything. |
4492 Condition is_string = masm->IsObjectStringType(object, scratch, scratch); | 4444 Condition is_string = masm->IsObjectStringType(object, scratch, scratch); |
4493 __ j(NegateCondition(is_string), &slow); | 4445 __ j(NegateCondition(is_string), &slow); |
4494 __ Set(eax, Immediate(Smi::FromInt(1))); | 4446 __ Set(eax, Immediate(Smi::FromInt(1))); |
4495 __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize); | 4447 __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize); |
4496 | 4448 |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4603 // ------------------------------------------------------------------------- | 4555 // ------------------------------------------------------------------------- |
4604 // StringCharCodeAtGenerator | 4556 // StringCharCodeAtGenerator |
4605 | 4557 |
4606 void StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) { | 4558 void StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) { |
4607 Label flat_string; | 4559 Label flat_string; |
4608 Label ascii_string; | 4560 Label ascii_string; |
4609 Label got_char_code; | 4561 Label got_char_code; |
4610 | 4562 |
4611 // If the receiver is a smi trigger the non-string case. | 4563 // If the receiver is a smi trigger the non-string case. |
4612 STATIC_ASSERT(kSmiTag == 0); | 4564 STATIC_ASSERT(kSmiTag == 0); |
4613 __ test(object_, Immediate(kSmiTagMask)); | 4565 __ JumpIfSmi(object_, receiver_not_string_); |
4614 __ j(zero, receiver_not_string_); | |
4615 | 4566 |
4616 // Fetch the instance type of the receiver into result register. | 4567 // Fetch the instance type of the receiver into result register. |
4617 __ mov(result_, FieldOperand(object_, HeapObject::kMapOffset)); | 4568 __ mov(result_, FieldOperand(object_, HeapObject::kMapOffset)); |
4618 __ movzx_b(result_, FieldOperand(result_, Map::kInstanceTypeOffset)); | 4569 __ movzx_b(result_, FieldOperand(result_, Map::kInstanceTypeOffset)); |
4619 // If the receiver is not a string trigger the non-string case. | 4570 // If the receiver is not a string trigger the non-string case. |
4620 __ test(result_, Immediate(kIsNotStringMask)); | 4571 __ test(result_, Immediate(kIsNotStringMask)); |
4621 __ j(not_zero, receiver_not_string_); | 4572 __ j(not_zero, receiver_not_string_); |
4622 | 4573 |
4623 // If the index is non-smi trigger the non-smi case. | 4574 // If the index is non-smi trigger the non-smi case. |
4624 STATIC_ASSERT(kSmiTag == 0); | 4575 STATIC_ASSERT(kSmiTag == 0); |
4625 __ test(index_, Immediate(kSmiTagMask)); | 4576 __ JumpIfNotSmi(index_, &index_not_smi_); |
4626 __ j(not_zero, &index_not_smi_); | |
4627 | 4577 |
4628 // Put smi-tagged index into scratch register. | 4578 // Put smi-tagged index into scratch register. |
4629 __ mov(scratch_, index_); | 4579 __ mov(scratch_, index_); |
4630 __ bind(&got_smi_index_); | 4580 __ bind(&got_smi_index_); |
4631 | 4581 |
4632 // Check for index out of range. | 4582 // Check for index out of range. |
4633 __ cmp(scratch_, FieldOperand(object_, String::kLengthOffset)); | 4583 __ cmp(scratch_, FieldOperand(object_, String::kLengthOffset)); |
4634 __ j(above_equal, index_out_of_range_); | 4584 __ j(above_equal, index_out_of_range_); |
4635 | 4585 |
4636 // We need special handling for non-flat strings. | 4586 // We need special handling for non-flat strings. |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4714 __ mov(scratch_, eax); | 4664 __ mov(scratch_, eax); |
4715 } | 4665 } |
4716 __ pop(index_); | 4666 __ pop(index_); |
4717 __ pop(object_); | 4667 __ pop(object_); |
4718 // Reload the instance type. | 4668 // Reload the instance type. |
4719 __ mov(result_, FieldOperand(object_, HeapObject::kMapOffset)); | 4669 __ mov(result_, FieldOperand(object_, HeapObject::kMapOffset)); |
4720 __ movzx_b(result_, FieldOperand(result_, Map::kInstanceTypeOffset)); | 4670 __ movzx_b(result_, FieldOperand(result_, Map::kInstanceTypeOffset)); |
4721 call_helper.AfterCall(masm); | 4671 call_helper.AfterCall(masm); |
4722 // If index is still not a smi, it must be out of range. | 4672 // If index is still not a smi, it must be out of range. |
4723 STATIC_ASSERT(kSmiTag == 0); | 4673 STATIC_ASSERT(kSmiTag == 0); |
4724 __ test(scratch_, Immediate(kSmiTagMask)); | 4674 __ JumpIfNotSmi(scratch_, index_out_of_range_); |
4725 __ j(not_zero, index_out_of_range_); | |
4726 // Otherwise, return to the fast path. | 4675 // Otherwise, return to the fast path. |
4727 __ jmp(&got_smi_index_); | 4676 __ jmp(&got_smi_index_); |
4728 | 4677 |
4729 // Call runtime. We get here when the receiver is a string and the | 4678 // Call runtime. We get here when the receiver is a string and the |
4730 // index is a number, but the code of getting the actual character | 4679 // index is a number, but the code of getting the actual character |
4731 // is too complex (e.g., when the string needs to be flattened). | 4680 // is too complex (e.g., when the string needs to be flattened). |
4732 __ bind(&call_runtime_); | 4681 __ bind(&call_runtime_); |
4733 call_helper.BeforeCall(masm); | 4682 call_helper.BeforeCall(masm); |
4734 __ push(object_); | 4683 __ push(object_); |
4735 __ push(index_); | 4684 __ push(index_); |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4809 void StringAddStub::Generate(MacroAssembler* masm) { | 4758 void StringAddStub::Generate(MacroAssembler* masm) { |
4810 Label string_add_runtime, call_builtin; | 4759 Label string_add_runtime, call_builtin; |
4811 Builtins::JavaScript builtin_id = Builtins::ADD; | 4760 Builtins::JavaScript builtin_id = Builtins::ADD; |
4812 | 4761 |
4813 // Load the two arguments. | 4762 // Load the two arguments. |
4814 __ mov(eax, Operand(esp, 2 * kPointerSize)); // First argument. | 4763 __ mov(eax, Operand(esp, 2 * kPointerSize)); // First argument. |
4815 __ mov(edx, Operand(esp, 1 * kPointerSize)); // Second argument. | 4764 __ mov(edx, Operand(esp, 1 * kPointerSize)); // Second argument. |
4816 | 4765 |
4817 // Make sure that both arguments are strings if not known in advance. | 4766 // Make sure that both arguments are strings if not known in advance. |
4818 if (flags_ == NO_STRING_ADD_FLAGS) { | 4767 if (flags_ == NO_STRING_ADD_FLAGS) { |
4819 __ test(eax, Immediate(kSmiTagMask)); | 4768 __ JumpIfSmi(eax, &string_add_runtime); |
4820 __ j(zero, &string_add_runtime); | |
4821 __ CmpObjectType(eax, FIRST_NONSTRING_TYPE, ebx); | 4769 __ CmpObjectType(eax, FIRST_NONSTRING_TYPE, ebx); |
4822 __ j(above_equal, &string_add_runtime); | 4770 __ j(above_equal, &string_add_runtime); |
4823 | 4771 |
4824 // First argument is a a string, test second. | 4772 // First argument is a a string, test second. |
4825 __ test(edx, Immediate(kSmiTagMask)); | 4773 __ JumpIfSmi(edx, &string_add_runtime); |
4826 __ j(zero, &string_add_runtime); | |
4827 __ CmpObjectType(edx, FIRST_NONSTRING_TYPE, ebx); | 4774 __ CmpObjectType(edx, FIRST_NONSTRING_TYPE, ebx); |
4828 __ j(above_equal, &string_add_runtime); | 4775 __ j(above_equal, &string_add_runtime); |
4829 } else { | 4776 } else { |
4830 // Here at least one of the arguments is definitely a string. | 4777 // Here at least one of the arguments is definitely a string. |
4831 // We convert the one that is not known to be a string. | 4778 // We convert the one that is not known to be a string. |
4832 if ((flags_ & NO_STRING_CHECK_LEFT_IN_STUB) == 0) { | 4779 if ((flags_ & NO_STRING_CHECK_LEFT_IN_STUB) == 0) { |
4833 ASSERT((flags_ & NO_STRING_CHECK_RIGHT_IN_STUB) != 0); | 4780 ASSERT((flags_ & NO_STRING_CHECK_RIGHT_IN_STUB) != 0); |
4834 GenerateConvertArgument(masm, 2 * kPointerSize, eax, ebx, ecx, edi, | 4781 GenerateConvertArgument(masm, 2 * kPointerSize, eax, ebx, ecx, edi, |
4835 &call_builtin); | 4782 &call_builtin); |
4836 builtin_id = Builtins::STRING_ADD_RIGHT; | 4783 builtin_id = Builtins::STRING_ADD_RIGHT; |
(...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5084 | 5031 |
5085 void StringAddStub::GenerateConvertArgument(MacroAssembler* masm, | 5032 void StringAddStub::GenerateConvertArgument(MacroAssembler* masm, |
5086 int stack_offset, | 5033 int stack_offset, |
5087 Register arg, | 5034 Register arg, |
5088 Register scratch1, | 5035 Register scratch1, |
5089 Register scratch2, | 5036 Register scratch2, |
5090 Register scratch3, | 5037 Register scratch3, |
5091 Label* slow) { | 5038 Label* slow) { |
5092 // First check if the argument is already a string. | 5039 // First check if the argument is already a string. |
5093 Label not_string, done; | 5040 Label not_string, done; |
5094 __ test(arg, Immediate(kSmiTagMask)); | 5041 __ JumpIfSmi(arg, ¬_string); |
5095 __ j(zero, ¬_string); | |
5096 __ CmpObjectType(arg, FIRST_NONSTRING_TYPE, scratch1); | 5042 __ CmpObjectType(arg, FIRST_NONSTRING_TYPE, scratch1); |
5097 __ j(below, &done); | 5043 __ j(below, &done); |
5098 | 5044 |
5099 // Check the number to string cache. | 5045 // Check the number to string cache. |
5100 Label not_cached; | 5046 Label not_cached; |
5101 __ bind(¬_string); | 5047 __ bind(¬_string); |
5102 // Puts the cached result into scratch1. | 5048 // Puts the cached result into scratch1. |
5103 NumberToStringStub::GenerateLookupNumberStringCache(masm, | 5049 NumberToStringStub::GenerateLookupNumberStringCache(masm, |
5104 arg, | 5050 arg, |
5105 scratch1, | 5051 scratch1, |
5106 scratch2, | 5052 scratch2, |
5107 scratch3, | 5053 scratch3, |
5108 false, | 5054 false, |
5109 ¬_cached); | 5055 ¬_cached); |
5110 __ mov(arg, scratch1); | 5056 __ mov(arg, scratch1); |
5111 __ mov(Operand(esp, stack_offset), arg); | 5057 __ mov(Operand(esp, stack_offset), arg); |
5112 __ jmp(&done); | 5058 __ jmp(&done); |
5113 | 5059 |
5114 // Check if the argument is a safe string wrapper. | 5060 // Check if the argument is a safe string wrapper. |
5115 __ bind(¬_cached); | 5061 __ bind(¬_cached); |
5116 __ test(arg, Immediate(kSmiTagMask)); | 5062 __ JumpIfSmi(arg, slow); |
5117 __ j(zero, slow); | |
5118 __ CmpObjectType(arg, JS_VALUE_TYPE, scratch1); // map -> scratch1. | 5063 __ CmpObjectType(arg, JS_VALUE_TYPE, scratch1); // map -> scratch1. |
5119 __ j(not_equal, slow); | 5064 __ j(not_equal, slow); |
5120 __ test_b(FieldOperand(scratch1, Map::kBitField2Offset), | 5065 __ test_b(FieldOperand(scratch1, Map::kBitField2Offset), |
5121 1 << Map::kStringWrapperSafeForDefaultValueOf); | 5066 1 << Map::kStringWrapperSafeForDefaultValueOf); |
5122 __ j(zero, slow); | 5067 __ j(zero, slow); |
5123 __ mov(arg, FieldOperand(arg, JSValue::kValueOffset)); | 5068 __ mov(arg, FieldOperand(arg, JSValue::kValueOffset)); |
5124 __ mov(Operand(esp, stack_offset), arg); | 5069 __ mov(Operand(esp, stack_offset), arg); |
5125 | 5070 |
5126 __ bind(&done); | 5071 __ bind(&done); |
5127 } | 5072 } |
(...skipping 273 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5401 | 5346 |
5402 // Stack frame on entry. | 5347 // Stack frame on entry. |
5403 // esp[0]: return address | 5348 // esp[0]: return address |
5404 // esp[4]: to | 5349 // esp[4]: to |
5405 // esp[8]: from | 5350 // esp[8]: from |
5406 // esp[12]: string | 5351 // esp[12]: string |
5407 | 5352 |
5408 // Make sure first argument is a string. | 5353 // Make sure first argument is a string. |
5409 __ mov(eax, Operand(esp, 3 * kPointerSize)); | 5354 __ mov(eax, Operand(esp, 3 * kPointerSize)); |
5410 STATIC_ASSERT(kSmiTag == 0); | 5355 STATIC_ASSERT(kSmiTag == 0); |
5411 __ test(eax, Immediate(kSmiTagMask)); | 5356 __ JumpIfSmi(eax, &runtime); |
5412 __ j(zero, &runtime); | |
5413 Condition is_string = masm->IsObjectStringType(eax, ebx, ebx); | 5357 Condition is_string = masm->IsObjectStringType(eax, ebx, ebx); |
5414 __ j(NegateCondition(is_string), &runtime); | 5358 __ j(NegateCondition(is_string), &runtime); |
5415 | 5359 |
5416 // eax: string | 5360 // eax: string |
5417 // ebx: instance type | 5361 // ebx: instance type |
5418 | 5362 |
5419 // Calculate length of sub string using the smi values. | 5363 // Calculate length of sub string using the smi values. |
5420 Label result_longer_than_two; | 5364 Label result_longer_than_two; |
5421 __ mov(ecx, Operand(esp, 1 * kPointerSize)); // To index. | 5365 __ mov(ecx, Operand(esp, 1 * kPointerSize)); // To index. |
5422 __ test(ecx, Immediate(kSmiTagMask)); | 5366 __ JumpIfNotSmi(ecx, &runtime); |
5423 __ j(not_zero, &runtime); | |
5424 __ mov(edx, Operand(esp, 2 * kPointerSize)); // From index. | 5367 __ mov(edx, Operand(esp, 2 * kPointerSize)); // From index. |
5425 __ test(edx, Immediate(kSmiTagMask)); | 5368 __ JumpIfNotSmi(edx, &runtime); |
5426 __ j(not_zero, &runtime); | |
5427 __ sub(ecx, Operand(edx)); | 5369 __ sub(ecx, Operand(edx)); |
5428 __ cmp(ecx, FieldOperand(eax, String::kLengthOffset)); | 5370 __ cmp(ecx, FieldOperand(eax, String::kLengthOffset)); |
5429 Label return_eax; | 5371 Label return_eax; |
5430 __ j(equal, &return_eax); | 5372 __ j(equal, &return_eax); |
5431 // Special handling of sub-strings of length 1 and 2. One character strings | 5373 // Special handling of sub-strings of length 1 and 2. One character strings |
5432 // are handled in the runtime system (looked up in the single character | 5374 // are handled in the runtime system (looked up in the single character |
5433 // cache). Two character strings are looked for in the symbol cache. | 5375 // cache). Two character strings are looked for in the symbol cache. |
5434 __ SmiUntag(ecx); // Result length is no longer smi. | 5376 __ SmiUntag(ecx); // Result length is no longer smi. |
5435 __ cmp(ecx, 2); | 5377 __ cmp(ecx, 2); |
5436 __ j(greater, &result_longer_than_two); | 5378 __ j(greater, &result_longer_than_two); |
(...skipping 271 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5708 __ bind(&runtime); | 5650 __ bind(&runtime); |
5709 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); | 5651 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); |
5710 } | 5652 } |
5711 | 5653 |
5712 | 5654 |
5713 void ICCompareStub::GenerateSmis(MacroAssembler* masm) { | 5655 void ICCompareStub::GenerateSmis(MacroAssembler* masm) { |
5714 ASSERT(state_ == CompareIC::SMIS); | 5656 ASSERT(state_ == CompareIC::SMIS); |
5715 Label miss; | 5657 Label miss; |
5716 __ mov(ecx, Operand(edx)); | 5658 __ mov(ecx, Operand(edx)); |
5717 __ or_(ecx, Operand(eax)); | 5659 __ or_(ecx, Operand(eax)); |
5718 __ test(ecx, Immediate(kSmiTagMask)); | 5660 __ JumpIfNotSmi(ecx, &miss, Label::kNear); |
5719 __ j(not_zero, &miss, Label::kNear); | |
5720 | 5661 |
5721 if (GetCondition() == equal) { | 5662 if (GetCondition() == equal) { |
5722 // For equality we do not care about the sign of the result. | 5663 // For equality we do not care about the sign of the result. |
5723 __ sub(eax, Operand(edx)); | 5664 __ sub(eax, Operand(edx)); |
5724 } else { | 5665 } else { |
5725 Label done; | 5666 Label done; |
5726 __ sub(edx, Operand(eax)); | 5667 __ sub(edx, Operand(eax)); |
5727 __ j(no_overflow, &done, Label::kNear); | 5668 __ j(no_overflow, &done, Label::kNear); |
5728 // Correct sign of result in case of overflow. | 5669 // Correct sign of result in case of overflow. |
5729 __ not_(edx); | 5670 __ not_(edx); |
5730 __ bind(&done); | 5671 __ bind(&done); |
5731 __ mov(eax, edx); | 5672 __ mov(eax, edx); |
5732 } | 5673 } |
5733 __ ret(0); | 5674 __ ret(0); |
5734 | 5675 |
5735 __ bind(&miss); | 5676 __ bind(&miss); |
5736 GenerateMiss(masm); | 5677 GenerateMiss(masm); |
5737 } | 5678 } |
5738 | 5679 |
5739 | 5680 |
5740 void ICCompareStub::GenerateHeapNumbers(MacroAssembler* masm) { | 5681 void ICCompareStub::GenerateHeapNumbers(MacroAssembler* masm) { |
5741 ASSERT(state_ == CompareIC::HEAP_NUMBERS); | 5682 ASSERT(state_ == CompareIC::HEAP_NUMBERS); |
5742 | 5683 |
5743 Label generic_stub; | 5684 Label generic_stub; |
5744 Label unordered; | 5685 Label unordered; |
5745 Label miss; | 5686 Label miss; |
5746 __ mov(ecx, Operand(edx)); | 5687 __ mov(ecx, Operand(edx)); |
5747 __ and_(ecx, Operand(eax)); | 5688 __ and_(ecx, Operand(eax)); |
5748 __ test(ecx, Immediate(kSmiTagMask)); | 5689 __ JumpIfSmi(ecx, &generic_stub, Label::kNear); |
5749 __ j(zero, &generic_stub, Label::kNear); | |
5750 | 5690 |
5751 __ CmpObjectType(eax, HEAP_NUMBER_TYPE, ecx); | 5691 __ CmpObjectType(eax, HEAP_NUMBER_TYPE, ecx); |
5752 __ j(not_equal, &miss, Label::kNear); | 5692 __ j(not_equal, &miss, Label::kNear); |
5753 __ CmpObjectType(edx, HEAP_NUMBER_TYPE, ecx); | 5693 __ CmpObjectType(edx, HEAP_NUMBER_TYPE, ecx); |
5754 __ j(not_equal, &miss, Label::kNear); | 5694 __ j(not_equal, &miss, Label::kNear); |
5755 | 5695 |
5756 // Inlining the double comparison and falling back to the general compare | 5696 // Inlining the double comparison and falling back to the general compare |
5757 // stub if NaN is involved or SS2 or CMOV is unsupported. | 5697 // stub if NaN is involved or SS2 or CMOV is unsupported. |
5758 if (CpuFeatures::IsSupported(SSE2) && CpuFeatures::IsSupported(CMOV)) { | 5698 if (CpuFeatures::IsSupported(SSE2) && CpuFeatures::IsSupported(CMOV)) { |
5759 CpuFeatures::Scope scope1(SSE2); | 5699 CpuFeatures::Scope scope1(SSE2); |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5798 Register left = edx; | 5738 Register left = edx; |
5799 Register right = eax; | 5739 Register right = eax; |
5800 Register tmp1 = ecx; | 5740 Register tmp1 = ecx; |
5801 Register tmp2 = ebx; | 5741 Register tmp2 = ebx; |
5802 | 5742 |
5803 // Check that both operands are heap objects. | 5743 // Check that both operands are heap objects. |
5804 Label miss; | 5744 Label miss; |
5805 __ mov(tmp1, Operand(left)); | 5745 __ mov(tmp1, Operand(left)); |
5806 STATIC_ASSERT(kSmiTag == 0); | 5746 STATIC_ASSERT(kSmiTag == 0); |
5807 __ and_(tmp1, Operand(right)); | 5747 __ and_(tmp1, Operand(right)); |
5808 __ test(tmp1, Immediate(kSmiTagMask)); | 5748 __ JumpIfSmi(tmp1, &miss, Label::kNear); |
5809 __ j(zero, &miss, Label::kNear); | |
5810 | 5749 |
5811 // Check that both operands are symbols. | 5750 // Check that both operands are symbols. |
5812 __ mov(tmp1, FieldOperand(left, HeapObject::kMapOffset)); | 5751 __ mov(tmp1, FieldOperand(left, HeapObject::kMapOffset)); |
5813 __ mov(tmp2, FieldOperand(right, HeapObject::kMapOffset)); | 5752 __ mov(tmp2, FieldOperand(right, HeapObject::kMapOffset)); |
5814 __ movzx_b(tmp1, FieldOperand(tmp1, Map::kInstanceTypeOffset)); | 5753 __ movzx_b(tmp1, FieldOperand(tmp1, Map::kInstanceTypeOffset)); |
5815 __ movzx_b(tmp2, FieldOperand(tmp2, Map::kInstanceTypeOffset)); | 5754 __ movzx_b(tmp2, FieldOperand(tmp2, Map::kInstanceTypeOffset)); |
5816 STATIC_ASSERT(kSymbolTag != 0); | 5755 STATIC_ASSERT(kSymbolTag != 0); |
5817 __ and_(tmp1, Operand(tmp2)); | 5756 __ and_(tmp1, Operand(tmp2)); |
5818 __ test(tmp1, Immediate(kIsSymbolMask)); | 5757 __ test(tmp1, Immediate(kIsSymbolMask)); |
5819 __ j(zero, &miss, Label::kNear); | 5758 __ j(zero, &miss, Label::kNear); |
(...skipping 25 matching lines...) Expand all Loading... |
5845 Register left = edx; | 5784 Register left = edx; |
5846 Register right = eax; | 5785 Register right = eax; |
5847 Register tmp1 = ecx; | 5786 Register tmp1 = ecx; |
5848 Register tmp2 = ebx; | 5787 Register tmp2 = ebx; |
5849 Register tmp3 = edi; | 5788 Register tmp3 = edi; |
5850 | 5789 |
5851 // Check that both operands are heap objects. | 5790 // Check that both operands are heap objects. |
5852 __ mov(tmp1, Operand(left)); | 5791 __ mov(tmp1, Operand(left)); |
5853 STATIC_ASSERT(kSmiTag == 0); | 5792 STATIC_ASSERT(kSmiTag == 0); |
5854 __ and_(tmp1, Operand(right)); | 5793 __ and_(tmp1, Operand(right)); |
5855 __ test(tmp1, Immediate(kSmiTagMask)); | 5794 __ JumpIfSmi(tmp1, &miss); |
5856 __ j(zero, &miss); | |
5857 | 5795 |
5858 // Check that both operands are strings. This leaves the instance | 5796 // Check that both operands are strings. This leaves the instance |
5859 // types loaded in tmp1 and tmp2. | 5797 // types loaded in tmp1 and tmp2. |
5860 __ mov(tmp1, FieldOperand(left, HeapObject::kMapOffset)); | 5798 __ mov(tmp1, FieldOperand(left, HeapObject::kMapOffset)); |
5861 __ mov(tmp2, FieldOperand(right, HeapObject::kMapOffset)); | 5799 __ mov(tmp2, FieldOperand(right, HeapObject::kMapOffset)); |
5862 __ movzx_b(tmp1, FieldOperand(tmp1, Map::kInstanceTypeOffset)); | 5800 __ movzx_b(tmp1, FieldOperand(tmp1, Map::kInstanceTypeOffset)); |
5863 __ movzx_b(tmp2, FieldOperand(tmp2, Map::kInstanceTypeOffset)); | 5801 __ movzx_b(tmp2, FieldOperand(tmp2, Map::kInstanceTypeOffset)); |
5864 __ mov(tmp3, tmp1); | 5802 __ mov(tmp3, tmp1); |
5865 STATIC_ASSERT(kNotStringTag != 0); | 5803 STATIC_ASSERT(kNotStringTag != 0); |
5866 __ or_(tmp3, Operand(tmp2)); | 5804 __ or_(tmp3, Operand(tmp2)); |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5911 __ bind(&miss); | 5849 __ bind(&miss); |
5912 GenerateMiss(masm); | 5850 GenerateMiss(masm); |
5913 } | 5851 } |
5914 | 5852 |
5915 | 5853 |
5916 void ICCompareStub::GenerateObjects(MacroAssembler* masm) { | 5854 void ICCompareStub::GenerateObjects(MacroAssembler* masm) { |
5917 ASSERT(state_ == CompareIC::OBJECTS); | 5855 ASSERT(state_ == CompareIC::OBJECTS); |
5918 Label miss; | 5856 Label miss; |
5919 __ mov(ecx, Operand(edx)); | 5857 __ mov(ecx, Operand(edx)); |
5920 __ and_(ecx, Operand(eax)); | 5858 __ and_(ecx, Operand(eax)); |
5921 __ test(ecx, Immediate(kSmiTagMask)); | 5859 __ JumpIfSmi(ecx, &miss, Label::kNear); |
5922 __ j(zero, &miss, Label::kNear); | |
5923 | 5860 |
5924 __ CmpObjectType(eax, JS_OBJECT_TYPE, ecx); | 5861 __ CmpObjectType(eax, JS_OBJECT_TYPE, ecx); |
5925 __ j(not_equal, &miss, Label::kNear); | 5862 __ j(not_equal, &miss, Label::kNear); |
5926 __ CmpObjectType(edx, JS_OBJECT_TYPE, ecx); | 5863 __ CmpObjectType(edx, JS_OBJECT_TYPE, ecx); |
5927 __ j(not_equal, &miss, Label::kNear); | 5864 __ j(not_equal, &miss, Label::kNear); |
5928 | 5865 |
5929 ASSERT(GetCondition() == equal); | 5866 ASSERT(GetCondition() == equal); |
5930 __ sub(eax, Operand(edx)); | 5867 __ sub(eax, Operand(edx)); |
5931 __ ret(0); | 5868 __ ret(0); |
5932 | 5869 |
(...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6176 __ Drop(1); | 6113 __ Drop(1); |
6177 __ ret(2 * kPointerSize); | 6114 __ ret(2 * kPointerSize); |
6178 } | 6115 } |
6179 | 6116 |
6180 | 6117 |
6181 #undef __ | 6118 #undef __ |
6182 | 6119 |
6183 } } // namespace v8::internal | 6120 } } // namespace v8::internal |
6184 | 6121 |
6185 #endif // V8_TARGET_ARCH_IA32 | 6122 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |