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