| 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 24 matching lines...) Expand all Loading... |
| 35 #include "isolate.h" | 35 #include "isolate.h" |
| 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 NearLabel check_heap_number, call_builtin; | 45 Label check_heap_number, call_builtin; |
| 46 __ test(eax, Immediate(kSmiTagMask)); | 46 __ test(eax, Immediate(kSmiTagMask)); |
| 47 __ j(not_zero, &check_heap_number); | 47 __ j(not_zero, &check_heap_number, Label::kNear); |
| 48 __ ret(0); | 48 __ ret(0); |
| 49 | 49 |
| 50 __ bind(&check_heap_number); | 50 __ bind(&check_heap_number); |
| 51 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); | 51 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); |
| 52 Factory* factory = masm->isolate()->factory(); | 52 Factory* factory = masm->isolate()->factory(); |
| 53 __ cmp(Operand(ebx), Immediate(factory->heap_number_map())); | 53 __ cmp(Operand(ebx), Immediate(factory->heap_number_map())); |
| 54 __ j(not_equal, &call_builtin); | 54 __ j(not_equal, &call_builtin, Label::kNear); |
| 55 __ ret(0); | 55 __ ret(0); |
| 56 | 56 |
| 57 __ bind(&call_builtin); | 57 __ bind(&call_builtin); |
| 58 __ pop(ecx); // Pop return address. | 58 __ pop(ecx); // Pop return address. |
| 59 __ push(eax); | 59 __ push(eax); |
| 60 __ push(ecx); // Push return address. | 60 __ push(ecx); // Push return address. |
| 61 __ InvokeBuiltin(Builtins::TO_NUMBER, JUMP_FUNCTION); | 61 __ InvokeBuiltin(Builtins::TO_NUMBER, JUMP_FUNCTION); |
| 62 } | 62 } |
| 63 | 63 |
| 64 | 64 |
| (...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 235 // Return and remove the on-stack parameters. | 235 // Return and remove the on-stack parameters. |
| 236 __ ret(3 * kPointerSize); | 236 __ ret(3 * kPointerSize); |
| 237 | 237 |
| 238 __ bind(&slow_case); | 238 __ bind(&slow_case); |
| 239 __ TailCallRuntime(Runtime::kCreateArrayLiteralShallow, 3, 1); | 239 __ TailCallRuntime(Runtime::kCreateArrayLiteralShallow, 3, 1); |
| 240 } | 240 } |
| 241 | 241 |
| 242 | 242 |
| 243 // NOTE: The stub does not handle the inlined cases (Smis, Booleans, undefined). | 243 // NOTE: The stub does not handle the inlined cases (Smis, Booleans, undefined). |
| 244 void ToBooleanStub::Generate(MacroAssembler* masm) { | 244 void ToBooleanStub::Generate(MacroAssembler* masm) { |
| 245 NearLabel false_result, true_result, not_string; | 245 Label false_result, true_result, not_string; |
| 246 __ mov(eax, Operand(esp, 1 * kPointerSize)); | 246 __ mov(eax, Operand(esp, 1 * kPointerSize)); |
| 247 | 247 |
| 248 // 'null' => false. | 248 // 'null' => false. |
| 249 Factory* factory = masm->isolate()->factory(); | 249 Factory* factory = masm->isolate()->factory(); |
| 250 __ cmp(eax, factory->null_value()); | 250 __ cmp(eax, factory->null_value()); |
| 251 __ j(equal, &false_result); | 251 __ j(equal, &false_result, Label::kNear); |
| 252 | 252 |
| 253 // Get the map and type of the heap object. | 253 // Get the map and type of the heap object. |
| 254 __ mov(edx, FieldOperand(eax, HeapObject::kMapOffset)); | 254 __ mov(edx, FieldOperand(eax, HeapObject::kMapOffset)); |
| 255 __ movzx_b(ecx, FieldOperand(edx, Map::kInstanceTypeOffset)); | 255 __ movzx_b(ecx, FieldOperand(edx, Map::kInstanceTypeOffset)); |
| 256 | 256 |
| 257 // Undetectable => false. | 257 // Undetectable => false. |
| 258 __ test_b(FieldOperand(edx, Map::kBitFieldOffset), | 258 __ test_b(FieldOperand(edx, Map::kBitFieldOffset), |
| 259 1 << Map::kIsUndetectable); | 259 1 << Map::kIsUndetectable); |
| 260 __ j(not_zero, &false_result); | 260 __ j(not_zero, &false_result, Label::kNear); |
| 261 | 261 |
| 262 // JavaScript object => true. | 262 // JavaScript object => true. |
| 263 __ CmpInstanceType(edx, FIRST_JS_OBJECT_TYPE); | 263 __ CmpInstanceType(edx, FIRST_JS_OBJECT_TYPE); |
| 264 __ j(above_equal, &true_result); | 264 __ j(above_equal, &true_result, Label::kNear); |
| 265 | 265 |
| 266 // String value => false iff empty. | 266 // String value => false iff empty. |
| 267 __ CmpInstanceType(edx, FIRST_NONSTRING_TYPE); | 267 __ CmpInstanceType(edx, FIRST_NONSTRING_TYPE); |
| 268 __ j(above_equal, ¬_string); | 268 __ j(above_equal, ¬_string, Label::kNear); |
| 269 STATIC_ASSERT(kSmiTag == 0); | 269 STATIC_ASSERT(kSmiTag == 0); |
| 270 __ cmp(FieldOperand(eax, String::kLengthOffset), Immediate(0)); | 270 __ cmp(FieldOperand(eax, String::kLengthOffset), Immediate(0)); |
| 271 __ j(zero, &false_result); | 271 __ j(zero, &false_result, Label::kNear); |
| 272 __ jmp(&true_result); | 272 __ jmp(&true_result, Label::kNear); |
| 273 | 273 |
| 274 __ bind(¬_string); | 274 __ bind(¬_string); |
| 275 // HeapNumber => false iff +0, -0, or NaN. | 275 // HeapNumber => false iff +0, -0, or NaN. |
| 276 __ cmp(edx, factory->heap_number_map()); | 276 __ cmp(edx, factory->heap_number_map()); |
| 277 __ j(not_equal, &true_result); | 277 __ j(not_equal, &true_result, Label::kNear); |
| 278 __ fldz(); | 278 __ fldz(); |
| 279 __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset)); | 279 __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset)); |
| 280 __ FCmp(); | 280 __ FCmp(); |
| 281 __ j(zero, &false_result); | 281 __ j(zero, &false_result, Label::kNear); |
| 282 // Fall through to |true_result|. | 282 // Fall through to |true_result|. |
| 283 | 283 |
| 284 // Return 1/0 for true/false in eax. | 284 // Return 1/0 for true/false in eax. |
| 285 __ bind(&true_result); | 285 __ bind(&true_result); |
| 286 __ mov(eax, 1); | 286 __ mov(eax, 1); |
| 287 __ ret(1 * kPointerSize); | 287 __ ret(1 * kPointerSize); |
| 288 __ bind(&false_result); | 288 __ bind(&false_result); |
| 289 __ mov(eax, 0); | 289 __ mov(eax, 0); |
| 290 __ ret(1 * kPointerSize); | 290 __ ret(1 * kPointerSize); |
| 291 } | 291 } |
| (...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 499 // it's probably slower to test than just to do it. | 499 // it's probably slower to test than just to do it. |
| 500 __ mov(scratch2, FieldOperand(source, HeapNumber::kMantissaOffset)); | 500 __ mov(scratch2, FieldOperand(source, HeapNumber::kMantissaOffset)); |
| 501 // Shift down 22 bits to get the most significant 10 bits or the low | 501 // Shift down 22 bits to get the most significant 10 bits or the low |
| 502 // mantissa word. | 502 // mantissa word. |
| 503 __ shr(scratch2, 32 - shift_distance); | 503 __ shr(scratch2, 32 - shift_distance); |
| 504 __ or_(scratch2, Operand(scratch)); | 504 __ or_(scratch2, Operand(scratch)); |
| 505 // Move down according to the exponent. | 505 // Move down according to the exponent. |
| 506 __ shr_cl(scratch2); | 506 __ shr_cl(scratch2); |
| 507 // Now the unsigned answer is in scratch2. We need to move it to ecx and | 507 // Now the unsigned answer is in scratch2. We need to move it to ecx and |
| 508 // we may need to fix the sign. | 508 // we may need to fix the sign. |
| 509 NearLabel negative; | 509 Label negative; |
| 510 __ xor_(ecx, Operand(ecx)); | 510 __ xor_(ecx, Operand(ecx)); |
| 511 __ cmp(ecx, FieldOperand(source, HeapNumber::kExponentOffset)); | 511 __ cmp(ecx, FieldOperand(source, HeapNumber::kExponentOffset)); |
| 512 __ j(greater, &negative); | 512 __ j(greater, &negative, Label::kNear); |
| 513 __ mov(ecx, scratch2); | 513 __ mov(ecx, scratch2); |
| 514 __ jmp(&done); | 514 __ jmp(&done, Label::kNear); |
| 515 __ bind(&negative); | 515 __ bind(&negative); |
| 516 __ sub(ecx, Operand(scratch2)); | 516 __ sub(ecx, Operand(scratch2)); |
| 517 __ bind(&done); | 517 __ bind(&done); |
| 518 } | 518 } |
| 519 } | 519 } |
| 520 | 520 |
| 521 | 521 |
| 522 Handle<Code> GetTypeRecordingUnaryOpStub(int key, | 522 Handle<Code> GetTypeRecordingUnaryOpStub(int key, |
| 523 TRUnaryOpIC::TypeInfo type_info) { | 523 TRUnaryOpIC::TypeInfo type_info) { |
| 524 TypeRecordingUnaryOpStub stub(key, type_info); | 524 TypeRecordingUnaryOpStub stub(key, type_info); |
| (...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 744 Label* slow) { | 744 Label* slow) { |
| 745 __ mov(edx, FieldOperand(eax, HeapObject::kMapOffset)); | 745 __ mov(edx, FieldOperand(eax, HeapObject::kMapOffset)); |
| 746 __ cmp(edx, masm->isolate()->factory()->heap_number_map()); | 746 __ cmp(edx, masm->isolate()->factory()->heap_number_map()); |
| 747 __ j(not_equal, slow); | 747 __ j(not_equal, slow); |
| 748 | 748 |
| 749 // Convert the heap number in eax to an untagged integer in ecx. | 749 // Convert the heap number in eax to an untagged integer in ecx. |
| 750 IntegerConvert(masm, eax, TypeInfo::Unknown(), CpuFeatures::IsSupported(SSE3), | 750 IntegerConvert(masm, eax, TypeInfo::Unknown(), CpuFeatures::IsSupported(SSE3), |
| 751 slow); | 751 slow); |
| 752 | 752 |
| 753 // Do the bitwise operation and check if the result fits in a smi. | 753 // Do the bitwise operation and check if the result fits in a smi. |
| 754 NearLabel try_float; | 754 Label try_float; |
| 755 __ not_(ecx); | 755 __ not_(ecx); |
| 756 __ cmp(ecx, 0xc0000000); | 756 __ cmp(ecx, 0xc0000000); |
| 757 __ j(sign, &try_float); | 757 __ j(sign, &try_float, Label::kNear); |
| 758 | 758 |
| 759 // Tag the result as a smi and we're done. | 759 // Tag the result as a smi and we're done. |
| 760 STATIC_ASSERT(kSmiTagSize == 1); | 760 STATIC_ASSERT(kSmiTagSize == 1); |
| 761 __ lea(eax, Operand(ecx, times_2, kSmiTag)); | 761 __ lea(eax, Operand(ecx, times_2, kSmiTag)); |
| 762 __ ret(0); | 762 __ ret(0); |
| 763 | 763 |
| 764 // Try to store the result in a heap number. | 764 // Try to store the result in a heap number. |
| 765 __ bind(&try_float); | 765 __ bind(&try_float); |
| 766 if (mode_ == UNARY_NO_OVERWRITE) { | 766 if (mode_ == UNARY_NO_OVERWRITE) { |
| 767 Label slow_allocate_heapnumber, heapnumber_allocated; | 767 Label slow_allocate_heapnumber, heapnumber_allocated; |
| (...skipping 759 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1527 // Tag smi result and return. | 1527 // Tag smi result and return. |
| 1528 __ SmiTag(eax); | 1528 __ SmiTag(eax); |
| 1529 __ ret(2 * kPointerSize); // Drop two pushed arguments from the stack. | 1529 __ ret(2 * kPointerSize); // Drop two pushed arguments from the stack. |
| 1530 | 1530 |
| 1531 // All ops except SHR return a signed int32 that we load in | 1531 // All ops except SHR return a signed int32 that we load in |
| 1532 // a HeapNumber. | 1532 // a HeapNumber. |
| 1533 if (op_ != Token::SHR) { | 1533 if (op_ != Token::SHR) { |
| 1534 __ bind(&non_smi_result); | 1534 __ bind(&non_smi_result); |
| 1535 // Allocate a heap number if needed. | 1535 // Allocate a heap number if needed. |
| 1536 __ mov(ebx, Operand(eax)); // ebx: result | 1536 __ mov(ebx, Operand(eax)); // ebx: result |
| 1537 NearLabel skip_allocation; | 1537 Label skip_allocation; |
| 1538 switch (mode_) { | 1538 switch (mode_) { |
| 1539 case OVERWRITE_LEFT: | 1539 case OVERWRITE_LEFT: |
| 1540 case OVERWRITE_RIGHT: | 1540 case OVERWRITE_RIGHT: |
| 1541 // If the operand was an object, we skip the | 1541 // If the operand was an object, we skip the |
| 1542 // allocation of a heap number. | 1542 // allocation of a heap number. |
| 1543 __ mov(eax, Operand(esp, mode_ == OVERWRITE_RIGHT ? | 1543 __ mov(eax, Operand(esp, mode_ == OVERWRITE_RIGHT ? |
| 1544 1 * kPointerSize : 2 * kPointerSize)); | 1544 1 * kPointerSize : 2 * kPointerSize)); |
| 1545 __ test(eax, Immediate(kSmiTagMask)); | 1545 __ test(eax, Immediate(kSmiTagMask)); |
| 1546 __ j(not_zero, &skip_allocation, not_taken); | 1546 __ j(not_zero, &skip_allocation, not_taken, Label::kNear); |
| 1547 // Fall through! | 1547 // Fall through! |
| 1548 case NO_OVERWRITE: | 1548 case NO_OVERWRITE: |
| 1549 __ AllocateHeapNumber(eax, ecx, edx, &call_runtime); | 1549 __ AllocateHeapNumber(eax, ecx, edx, &call_runtime); |
| 1550 __ bind(&skip_allocation); | 1550 __ bind(&skip_allocation); |
| 1551 break; | 1551 break; |
| 1552 default: UNREACHABLE(); | 1552 default: UNREACHABLE(); |
| 1553 } | 1553 } |
| 1554 // Store the result in the HeapNumber and return. | 1554 // Store the result in the HeapNumber and return. |
| 1555 if (CpuFeatures::IsSupported(SSE2)) { | 1555 if (CpuFeatures::IsSupported(SSE2)) { |
| 1556 CpuFeatures::Scope use_sse2(SSE2); | 1556 CpuFeatures::Scope use_sse2(SSE2); |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1615 case Token::SHR: | 1615 case Token::SHR: |
| 1616 __ InvokeBuiltin(Builtins::SHR, JUMP_FUNCTION); | 1616 __ InvokeBuiltin(Builtins::SHR, JUMP_FUNCTION); |
| 1617 break; | 1617 break; |
| 1618 default: | 1618 default: |
| 1619 UNREACHABLE(); | 1619 UNREACHABLE(); |
| 1620 } | 1620 } |
| 1621 } | 1621 } |
| 1622 | 1622 |
| 1623 | 1623 |
| 1624 void TypeRecordingBinaryOpStub::GenerateOddballStub(MacroAssembler* masm) { | 1624 void TypeRecordingBinaryOpStub::GenerateOddballStub(MacroAssembler* masm) { |
| 1625 Label call_runtime; | |
| 1626 | |
| 1627 if (op_ == Token::ADD) { | 1625 if (op_ == Token::ADD) { |
| 1628 // Handle string addition here, because it is the only operation | 1626 // Handle string addition here, because it is the only operation |
| 1629 // that does not do a ToNumber conversion on the operands. | 1627 // that does not do a ToNumber conversion on the operands. |
| 1630 GenerateAddStrings(masm); | 1628 GenerateAddStrings(masm); |
| 1631 } | 1629 } |
| 1632 | 1630 |
| 1633 Factory* factory = masm->isolate()->factory(); | 1631 Factory* factory = masm->isolate()->factory(); |
| 1634 | 1632 |
| 1635 // Convert odd ball arguments to numbers. | 1633 // Convert odd ball arguments to numbers. |
| 1636 NearLabel check, done; | 1634 Label check, done; |
| 1637 __ cmp(edx, factory->undefined_value()); | 1635 __ cmp(edx, factory->undefined_value()); |
| 1638 __ j(not_equal, &check); | 1636 __ j(not_equal, &check, Label::kNear); |
| 1639 if (Token::IsBitOp(op_)) { | 1637 if (Token::IsBitOp(op_)) { |
| 1640 __ xor_(edx, Operand(edx)); | 1638 __ xor_(edx, Operand(edx)); |
| 1641 } else { | 1639 } else { |
| 1642 __ mov(edx, Immediate(factory->nan_value())); | 1640 __ mov(edx, Immediate(factory->nan_value())); |
| 1643 } | 1641 } |
| 1644 __ jmp(&done); | 1642 __ jmp(&done, Label::kNear); |
| 1645 __ bind(&check); | 1643 __ bind(&check); |
| 1646 __ cmp(eax, factory->undefined_value()); | 1644 __ cmp(eax, factory->undefined_value()); |
| 1647 __ j(not_equal, &done); | 1645 __ j(not_equal, &done, Label::kNear); |
| 1648 if (Token::IsBitOp(op_)) { | 1646 if (Token::IsBitOp(op_)) { |
| 1649 __ xor_(eax, Operand(eax)); | 1647 __ xor_(eax, Operand(eax)); |
| 1650 } else { | 1648 } else { |
| 1651 __ mov(eax, Immediate(factory->nan_value())); | 1649 __ mov(eax, Immediate(factory->nan_value())); |
| 1652 } | 1650 } |
| 1653 __ bind(&done); | 1651 __ bind(&done); |
| 1654 | 1652 |
| 1655 GenerateHeapNumberStub(masm); | 1653 GenerateHeapNumberStub(masm); |
| 1656 } | 1654 } |
| 1657 | 1655 |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1744 // Tag smi result and return. | 1742 // Tag smi result and return. |
| 1745 __ SmiTag(eax); | 1743 __ SmiTag(eax); |
| 1746 __ ret(2 * kPointerSize); // Drop two pushed arguments from the stack. | 1744 __ ret(2 * kPointerSize); // Drop two pushed arguments from the stack. |
| 1747 | 1745 |
| 1748 // All ops except SHR return a signed int32 that we load in | 1746 // All ops except SHR return a signed int32 that we load in |
| 1749 // a HeapNumber. | 1747 // a HeapNumber. |
| 1750 if (op_ != Token::SHR) { | 1748 if (op_ != Token::SHR) { |
| 1751 __ bind(&non_smi_result); | 1749 __ bind(&non_smi_result); |
| 1752 // Allocate a heap number if needed. | 1750 // Allocate a heap number if needed. |
| 1753 __ mov(ebx, Operand(eax)); // ebx: result | 1751 __ mov(ebx, Operand(eax)); // ebx: result |
| 1754 NearLabel skip_allocation; | 1752 Label skip_allocation; |
| 1755 switch (mode_) { | 1753 switch (mode_) { |
| 1756 case OVERWRITE_LEFT: | 1754 case OVERWRITE_LEFT: |
| 1757 case OVERWRITE_RIGHT: | 1755 case OVERWRITE_RIGHT: |
| 1758 // If the operand was an object, we skip the | 1756 // If the operand was an object, we skip the |
| 1759 // allocation of a heap number. | 1757 // allocation of a heap number. |
| 1760 __ mov(eax, Operand(esp, mode_ == OVERWRITE_RIGHT ? | 1758 __ mov(eax, Operand(esp, mode_ == OVERWRITE_RIGHT ? |
| 1761 1 * kPointerSize : 2 * kPointerSize)); | 1759 1 * kPointerSize : 2 * kPointerSize)); |
| 1762 __ test(eax, Immediate(kSmiTagMask)); | 1760 __ test(eax, Immediate(kSmiTagMask)); |
| 1763 __ j(not_zero, &skip_allocation, not_taken); | 1761 __ j(not_zero, &skip_allocation, not_taken, Label::kNear); |
| 1764 // Fall through! | 1762 // Fall through! |
| 1765 case NO_OVERWRITE: | 1763 case NO_OVERWRITE: |
| 1766 __ AllocateHeapNumber(eax, ecx, edx, &call_runtime); | 1764 __ AllocateHeapNumber(eax, ecx, edx, &call_runtime); |
| 1767 __ bind(&skip_allocation); | 1765 __ bind(&skip_allocation); |
| 1768 break; | 1766 break; |
| 1769 default: UNREACHABLE(); | 1767 default: UNREACHABLE(); |
| 1770 } | 1768 } |
| 1771 // Store the result in the HeapNumber and return. | 1769 // Store the result in the HeapNumber and return. |
| 1772 if (CpuFeatures::IsSupported(SSE2)) { | 1770 if (CpuFeatures::IsSupported(SSE2)) { |
| 1773 CpuFeatures::Scope use_sse2(SSE2); | 1771 CpuFeatures::Scope use_sse2(SSE2); |
| (...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1944 // Tag smi result and return. | 1942 // Tag smi result and return. |
| 1945 __ SmiTag(eax); | 1943 __ SmiTag(eax); |
| 1946 __ ret(2 * kPointerSize); // Drop the arguments from the stack. | 1944 __ ret(2 * kPointerSize); // Drop the arguments from the stack. |
| 1947 | 1945 |
| 1948 // All ops except SHR return a signed int32 that we load in | 1946 // All ops except SHR return a signed int32 that we load in |
| 1949 // a HeapNumber. | 1947 // a HeapNumber. |
| 1950 if (op_ != Token::SHR) { | 1948 if (op_ != Token::SHR) { |
| 1951 __ bind(&non_smi_result); | 1949 __ bind(&non_smi_result); |
| 1952 // Allocate a heap number if needed. | 1950 // Allocate a heap number if needed. |
| 1953 __ mov(ebx, Operand(eax)); // ebx: result | 1951 __ mov(ebx, Operand(eax)); // ebx: result |
| 1954 NearLabel skip_allocation; | 1952 Label skip_allocation; |
| 1955 switch (mode_) { | 1953 switch (mode_) { |
| 1956 case OVERWRITE_LEFT: | 1954 case OVERWRITE_LEFT: |
| 1957 case OVERWRITE_RIGHT: | 1955 case OVERWRITE_RIGHT: |
| 1958 // If the operand was an object, we skip the | 1956 // If the operand was an object, we skip the |
| 1959 // allocation of a heap number. | 1957 // allocation of a heap number. |
| 1960 __ mov(eax, Operand(esp, mode_ == OVERWRITE_RIGHT ? | 1958 __ mov(eax, Operand(esp, mode_ == OVERWRITE_RIGHT ? |
| 1961 1 * kPointerSize : 2 * kPointerSize)); | 1959 1 * kPointerSize : 2 * kPointerSize)); |
| 1962 __ test(eax, Immediate(kSmiTagMask)); | 1960 __ test(eax, Immediate(kSmiTagMask)); |
| 1963 __ j(not_zero, &skip_allocation, not_taken); | 1961 __ j(not_zero, &skip_allocation, not_taken, Label::kNear); |
| 1964 // Fall through! | 1962 // Fall through! |
| 1965 case NO_OVERWRITE: | 1963 case NO_OVERWRITE: |
| 1966 __ AllocateHeapNumber(eax, ecx, edx, &call_runtime); | 1964 __ AllocateHeapNumber(eax, ecx, edx, &call_runtime); |
| 1967 __ bind(&skip_allocation); | 1965 __ bind(&skip_allocation); |
| 1968 break; | 1966 break; |
| 1969 default: UNREACHABLE(); | 1967 default: UNREACHABLE(); |
| 1970 } | 1968 } |
| 1971 // Store the result in the HeapNumber and return. | 1969 // Store the result in the HeapNumber and return. |
| 1972 if (CpuFeatures::IsSupported(SSE2)) { | 1970 if (CpuFeatures::IsSupported(SSE2)) { |
| 1973 CpuFeatures::Scope use_sse2(SSE2); | 1971 CpuFeatures::Scope use_sse2(SSE2); |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2029 __ InvokeBuiltin(Builtins::SHR, JUMP_FUNCTION); | 2027 __ InvokeBuiltin(Builtins::SHR, JUMP_FUNCTION); |
| 2030 break; | 2028 break; |
| 2031 default: | 2029 default: |
| 2032 UNREACHABLE(); | 2030 UNREACHABLE(); |
| 2033 } | 2031 } |
| 2034 } | 2032 } |
| 2035 | 2033 |
| 2036 | 2034 |
| 2037 void TypeRecordingBinaryOpStub::GenerateAddStrings(MacroAssembler* masm) { | 2035 void TypeRecordingBinaryOpStub::GenerateAddStrings(MacroAssembler* masm) { |
| 2038 ASSERT(op_ == Token::ADD); | 2036 ASSERT(op_ == Token::ADD); |
| 2039 NearLabel left_not_string, call_runtime; | 2037 Label left_not_string, call_runtime; |
| 2040 | 2038 |
| 2041 // Registers containing left and right operands respectively. | 2039 // Registers containing left and right operands respectively. |
| 2042 Register left = edx; | 2040 Register left = edx; |
| 2043 Register right = eax; | 2041 Register right = eax; |
| 2044 | 2042 |
| 2045 // Test if left operand is a string. | 2043 // Test if left operand is a string. |
| 2046 __ test(left, Immediate(kSmiTagMask)); | 2044 __ test(left, Immediate(kSmiTagMask)); |
| 2047 __ j(zero, &left_not_string); | 2045 __ j(zero, &left_not_string, Label::kNear); |
| 2048 __ CmpObjectType(left, FIRST_NONSTRING_TYPE, ecx); | 2046 __ CmpObjectType(left, FIRST_NONSTRING_TYPE, ecx); |
| 2049 __ j(above_equal, &left_not_string); | 2047 __ j(above_equal, &left_not_string, Label::kNear); |
| 2050 | 2048 |
| 2051 StringAddStub string_add_left_stub(NO_STRING_CHECK_LEFT_IN_STUB); | 2049 StringAddStub string_add_left_stub(NO_STRING_CHECK_LEFT_IN_STUB); |
| 2052 GenerateRegisterArgsPush(masm); | 2050 GenerateRegisterArgsPush(masm); |
| 2053 __ TailCallStub(&string_add_left_stub); | 2051 __ TailCallStub(&string_add_left_stub); |
| 2054 | 2052 |
| 2055 // Left operand is not a string, test right. | 2053 // Left operand is not a string, test right. |
| 2056 __ bind(&left_not_string); | 2054 __ bind(&left_not_string); |
| 2057 __ test(right, Immediate(kSmiTagMask)); | 2055 __ test(right, Immediate(kSmiTagMask)); |
| 2058 __ j(zero, &call_runtime); | 2056 __ j(zero, &call_runtime, Label::kNear); |
| 2059 __ CmpObjectType(right, FIRST_NONSTRING_TYPE, ecx); | 2057 __ CmpObjectType(right, FIRST_NONSTRING_TYPE, ecx); |
| 2060 __ j(above_equal, &call_runtime); | 2058 __ j(above_equal, &call_runtime, Label::kNear); |
| 2061 | 2059 |
| 2062 StringAddStub string_add_right_stub(NO_STRING_CHECK_RIGHT_IN_STUB); | 2060 StringAddStub string_add_right_stub(NO_STRING_CHECK_RIGHT_IN_STUB); |
| 2063 GenerateRegisterArgsPush(masm); | 2061 GenerateRegisterArgsPush(masm); |
| 2064 __ TailCallStub(&string_add_right_stub); | 2062 __ TailCallStub(&string_add_right_stub); |
| 2065 | 2063 |
| 2066 // Neither argument is a string. | 2064 // Neither argument is a string. |
| 2067 __ bind(&call_runtime); | 2065 __ bind(&call_runtime); |
| 2068 } | 2066 } |
| 2069 | 2067 |
| 2070 | 2068 |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2131 // xmm1: untagged double input argument | 2129 // xmm1: untagged double input argument |
| 2132 // Output: | 2130 // Output: |
| 2133 // xmm1: untagged double result. | 2131 // xmm1: untagged double result. |
| 2134 | 2132 |
| 2135 Label runtime_call; | 2133 Label runtime_call; |
| 2136 Label runtime_call_clear_stack; | 2134 Label runtime_call_clear_stack; |
| 2137 Label skip_cache; | 2135 Label skip_cache; |
| 2138 const bool tagged = (argument_type_ == TAGGED); | 2136 const bool tagged = (argument_type_ == TAGGED); |
| 2139 if (tagged) { | 2137 if (tagged) { |
| 2140 // Test that eax is a number. | 2138 // Test that eax is a number. |
| 2141 NearLabel input_not_smi; | 2139 Label input_not_smi; |
| 2142 NearLabel loaded; | 2140 Label loaded; |
| 2143 __ mov(eax, Operand(esp, kPointerSize)); | 2141 __ mov(eax, Operand(esp, kPointerSize)); |
| 2144 __ test(eax, Immediate(kSmiTagMask)); | 2142 __ test(eax, Immediate(kSmiTagMask)); |
| 2145 __ j(not_zero, &input_not_smi); | 2143 __ j(not_zero, &input_not_smi, Label::kNear); |
| 2146 // Input is a smi. Untag and load it onto the FPU stack. | 2144 // Input is a smi. Untag and load it onto the FPU stack. |
| 2147 // Then load the low and high words of the double into ebx, edx. | 2145 // Then load the low and high words of the double into ebx, edx. |
| 2148 STATIC_ASSERT(kSmiTagSize == 1); | 2146 STATIC_ASSERT(kSmiTagSize == 1); |
| 2149 __ sar(eax, 1); | 2147 __ sar(eax, 1); |
| 2150 __ sub(Operand(esp), Immediate(2 * kPointerSize)); | 2148 __ sub(Operand(esp), Immediate(2 * kPointerSize)); |
| 2151 __ mov(Operand(esp, 0), eax); | 2149 __ mov(Operand(esp, 0), eax); |
| 2152 __ fild_s(Operand(esp, 0)); | 2150 __ fild_s(Operand(esp, 0)); |
| 2153 __ fst_d(Operand(esp, 0)); | 2151 __ fst_d(Operand(esp, 0)); |
| 2154 __ pop(edx); | 2152 __ pop(edx); |
| 2155 __ pop(ebx); | 2153 __ pop(ebx); |
| 2156 __ jmp(&loaded); | 2154 __ jmp(&loaded, Label::kNear); |
| 2157 __ bind(&input_not_smi); | 2155 __ bind(&input_not_smi); |
| 2158 // Check if input is a HeapNumber. | 2156 // Check if input is a HeapNumber. |
| 2159 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); | 2157 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); |
| 2160 Factory* factory = masm->isolate()->factory(); | 2158 Factory* factory = masm->isolate()->factory(); |
| 2161 __ cmp(Operand(ebx), Immediate(factory->heap_number_map())); | 2159 __ cmp(Operand(ebx), Immediate(factory->heap_number_map())); |
| 2162 __ j(not_equal, &runtime_call); | 2160 __ j(not_equal, &runtime_call); |
| 2163 // Input is a HeapNumber. Push it on the FPU stack and load its | 2161 // Input is a HeapNumber. Push it on the FPU stack and load its |
| 2164 // low and high words into ebx, edx. | 2162 // low and high words into ebx, edx. |
| 2165 __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset)); | 2163 __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset)); |
| 2166 __ mov(edx, FieldOperand(eax, HeapNumber::kExponentOffset)); | 2164 __ mov(edx, FieldOperand(eax, HeapNumber::kExponentOffset)); |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2220 CHECK_EQ(12, elem2_start - elem_start); // Two uint_32's and a pointer. | 2218 CHECK_EQ(12, elem2_start - elem_start); // Two uint_32's and a pointer. |
| 2221 CHECK_EQ(0, elem_in0 - elem_start); | 2219 CHECK_EQ(0, elem_in0 - elem_start); |
| 2222 CHECK_EQ(kIntSize, elem_in1 - elem_start); | 2220 CHECK_EQ(kIntSize, elem_in1 - elem_start); |
| 2223 CHECK_EQ(2 * kIntSize, elem_out - elem_start); | 2221 CHECK_EQ(2 * kIntSize, elem_out - elem_start); |
| 2224 } | 2222 } |
| 2225 #endif | 2223 #endif |
| 2226 // Find the address of the ecx'th entry in the cache, i.e., &eax[ecx*12]. | 2224 // Find the address of the ecx'th entry in the cache, i.e., &eax[ecx*12]. |
| 2227 __ lea(ecx, Operand(ecx, ecx, times_2, 0)); | 2225 __ lea(ecx, Operand(ecx, ecx, times_2, 0)); |
| 2228 __ lea(ecx, Operand(eax, ecx, times_4, 0)); | 2226 __ lea(ecx, Operand(eax, ecx, times_4, 0)); |
| 2229 // Check if cache matches: Double value is stored in uint32_t[2] array. | 2227 // Check if cache matches: Double value is stored in uint32_t[2] array. |
| 2230 NearLabel cache_miss; | 2228 Label cache_miss; |
| 2231 __ cmp(ebx, Operand(ecx, 0)); | 2229 __ cmp(ebx, Operand(ecx, 0)); |
| 2232 __ j(not_equal, &cache_miss); | 2230 __ j(not_equal, &cache_miss, Label::kNear); |
| 2233 __ cmp(edx, Operand(ecx, kIntSize)); | 2231 __ cmp(edx, Operand(ecx, kIntSize)); |
| 2234 __ j(not_equal, &cache_miss); | 2232 __ j(not_equal, &cache_miss, Label::kNear); |
| 2235 // Cache hit! | 2233 // Cache hit! |
| 2236 __ mov(eax, Operand(ecx, 2 * kIntSize)); | 2234 __ mov(eax, Operand(ecx, 2 * kIntSize)); |
| 2237 if (tagged) { | 2235 if (tagged) { |
| 2238 __ fstp(0); | 2236 __ fstp(0); |
| 2239 __ ret(kPointerSize); | 2237 __ ret(kPointerSize); |
| 2240 } else { // UNTAGGED. | 2238 } else { // UNTAGGED. |
| 2241 __ movdbl(xmm1, FieldOperand(eax, HeapNumber::kValueOffset)); | 2239 __ movdbl(xmm1, FieldOperand(eax, HeapNumber::kValueOffset)); |
| 2242 __ Ret(); | 2240 __ Ret(); |
| 2243 } | 2241 } |
| 2244 | 2242 |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2322 | 2320 |
| 2323 void TranscendentalCacheStub::GenerateOperation(MacroAssembler* masm) { | 2321 void TranscendentalCacheStub::GenerateOperation(MacroAssembler* masm) { |
| 2324 // Only free register is edi. | 2322 // Only free register is edi. |
| 2325 // Input value is on FP stack, and also in ebx/edx. | 2323 // Input value is on FP stack, and also in ebx/edx. |
| 2326 // Input value is possibly in xmm1. | 2324 // Input value is possibly in xmm1. |
| 2327 // Address of result (a newly allocated HeapNumber) may be in eax. | 2325 // Address of result (a newly allocated HeapNumber) may be in eax. |
| 2328 if (type_ == TranscendentalCache::SIN || type_ == TranscendentalCache::COS) { | 2326 if (type_ == TranscendentalCache::SIN || type_ == TranscendentalCache::COS) { |
| 2329 // Both fsin and fcos require arguments in the range +/-2^63 and | 2327 // Both fsin and fcos require arguments in the range +/-2^63 and |
| 2330 // return NaN for infinities and NaN. They can share all code except | 2328 // return NaN for infinities and NaN. They can share all code except |
| 2331 // the actual fsin/fcos operation. | 2329 // the actual fsin/fcos operation. |
| 2332 NearLabel in_range, done; | 2330 Label in_range, done; |
| 2333 // If argument is outside the range -2^63..2^63, fsin/cos doesn't | 2331 // If argument is outside the range -2^63..2^63, fsin/cos doesn't |
| 2334 // work. We must reduce it to the appropriate range. | 2332 // work. We must reduce it to the appropriate range. |
| 2335 __ mov(edi, edx); | 2333 __ mov(edi, edx); |
| 2336 __ and_(Operand(edi), Immediate(0x7ff00000)); // Exponent only. | 2334 __ and_(Operand(edi), Immediate(0x7ff00000)); // Exponent only. |
| 2337 int supported_exponent_limit = | 2335 int supported_exponent_limit = |
| 2338 (63 + HeapNumber::kExponentBias) << HeapNumber::kExponentShift; | 2336 (63 + HeapNumber::kExponentBias) << HeapNumber::kExponentShift; |
| 2339 __ cmp(Operand(edi), Immediate(supported_exponent_limit)); | 2337 __ cmp(Operand(edi), Immediate(supported_exponent_limit)); |
| 2340 __ j(below, &in_range, taken); | 2338 __ j(below, &in_range, taken, Label::kNear); |
| 2341 // Check for infinity and NaN. Both return NaN for sin. | 2339 // Check for infinity and NaN. Both return NaN for sin. |
| 2342 __ cmp(Operand(edi), Immediate(0x7ff00000)); | 2340 __ cmp(Operand(edi), Immediate(0x7ff00000)); |
| 2343 NearLabel non_nan_result; | 2341 Label non_nan_result; |
| 2344 __ j(not_equal, &non_nan_result, taken); | 2342 __ j(not_equal, &non_nan_result, taken, Label::kNear); |
| 2345 // Input is +/-Infinity or NaN. Result is NaN. | 2343 // Input is +/-Infinity or NaN. Result is NaN. |
| 2346 __ fstp(0); | 2344 __ fstp(0); |
| 2347 // NaN is represented by 0x7ff8000000000000. | 2345 // NaN is represented by 0x7ff8000000000000. |
| 2348 __ push(Immediate(0x7ff80000)); | 2346 __ push(Immediate(0x7ff80000)); |
| 2349 __ push(Immediate(0)); | 2347 __ push(Immediate(0)); |
| 2350 __ fld_d(Operand(esp, 0)); | 2348 __ fld_d(Operand(esp, 0)); |
| 2351 __ add(Operand(esp), Immediate(2 * kPointerSize)); | 2349 __ add(Operand(esp), Immediate(2 * kPointerSize)); |
| 2352 __ jmp(&done); | 2350 __ jmp(&done, Label::kNear); |
| 2353 | 2351 |
| 2354 __ bind(&non_nan_result); | 2352 __ bind(&non_nan_result); |
| 2355 | 2353 |
| 2356 // Use fpmod to restrict argument to the range +/-2*PI. | 2354 // Use fpmod to restrict argument to the range +/-2*PI. |
| 2357 __ mov(edi, eax); // Save eax before using fnstsw_ax. | 2355 __ mov(edi, eax); // Save eax before using fnstsw_ax. |
| 2358 __ fldpi(); | 2356 __ fldpi(); |
| 2359 __ fadd(0); | 2357 __ fadd(0); |
| 2360 __ fld(1); | 2358 __ fld(1); |
| 2361 // FPU Stack: input, 2*pi, input. | 2359 // FPU Stack: input, 2*pi, input. |
| 2362 { | 2360 { |
| 2363 NearLabel no_exceptions; | 2361 Label no_exceptions; |
| 2364 __ fwait(); | 2362 __ fwait(); |
| 2365 __ fnstsw_ax(); | 2363 __ fnstsw_ax(); |
| 2366 // Clear if Illegal Operand or Zero Division exceptions are set. | 2364 // Clear if Illegal Operand or Zero Division exceptions are set. |
| 2367 __ test(Operand(eax), Immediate(5)); | 2365 __ test(Operand(eax), Immediate(5)); |
| 2368 __ j(zero, &no_exceptions); | 2366 __ j(zero, &no_exceptions, Label::kNear); |
| 2369 __ fnclex(); | 2367 __ fnclex(); |
| 2370 __ bind(&no_exceptions); | 2368 __ bind(&no_exceptions); |
| 2371 } | 2369 } |
| 2372 | 2370 |
| 2373 // Compute st(0) % st(1) | 2371 // Compute st(0) % st(1) |
| 2374 { | 2372 { |
| 2375 NearLabel partial_remainder_loop; | 2373 Label partial_remainder_loop; |
| 2376 __ bind(&partial_remainder_loop); | 2374 __ bind(&partial_remainder_loop); |
| 2377 __ fprem1(); | 2375 __ fprem1(); |
| 2378 __ fwait(); | 2376 __ fwait(); |
| 2379 __ fnstsw_ax(); | 2377 __ fnstsw_ax(); |
| 2380 __ test(Operand(eax), Immediate(0x400 /* C2 */)); | 2378 __ test(Operand(eax), Immediate(0x400 /* C2 */)); |
| 2381 // If C2 is set, computation only has partial result. Loop to | 2379 // If C2 is set, computation only has partial result. Loop to |
| 2382 // continue computation. | 2380 // continue computation. |
| 2383 __ j(not_zero, &partial_remainder_loop); | 2381 __ j(not_zero, &partial_remainder_loop); |
| 2384 } | 2382 } |
| 2385 // FPU Stack: input, 2*pi, input % 2*pi | 2383 // FPU Stack: input, 2*pi, input % 2*pi |
| (...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2547 | 2545 |
| 2548 void FloatingPointHelper::CheckLoadedIntegersWereInt32(MacroAssembler* masm, | 2546 void FloatingPointHelper::CheckLoadedIntegersWereInt32(MacroAssembler* masm, |
| 2549 bool use_sse3, | 2547 bool use_sse3, |
| 2550 Label* not_int32) { | 2548 Label* not_int32) { |
| 2551 return; | 2549 return; |
| 2552 } | 2550 } |
| 2553 | 2551 |
| 2554 | 2552 |
| 2555 void FloatingPointHelper::LoadFloatOperand(MacroAssembler* masm, | 2553 void FloatingPointHelper::LoadFloatOperand(MacroAssembler* masm, |
| 2556 Register number) { | 2554 Register number) { |
| 2557 NearLabel load_smi, done; | 2555 Label load_smi, done; |
| 2558 | 2556 |
| 2559 __ test(number, Immediate(kSmiTagMask)); | 2557 __ test(number, Immediate(kSmiTagMask)); |
| 2560 __ j(zero, &load_smi, not_taken); | 2558 __ j(zero, &load_smi, not_taken, Label::kNear); |
| 2561 __ fld_d(FieldOperand(number, HeapNumber::kValueOffset)); | 2559 __ fld_d(FieldOperand(number, HeapNumber::kValueOffset)); |
| 2562 __ jmp(&done); | 2560 __ jmp(&done, Label::kNear); |
| 2563 | 2561 |
| 2564 __ bind(&load_smi); | 2562 __ bind(&load_smi); |
| 2565 __ SmiUntag(number); | 2563 __ SmiUntag(number); |
| 2566 __ push(number); | 2564 __ push(number); |
| 2567 __ fild_s(Operand(esp, 0)); | 2565 __ fild_s(Operand(esp, 0)); |
| 2568 __ pop(number); | 2566 __ pop(number); |
| 2569 | 2567 |
| 2570 __ bind(&done); | 2568 __ bind(&done); |
| 2571 } | 2569 } |
| 2572 | 2570 |
| 2573 | 2571 |
| 2574 void FloatingPointHelper::LoadSSE2Operands(MacroAssembler* masm) { | 2572 void FloatingPointHelper::LoadSSE2Operands(MacroAssembler* masm) { |
| 2575 NearLabel load_smi_edx, load_eax, load_smi_eax, done; | 2573 Label load_smi_edx, load_eax, load_smi_eax, done; |
| 2576 // Load operand in edx into xmm0. | 2574 // Load operand in edx into xmm0. |
| 2577 __ test(edx, Immediate(kSmiTagMask)); | 2575 __ test(edx, Immediate(kSmiTagMask)); |
| 2578 __ j(zero, &load_smi_edx, not_taken); // Argument in edx is a smi. | 2576 // Argument in edx is a smi. |
| 2577 __ j(zero, &load_smi_edx, not_taken, Label::kNear); |
| 2579 __ movdbl(xmm0, FieldOperand(edx, HeapNumber::kValueOffset)); | 2578 __ movdbl(xmm0, FieldOperand(edx, HeapNumber::kValueOffset)); |
| 2580 | 2579 |
| 2581 __ bind(&load_eax); | 2580 __ bind(&load_eax); |
| 2582 // Load operand in eax into xmm1. | 2581 // Load operand in eax into xmm1. |
| 2583 __ test(eax, Immediate(kSmiTagMask)); | 2582 __ test(eax, Immediate(kSmiTagMask)); |
| 2584 __ j(zero, &load_smi_eax, not_taken); // Argument in eax is a smi. | 2583 // Argument in eax is a smi. |
| 2584 __ j(zero, &load_smi_eax, not_taken, Label::kNear); |
| 2585 __ movdbl(xmm1, FieldOperand(eax, HeapNumber::kValueOffset)); | 2585 __ movdbl(xmm1, FieldOperand(eax, HeapNumber::kValueOffset)); |
| 2586 __ jmp(&done); | 2586 __ jmp(&done, Label::kNear); |
| 2587 | 2587 |
| 2588 __ bind(&load_smi_edx); | 2588 __ bind(&load_smi_edx); |
| 2589 __ SmiUntag(edx); // Untag smi before converting to float. | 2589 __ SmiUntag(edx); // Untag smi before converting to float. |
| 2590 __ cvtsi2sd(xmm0, Operand(edx)); | 2590 __ cvtsi2sd(xmm0, Operand(edx)); |
| 2591 __ SmiTag(edx); // Retag smi for heap number overwriting test. | 2591 __ SmiTag(edx); // Retag smi for heap number overwriting test. |
| 2592 __ jmp(&load_eax); | 2592 __ jmp(&load_eax); |
| 2593 | 2593 |
| 2594 __ bind(&load_smi_eax); | 2594 __ bind(&load_smi_eax); |
| 2595 __ SmiUntag(eax); // Untag smi before converting to float. | 2595 __ SmiUntag(eax); // Untag smi before converting to float. |
| 2596 __ cvtsi2sd(xmm1, Operand(eax)); | 2596 __ cvtsi2sd(xmm1, Operand(eax)); |
| 2597 __ SmiTag(eax); // Retag smi for heap number overwriting test. | 2597 __ SmiTag(eax); // Retag smi for heap number overwriting test. |
| 2598 | 2598 |
| 2599 __ bind(&done); | 2599 __ bind(&done); |
| 2600 } | 2600 } |
| 2601 | 2601 |
| 2602 | 2602 |
| 2603 void FloatingPointHelper::LoadSSE2Operands(MacroAssembler* masm, | 2603 void FloatingPointHelper::LoadSSE2Operands(MacroAssembler* masm, |
| 2604 Label* not_numbers) { | 2604 Label* not_numbers) { |
| 2605 NearLabel load_smi_edx, load_eax, load_smi_eax, load_float_eax, done; | 2605 Label load_smi_edx, load_eax, load_smi_eax, load_float_eax, done; |
| 2606 // Load operand in edx into xmm0, or branch to not_numbers. | 2606 // Load operand in edx into xmm0, or branch to not_numbers. |
| 2607 __ test(edx, Immediate(kSmiTagMask)); | 2607 __ test(edx, Immediate(kSmiTagMask)); |
| 2608 __ j(zero, &load_smi_edx, not_taken); // Argument in edx is a smi. | 2608 // Argument in edx is a smi. |
| 2609 __ j(zero, &load_smi_edx, not_taken, Label::kNear); |
| 2609 Factory* factory = masm->isolate()->factory(); | 2610 Factory* factory = masm->isolate()->factory(); |
| 2610 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), factory->heap_number_map()); | 2611 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), factory->heap_number_map()); |
| 2611 __ j(not_equal, not_numbers); // Argument in edx is not a number. | 2612 __ j(not_equal, not_numbers); // Argument in edx is not a number. |
| 2612 __ movdbl(xmm0, FieldOperand(edx, HeapNumber::kValueOffset)); | 2613 __ movdbl(xmm0, FieldOperand(edx, HeapNumber::kValueOffset)); |
| 2613 __ bind(&load_eax); | 2614 __ bind(&load_eax); |
| 2614 // Load operand in eax into xmm1, or branch to not_numbers. | 2615 // Load operand in eax into xmm1, or branch to not_numbers. |
| 2615 __ test(eax, Immediate(kSmiTagMask)); | 2616 __ test(eax, Immediate(kSmiTagMask)); |
| 2616 __ j(zero, &load_smi_eax, not_taken); // Argument in eax is a smi. | 2617 // Argument in eax is a smi. |
| 2618 __ j(zero, &load_smi_eax, not_taken, Label::kNear); |
| 2617 __ cmp(FieldOperand(eax, HeapObject::kMapOffset), factory->heap_number_map()); | 2619 __ cmp(FieldOperand(eax, HeapObject::kMapOffset), factory->heap_number_map()); |
| 2618 __ j(equal, &load_float_eax); | 2620 __ j(equal, &load_float_eax, Label::kNear); |
| 2619 __ jmp(not_numbers); // Argument in eax is not a number. | 2621 __ jmp(not_numbers); // Argument in eax is not a number. |
| 2620 __ bind(&load_smi_edx); | 2622 __ bind(&load_smi_edx); |
| 2621 __ SmiUntag(edx); // Untag smi before converting to float. | 2623 __ SmiUntag(edx); // Untag smi before converting to float. |
| 2622 __ cvtsi2sd(xmm0, Operand(edx)); | 2624 __ cvtsi2sd(xmm0, Operand(edx)); |
| 2623 __ SmiTag(edx); // Retag smi for heap number overwriting test. | 2625 __ SmiTag(edx); // Retag smi for heap number overwriting test. |
| 2624 __ jmp(&load_eax); | 2626 __ jmp(&load_eax); |
| 2625 __ bind(&load_smi_eax); | 2627 __ bind(&load_smi_eax); |
| 2626 __ SmiUntag(eax); // Untag smi before converting to float. | 2628 __ SmiUntag(eax); // Untag smi before converting to float. |
| 2627 __ cvtsi2sd(xmm1, Operand(eax)); | 2629 __ cvtsi2sd(xmm1, Operand(eax)); |
| 2628 __ SmiTag(eax); // Retag smi for heap number overwriting test. | 2630 __ SmiTag(eax); // Retag smi for heap number overwriting test. |
| 2629 __ jmp(&done); | 2631 __ jmp(&done, Label::kNear); |
| 2630 __ bind(&load_float_eax); | 2632 __ bind(&load_float_eax); |
| 2631 __ movdbl(xmm1, FieldOperand(eax, HeapNumber::kValueOffset)); | 2633 __ movdbl(xmm1, FieldOperand(eax, HeapNumber::kValueOffset)); |
| 2632 __ bind(&done); | 2634 __ bind(&done); |
| 2633 } | 2635 } |
| 2634 | 2636 |
| 2635 | 2637 |
| 2636 void FloatingPointHelper::LoadSSE2Smis(MacroAssembler* masm, | 2638 void FloatingPointHelper::LoadSSE2Smis(MacroAssembler* masm, |
| 2637 Register scratch) { | 2639 Register scratch) { |
| 2638 const Register left = edx; | 2640 const Register left = edx; |
| 2639 const Register right = eax; | 2641 const Register right = eax; |
| (...skipping 20 matching lines...) Expand all Loading... |
| 2660 __ cvtsi2sd(xmm2, Operand(scratch)); | 2662 __ cvtsi2sd(xmm2, Operand(scratch)); |
| 2661 __ ucomisd(xmm1, xmm2); | 2663 __ ucomisd(xmm1, xmm2); |
| 2662 __ j(not_zero, non_int32); | 2664 __ j(not_zero, non_int32); |
| 2663 __ j(carry, non_int32); | 2665 __ j(carry, non_int32); |
| 2664 } | 2666 } |
| 2665 | 2667 |
| 2666 | 2668 |
| 2667 void FloatingPointHelper::LoadFloatOperands(MacroAssembler* masm, | 2669 void FloatingPointHelper::LoadFloatOperands(MacroAssembler* masm, |
| 2668 Register scratch, | 2670 Register scratch, |
| 2669 ArgLocation arg_location) { | 2671 ArgLocation arg_location) { |
| 2670 NearLabel load_smi_1, load_smi_2, done_load_1, done; | 2672 Label load_smi_1, load_smi_2, done_load_1, done; |
| 2671 if (arg_location == ARGS_IN_REGISTERS) { | 2673 if (arg_location == ARGS_IN_REGISTERS) { |
| 2672 __ mov(scratch, edx); | 2674 __ mov(scratch, edx); |
| 2673 } else { | 2675 } else { |
| 2674 __ mov(scratch, Operand(esp, 2 * kPointerSize)); | 2676 __ mov(scratch, Operand(esp, 2 * kPointerSize)); |
| 2675 } | 2677 } |
| 2676 __ test(scratch, Immediate(kSmiTagMask)); | 2678 __ test(scratch, Immediate(kSmiTagMask)); |
| 2677 __ j(zero, &load_smi_1, not_taken); | 2679 __ j(zero, &load_smi_1, not_taken, Label::kNear); |
| 2678 __ fld_d(FieldOperand(scratch, HeapNumber::kValueOffset)); | 2680 __ fld_d(FieldOperand(scratch, HeapNumber::kValueOffset)); |
| 2679 __ bind(&done_load_1); | 2681 __ bind(&done_load_1); |
| 2680 | 2682 |
| 2681 if (arg_location == ARGS_IN_REGISTERS) { | 2683 if (arg_location == ARGS_IN_REGISTERS) { |
| 2682 __ mov(scratch, eax); | 2684 __ mov(scratch, eax); |
| 2683 } else { | 2685 } else { |
| 2684 __ mov(scratch, Operand(esp, 1 * kPointerSize)); | 2686 __ mov(scratch, Operand(esp, 1 * kPointerSize)); |
| 2685 } | 2687 } |
| 2686 __ test(scratch, Immediate(kSmiTagMask)); | 2688 __ test(scratch, Immediate(kSmiTagMask)); |
| 2687 __ j(zero, &load_smi_2, not_taken); | 2689 __ j(zero, &load_smi_2, not_taken, Label::kNear); |
| 2688 __ fld_d(FieldOperand(scratch, HeapNumber::kValueOffset)); | 2690 __ fld_d(FieldOperand(scratch, HeapNumber::kValueOffset)); |
| 2689 __ jmp(&done); | 2691 __ jmp(&done, Label::kNear); |
| 2690 | 2692 |
| 2691 __ bind(&load_smi_1); | 2693 __ bind(&load_smi_1); |
| 2692 __ SmiUntag(scratch); | 2694 __ SmiUntag(scratch); |
| 2693 __ push(scratch); | 2695 __ push(scratch); |
| 2694 __ fild_s(Operand(esp, 0)); | 2696 __ fild_s(Operand(esp, 0)); |
| 2695 __ pop(scratch); | 2697 __ pop(scratch); |
| 2696 __ jmp(&done_load_1); | 2698 __ jmp(&done_load_1); |
| 2697 | 2699 |
| 2698 __ bind(&load_smi_2); | 2700 __ bind(&load_smi_2); |
| 2699 __ SmiUntag(scratch); | 2701 __ SmiUntag(scratch); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 2719 __ SmiUntag(scratch); | 2721 __ SmiUntag(scratch); |
| 2720 __ mov(Operand(esp, 0), scratch); | 2722 __ mov(Operand(esp, 0), scratch); |
| 2721 __ fild_s(Operand(esp, 0)); | 2723 __ fild_s(Operand(esp, 0)); |
| 2722 __ pop(scratch); | 2724 __ pop(scratch); |
| 2723 } | 2725 } |
| 2724 | 2726 |
| 2725 | 2727 |
| 2726 void FloatingPointHelper::CheckFloatOperands(MacroAssembler* masm, | 2728 void FloatingPointHelper::CheckFloatOperands(MacroAssembler* masm, |
| 2727 Label* non_float, | 2729 Label* non_float, |
| 2728 Register scratch) { | 2730 Register scratch) { |
| 2729 NearLabel test_other, done; | 2731 Label test_other, done; |
| 2730 // Test if both operands are floats or smi -> scratch=k_is_float; | 2732 // Test if both operands are floats or smi -> scratch=k_is_float; |
| 2731 // Otherwise scratch = k_not_float. | 2733 // Otherwise scratch = k_not_float. |
| 2732 __ test(edx, Immediate(kSmiTagMask)); | 2734 __ test(edx, Immediate(kSmiTagMask)); |
| 2733 __ j(zero, &test_other, not_taken); // argument in edx is OK | 2735 __ j(zero, &test_other, not_taken, Label::kNear); // argument in edx is OK |
| 2734 __ mov(scratch, FieldOperand(edx, HeapObject::kMapOffset)); | 2736 __ mov(scratch, FieldOperand(edx, HeapObject::kMapOffset)); |
| 2735 Factory* factory = masm->isolate()->factory(); | 2737 Factory* factory = masm->isolate()->factory(); |
| 2736 __ cmp(scratch, factory->heap_number_map()); | 2738 __ cmp(scratch, factory->heap_number_map()); |
| 2737 __ j(not_equal, non_float); // argument in edx is not a number -> NaN | 2739 __ j(not_equal, non_float); // argument in edx is not a number -> NaN |
| 2738 | 2740 |
| 2739 __ bind(&test_other); | 2741 __ bind(&test_other); |
| 2740 __ test(eax, Immediate(kSmiTagMask)); | 2742 __ test(eax, Immediate(kSmiTagMask)); |
| 2741 __ j(zero, &done); // argument in eax is OK | 2743 __ j(zero, &done, Label::kNear); // argument in eax is OK |
| 2742 __ mov(scratch, FieldOperand(eax, HeapObject::kMapOffset)); | 2744 __ mov(scratch, FieldOperand(eax, HeapObject::kMapOffset)); |
| 2743 __ cmp(scratch, factory->heap_number_map()); | 2745 __ cmp(scratch, factory->heap_number_map()); |
| 2744 __ j(not_equal, non_float); // argument in eax is not a number -> NaN | 2746 __ j(not_equal, non_float); // argument in eax is not a number -> NaN |
| 2745 | 2747 |
| 2746 // Fall-through: Both operands are numbers. | 2748 // Fall-through: Both operands are numbers. |
| 2747 __ bind(&done); | 2749 __ bind(&done); |
| 2748 } | 2750 } |
| 2749 | 2751 |
| 2750 | 2752 |
| 2751 void FloatingPointHelper::CheckFloatOperandsAreInt32(MacroAssembler* masm, | 2753 void FloatingPointHelper::CheckFloatOperandsAreInt32(MacroAssembler* masm, |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2796 // Optimized version of pow if exponent is a smi. | 2798 // Optimized version of pow if exponent is a smi. |
| 2797 // xmm0 contains the base. | 2799 // xmm0 contains the base. |
| 2798 __ bind(&powi); | 2800 __ bind(&powi); |
| 2799 __ SmiUntag(eax); | 2801 __ SmiUntag(eax); |
| 2800 | 2802 |
| 2801 // Save exponent in base as we need to check if exponent is negative later. | 2803 // Save exponent in base as we need to check if exponent is negative later. |
| 2802 // We know that base and exponent are in different registers. | 2804 // We know that base and exponent are in different registers. |
| 2803 __ mov(edx, eax); | 2805 __ mov(edx, eax); |
| 2804 | 2806 |
| 2805 // Get absolute value of exponent. | 2807 // Get absolute value of exponent. |
| 2806 NearLabel no_neg; | 2808 Label no_neg; |
| 2807 __ cmp(eax, 0); | 2809 __ cmp(eax, 0); |
| 2808 __ j(greater_equal, &no_neg); | 2810 __ j(greater_equal, &no_neg, Label::kNear); |
| 2809 __ neg(eax); | 2811 __ neg(eax); |
| 2810 __ bind(&no_neg); | 2812 __ bind(&no_neg); |
| 2811 | 2813 |
| 2812 // Load xmm1 with 1. | 2814 // Load xmm1 with 1. |
| 2813 __ movsd(xmm1, xmm3); | 2815 __ movsd(xmm1, xmm3); |
| 2814 NearLabel while_true; | 2816 Label while_true; |
| 2815 NearLabel no_multiply; | 2817 Label no_multiply; |
| 2816 | 2818 |
| 2817 __ bind(&while_true); | 2819 __ bind(&while_true); |
| 2818 __ shr(eax, 1); | 2820 __ shr(eax, 1); |
| 2819 __ j(not_carry, &no_multiply); | 2821 __ j(not_carry, &no_multiply, Label::kNear); |
| 2820 __ mulsd(xmm1, xmm0); | 2822 __ mulsd(xmm1, xmm0); |
| 2821 __ bind(&no_multiply); | 2823 __ bind(&no_multiply); |
| 2822 __ mulsd(xmm0, xmm0); | 2824 __ mulsd(xmm0, xmm0); |
| 2823 __ j(not_zero, &while_true); | 2825 __ j(not_zero, &while_true); |
| 2824 | 2826 |
| 2825 // base has the original value of the exponent - if the exponent is | 2827 // base has the original value of the exponent - if the exponent is |
| 2826 // negative return 1/result. | 2828 // negative return 1/result. |
| 2827 __ test(edx, Operand(edx)); | 2829 __ test(edx, Operand(edx)); |
| 2828 __ j(positive, &allocate_return); | 2830 __ j(positive, &allocate_return); |
| 2829 // Special case if xmm1 has reached infinity. | 2831 // Special case if xmm1 has reached infinity. |
| (...skipping 10 matching lines...) Expand all Loading... |
| 2840 // on doubles. | 2842 // on doubles. |
| 2841 __ bind(&exponent_nonsmi); | 2843 __ bind(&exponent_nonsmi); |
| 2842 __ cmp(FieldOperand(eax, HeapObject::kMapOffset), | 2844 __ cmp(FieldOperand(eax, HeapObject::kMapOffset), |
| 2843 factory->heap_number_map()); | 2845 factory->heap_number_map()); |
| 2844 __ j(not_equal, &call_runtime); | 2846 __ j(not_equal, &call_runtime); |
| 2845 __ movdbl(xmm1, FieldOperand(eax, HeapNumber::kValueOffset)); | 2847 __ movdbl(xmm1, FieldOperand(eax, HeapNumber::kValueOffset)); |
| 2846 // Test if exponent is nan. | 2848 // Test if exponent is nan. |
| 2847 __ ucomisd(xmm1, xmm1); | 2849 __ ucomisd(xmm1, xmm1); |
| 2848 __ j(parity_even, &call_runtime); | 2850 __ j(parity_even, &call_runtime); |
| 2849 | 2851 |
| 2850 NearLabel base_not_smi; | 2852 Label base_not_smi; |
| 2851 NearLabel handle_special_cases; | 2853 Label handle_special_cases; |
| 2852 __ test(edx, Immediate(kSmiTagMask)); | 2854 __ test(edx, Immediate(kSmiTagMask)); |
| 2853 __ j(not_zero, &base_not_smi); | 2855 __ j(not_zero, &base_not_smi, Label::kNear); |
| 2854 __ SmiUntag(edx); | 2856 __ SmiUntag(edx); |
| 2855 __ cvtsi2sd(xmm0, Operand(edx)); | 2857 __ cvtsi2sd(xmm0, Operand(edx)); |
| 2856 __ jmp(&handle_special_cases); | 2858 __ jmp(&handle_special_cases, Label::kNear); |
| 2857 | 2859 |
| 2858 __ bind(&base_not_smi); | 2860 __ bind(&base_not_smi); |
| 2859 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), | 2861 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), |
| 2860 factory->heap_number_map()); | 2862 factory->heap_number_map()); |
| 2861 __ j(not_equal, &call_runtime); | 2863 __ j(not_equal, &call_runtime); |
| 2862 __ mov(ecx, FieldOperand(edx, HeapNumber::kExponentOffset)); | 2864 __ mov(ecx, FieldOperand(edx, HeapNumber::kExponentOffset)); |
| 2863 __ and_(ecx, HeapNumber::kExponentMask); | 2865 __ and_(ecx, HeapNumber::kExponentMask); |
| 2864 __ cmp(Operand(ecx), Immediate(HeapNumber::kExponentMask)); | 2866 __ cmp(Operand(ecx), Immediate(HeapNumber::kExponentMask)); |
| 2865 // base is NaN or +/-Infinity | 2867 // base is NaN or +/-Infinity |
| 2866 __ j(greater_equal, &call_runtime); | 2868 __ j(greater_equal, &call_runtime); |
| 2867 __ movdbl(xmm0, FieldOperand(edx, HeapNumber::kValueOffset)); | 2869 __ movdbl(xmm0, FieldOperand(edx, HeapNumber::kValueOffset)); |
| 2868 | 2870 |
| 2869 // base is in xmm0 and exponent is in xmm1. | 2871 // base is in xmm0 and exponent is in xmm1. |
| 2870 __ bind(&handle_special_cases); | 2872 __ bind(&handle_special_cases); |
| 2871 NearLabel not_minus_half; | 2873 Label not_minus_half; |
| 2872 // Test for -0.5. | 2874 // Test for -0.5. |
| 2873 // Load xmm2 with -0.5. | 2875 // Load xmm2 with -0.5. |
| 2874 __ mov(ecx, Immediate(0xBF000000)); | 2876 __ mov(ecx, Immediate(0xBF000000)); |
| 2875 __ movd(xmm2, Operand(ecx)); | 2877 __ movd(xmm2, Operand(ecx)); |
| 2876 __ cvtss2sd(xmm2, xmm2); | 2878 __ cvtss2sd(xmm2, xmm2); |
| 2877 // xmm2 now has -0.5. | 2879 // xmm2 now has -0.5. |
| 2878 __ ucomisd(xmm2, xmm1); | 2880 __ ucomisd(xmm2, xmm1); |
| 2879 __ j(not_equal, ¬_minus_half); | 2881 __ j(not_equal, ¬_minus_half, Label::kNear); |
| 2880 | 2882 |
| 2881 // Calculates reciprocal of square root. | 2883 // Calculates reciprocal of square root. |
| 2882 // sqrtsd returns -0 when input is -0. ECMA spec requires +0. | 2884 // sqrtsd returns -0 when input is -0. ECMA spec requires +0. |
| 2883 __ xorps(xmm1, xmm1); | 2885 __ xorps(xmm1, xmm1); |
| 2884 __ addsd(xmm1, xmm0); | 2886 __ addsd(xmm1, xmm0); |
| 2885 __ sqrtsd(xmm1, xmm1); | 2887 __ sqrtsd(xmm1, xmm1); |
| 2886 __ divsd(xmm3, xmm1); | 2888 __ divsd(xmm3, xmm1); |
| 2887 __ movsd(xmm1, xmm3); | 2889 __ movsd(xmm1, xmm3); |
| 2888 __ jmp(&allocate_return); | 2890 __ jmp(&allocate_return); |
| 2889 | 2891 |
| (...skipping 29 matching lines...) Expand all Loading... |
| 2919 // stack. It is the offset of the last parameter (if any) relative | 2921 // stack. It is the offset of the last parameter (if any) relative |
| 2920 // to the frame pointer. | 2922 // to the frame pointer. |
| 2921 static const int kDisplacement = 1 * kPointerSize; | 2923 static const int kDisplacement = 1 * kPointerSize; |
| 2922 | 2924 |
| 2923 // Check that the key is a smi. | 2925 // Check that the key is a smi. |
| 2924 Label slow; | 2926 Label slow; |
| 2925 __ test(edx, Immediate(kSmiTagMask)); | 2927 __ test(edx, Immediate(kSmiTagMask)); |
| 2926 __ j(not_zero, &slow, not_taken); | 2928 __ j(not_zero, &slow, not_taken); |
| 2927 | 2929 |
| 2928 // Check if the calling frame is an arguments adaptor frame. | 2930 // Check if the calling frame is an arguments adaptor frame. |
| 2929 NearLabel adaptor; | 2931 Label adaptor; |
| 2930 __ mov(ebx, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); | 2932 __ mov(ebx, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); |
| 2931 __ mov(ecx, Operand(ebx, StandardFrameConstants::kContextOffset)); | 2933 __ mov(ecx, Operand(ebx, StandardFrameConstants::kContextOffset)); |
| 2932 __ cmp(Operand(ecx), Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); | 2934 __ cmp(Operand(ecx), Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); |
| 2933 __ j(equal, &adaptor); | 2935 __ j(equal, &adaptor, Label::kNear); |
| 2934 | 2936 |
| 2935 // Check index against formal parameters count limit passed in | 2937 // Check index against formal parameters count limit passed in |
| 2936 // through register eax. Use unsigned comparison to get negative | 2938 // through register eax. Use unsigned comparison to get negative |
| 2937 // check for free. | 2939 // check for free. |
| 2938 __ cmp(edx, Operand(eax)); | 2940 __ cmp(edx, Operand(eax)); |
| 2939 __ j(above_equal, &slow, not_taken); | 2941 __ j(above_equal, &slow, not_taken); |
| 2940 | 2942 |
| 2941 // Read the argument from the stack and return it. | 2943 // Read the argument from the stack and return it. |
| 2942 STATIC_ASSERT(kSmiTagSize == 1); | 2944 STATIC_ASSERT(kSmiTagSize == 1); |
| 2943 STATIC_ASSERT(kSmiTag == 0); // Shifting code depends on these. | 2945 STATIC_ASSERT(kSmiTag == 0); // Shifting code depends on these. |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2996 | 2998 |
| 2997 // Patch the arguments.length and the parameters pointer. | 2999 // Patch the arguments.length and the parameters pointer. |
| 2998 __ bind(&adaptor_frame); | 3000 __ bind(&adaptor_frame); |
| 2999 __ mov(ecx, Operand(edx, ArgumentsAdaptorFrameConstants::kLengthOffset)); | 3001 __ mov(ecx, Operand(edx, ArgumentsAdaptorFrameConstants::kLengthOffset)); |
| 3000 __ mov(Operand(esp, 1 * kPointerSize), ecx); | 3002 __ mov(Operand(esp, 1 * kPointerSize), ecx); |
| 3001 __ lea(edx, Operand(edx, ecx, times_2, kDisplacement)); | 3003 __ lea(edx, Operand(edx, ecx, times_2, kDisplacement)); |
| 3002 __ mov(Operand(esp, 2 * kPointerSize), edx); | 3004 __ mov(Operand(esp, 2 * kPointerSize), edx); |
| 3003 | 3005 |
| 3004 // Try the new space allocation. Start out with computing the size of | 3006 // Try the new space allocation. Start out with computing the size of |
| 3005 // the arguments object and the elements array. | 3007 // the arguments object and the elements array. |
| 3006 NearLabel add_arguments_object; | 3008 Label add_arguments_object; |
| 3007 __ bind(&try_allocate); | 3009 __ bind(&try_allocate); |
| 3008 __ test(ecx, Operand(ecx)); | 3010 __ test(ecx, Operand(ecx)); |
| 3009 __ j(zero, &add_arguments_object); | 3011 __ j(zero, &add_arguments_object, Label::kNear); |
| 3010 __ lea(ecx, Operand(ecx, times_2, FixedArray::kHeaderSize)); | 3012 __ lea(ecx, Operand(ecx, times_2, FixedArray::kHeaderSize)); |
| 3011 __ bind(&add_arguments_object); | 3013 __ bind(&add_arguments_object); |
| 3012 __ add(Operand(ecx), Immediate(GetArgumentsObjectSize())); | 3014 __ add(Operand(ecx), Immediate(GetArgumentsObjectSize())); |
| 3013 | 3015 |
| 3014 // Do the allocation of both objects in one go. | 3016 // Do the allocation of both objects in one go. |
| 3015 __ AllocateInNewSpace(ecx, eax, edx, ebx, &runtime, TAG_OBJECT); | 3017 __ AllocateInNewSpace(ecx, eax, edx, ebx, &runtime, TAG_OBJECT); |
| 3016 | 3018 |
| 3017 // Get the arguments boilerplate from the current (global) context. | 3019 // Get the arguments boilerplate from the current (global) context. |
| 3018 __ mov(edi, Operand(esi, Context::SlotOffset(Context::GLOBAL_INDEX))); | 3020 __ mov(edi, Operand(esi, Context::SlotOffset(Context::GLOBAL_INDEX))); |
| 3019 __ mov(edi, FieldOperand(edi, GlobalObject::kGlobalContextOffset)); | 3021 __ mov(edi, FieldOperand(edi, GlobalObject::kGlobalContextOffset)); |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3055 __ lea(edi, Operand(eax, GetArgumentsObjectSize())); | 3057 __ lea(edi, Operand(eax, GetArgumentsObjectSize())); |
| 3056 __ mov(FieldOperand(eax, JSObject::kElementsOffset), edi); | 3058 __ mov(FieldOperand(eax, JSObject::kElementsOffset), edi); |
| 3057 __ mov(FieldOperand(edi, FixedArray::kMapOffset), | 3059 __ mov(FieldOperand(edi, FixedArray::kMapOffset), |
| 3058 Immediate(masm->isolate()->factory()->fixed_array_map())); | 3060 Immediate(masm->isolate()->factory()->fixed_array_map())); |
| 3059 | 3061 |
| 3060 __ mov(FieldOperand(edi, FixedArray::kLengthOffset), ecx); | 3062 __ mov(FieldOperand(edi, FixedArray::kLengthOffset), ecx); |
| 3061 // Untag the length for the loop below. | 3063 // Untag the length for the loop below. |
| 3062 __ SmiUntag(ecx); | 3064 __ SmiUntag(ecx); |
| 3063 | 3065 |
| 3064 // Copy the fixed array slots. | 3066 // Copy the fixed array slots. |
| 3065 NearLabel loop; | 3067 Label loop; |
| 3066 __ bind(&loop); | 3068 __ bind(&loop); |
| 3067 __ mov(ebx, Operand(edx, -1 * kPointerSize)); // Skip receiver. | 3069 __ mov(ebx, Operand(edx, -1 * kPointerSize)); // Skip receiver. |
| 3068 __ mov(FieldOperand(edi, FixedArray::kHeaderSize), ebx); | 3070 __ mov(FieldOperand(edi, FixedArray::kHeaderSize), ebx); |
| 3069 __ add(Operand(edi), Immediate(kPointerSize)); | 3071 __ add(Operand(edi), Immediate(kPointerSize)); |
| 3070 __ sub(Operand(edx), Immediate(kPointerSize)); | 3072 __ sub(Operand(edx), Immediate(kPointerSize)); |
| 3071 __ dec(ecx); | 3073 __ dec(ecx); |
| 3072 __ j(not_zero, &loop); | 3074 __ j(not_zero, &loop); |
| 3073 | 3075 |
| 3074 // Return and remove the on-stack parameters. | 3076 // Return and remove the on-stack parameters. |
| 3075 __ bind(&done); | 3077 __ bind(&done); |
| (...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3292 __ add(ecx, Operand::StaticVariable(address_of_regexp_stack_memory_size)); | 3294 __ add(ecx, Operand::StaticVariable(address_of_regexp_stack_memory_size)); |
| 3293 __ mov(Operand(esp, 5 * kPointerSize), ecx); | 3295 __ mov(Operand(esp, 5 * kPointerSize), ecx); |
| 3294 | 3296 |
| 3295 // Argument 5: static offsets vector buffer. | 3297 // Argument 5: static offsets vector buffer. |
| 3296 __ mov(Operand(esp, 4 * kPointerSize), | 3298 __ mov(Operand(esp, 4 * kPointerSize), |
| 3297 Immediate(ExternalReference::address_of_static_offsets_vector( | 3299 Immediate(ExternalReference::address_of_static_offsets_vector( |
| 3298 masm->isolate()))); | 3300 masm->isolate()))); |
| 3299 | 3301 |
| 3300 // Argument 4: End of string data | 3302 // Argument 4: End of string data |
| 3301 // Argument 3: Start of string data | 3303 // Argument 3: Start of string data |
| 3302 NearLabel setup_two_byte, setup_rest; | 3304 Label setup_two_byte, setup_rest; |
| 3303 __ test(edi, Operand(edi)); | 3305 __ test(edi, Operand(edi)); |
| 3304 __ mov(edi, FieldOperand(eax, String::kLengthOffset)); | 3306 __ mov(edi, FieldOperand(eax, String::kLengthOffset)); |
| 3305 __ j(zero, &setup_two_byte); | 3307 __ j(zero, &setup_two_byte, Label::kNear); |
| 3306 __ SmiUntag(edi); | 3308 __ SmiUntag(edi); |
| 3307 __ lea(ecx, FieldOperand(eax, edi, times_1, SeqAsciiString::kHeaderSize)); | 3309 __ lea(ecx, FieldOperand(eax, edi, times_1, SeqAsciiString::kHeaderSize)); |
| 3308 __ mov(Operand(esp, 3 * kPointerSize), ecx); // Argument 4. | 3310 __ mov(Operand(esp, 3 * kPointerSize), ecx); // Argument 4. |
| 3309 __ lea(ecx, FieldOperand(eax, ebx, times_1, SeqAsciiString::kHeaderSize)); | 3311 __ lea(ecx, FieldOperand(eax, ebx, times_1, SeqAsciiString::kHeaderSize)); |
| 3310 __ mov(Operand(esp, 2 * kPointerSize), ecx); // Argument 3. | 3312 __ mov(Operand(esp, 2 * kPointerSize), ecx); // Argument 3. |
| 3311 __ jmp(&setup_rest); | 3313 __ jmp(&setup_rest, Label::kNear); |
| 3312 | 3314 |
| 3313 __ bind(&setup_two_byte); | 3315 __ bind(&setup_two_byte); |
| 3314 STATIC_ASSERT(kSmiTag == 0); | 3316 STATIC_ASSERT(kSmiTag == 0); |
| 3315 STATIC_ASSERT(kSmiTagSize == 1); // edi is smi (powered by 2). | 3317 STATIC_ASSERT(kSmiTagSize == 1); // edi is smi (powered by 2). |
| 3316 __ lea(ecx, FieldOperand(eax, edi, times_1, SeqTwoByteString::kHeaderSize)); | 3318 __ lea(ecx, FieldOperand(eax, edi, times_1, SeqTwoByteString::kHeaderSize)); |
| 3317 __ mov(Operand(esp, 3 * kPointerSize), ecx); // Argument 4. | 3319 __ mov(Operand(esp, 3 * kPointerSize), ecx); // Argument 4. |
| 3318 __ lea(ecx, FieldOperand(eax, ebx, times_2, SeqTwoByteString::kHeaderSize)); | 3320 __ lea(ecx, FieldOperand(eax, ebx, times_2, SeqTwoByteString::kHeaderSize)); |
| 3319 __ mov(Operand(esp, 2 * kPointerSize), ecx); // Argument 3. | 3321 __ mov(Operand(esp, 2 * kPointerSize), ecx); // Argument 3. |
| 3320 | 3322 |
| 3321 __ bind(&setup_rest); | 3323 __ bind(&setup_rest); |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3409 __ RecordWrite(ecx, RegExpImpl::kLastInputOffset, eax, edi); | 3411 __ RecordWrite(ecx, RegExpImpl::kLastInputOffset, eax, edi); |
| 3410 | 3412 |
| 3411 // Get the static offsets vector filled by the native regexp code. | 3413 // Get the static offsets vector filled by the native regexp code. |
| 3412 ExternalReference address_of_static_offsets_vector = | 3414 ExternalReference address_of_static_offsets_vector = |
| 3413 ExternalReference::address_of_static_offsets_vector(masm->isolate()); | 3415 ExternalReference::address_of_static_offsets_vector(masm->isolate()); |
| 3414 __ mov(ecx, Immediate(address_of_static_offsets_vector)); | 3416 __ mov(ecx, Immediate(address_of_static_offsets_vector)); |
| 3415 | 3417 |
| 3416 // ebx: last_match_info backing store (FixedArray) | 3418 // ebx: last_match_info backing store (FixedArray) |
| 3417 // ecx: offsets vector | 3419 // ecx: offsets vector |
| 3418 // edx: number of capture registers | 3420 // edx: number of capture registers |
| 3419 NearLabel next_capture, done; | 3421 Label next_capture, done; |
| 3420 // Capture register counter starts from number of capture registers and | 3422 // Capture register counter starts from number of capture registers and |
| 3421 // counts down until wraping after zero. | 3423 // counts down until wraping after zero. |
| 3422 __ bind(&next_capture); | 3424 __ bind(&next_capture); |
| 3423 __ sub(Operand(edx), Immediate(1)); | 3425 __ sub(Operand(edx), Immediate(1)); |
| 3424 __ j(negative, &done); | 3426 __ j(negative, &done, Label::kNear); |
| 3425 // Read the value from the static offsets vector buffer. | 3427 // Read the value from the static offsets vector buffer. |
| 3426 __ mov(edi, Operand(ecx, edx, times_int_size, 0)); | 3428 __ mov(edi, Operand(ecx, edx, times_int_size, 0)); |
| 3427 __ SmiTag(edi); | 3429 __ SmiTag(edi); |
| 3428 // Store the smi value in the last match info. | 3430 // Store the smi value in the last match info. |
| 3429 __ mov(FieldOperand(ebx, | 3431 __ mov(FieldOperand(ebx, |
| 3430 edx, | 3432 edx, |
| 3431 times_pointer_size, | 3433 times_pointer_size, |
| 3432 RegExpImpl::kFirstCaptureOffset), | 3434 RegExpImpl::kFirstCaptureOffset), |
| 3433 edi); | 3435 edi); |
| 3434 __ jmp(&next_capture); | 3436 __ jmp(&next_capture); |
| 3435 __ bind(&done); | 3437 __ bind(&done); |
| 3436 | 3438 |
| 3437 // Return last match info. | 3439 // Return last match info. |
| 3438 __ mov(eax, Operand(esp, kLastMatchInfoOffset)); | 3440 __ mov(eax, Operand(esp, kLastMatchInfoOffset)); |
| 3439 __ ret(4 * kPointerSize); | 3441 __ ret(4 * kPointerSize); |
| 3440 | 3442 |
| 3441 // Do the runtime call to execute the regexp. | 3443 // Do the runtime call to execute the regexp. |
| 3442 __ bind(&runtime); | 3444 __ bind(&runtime); |
| 3443 __ TailCallRuntime(Runtime::kRegExpExec, 4, 1); | 3445 __ TailCallRuntime(Runtime::kRegExpExec, 4, 1); |
| 3444 #endif // V8_INTERPRETED_REGEXP | 3446 #endif // V8_INTERPRETED_REGEXP |
| 3445 } | 3447 } |
| 3446 | 3448 |
| 3447 | 3449 |
| 3448 void RegExpConstructResultStub::Generate(MacroAssembler* masm) { | 3450 void RegExpConstructResultStub::Generate(MacroAssembler* masm) { |
| 3449 const int kMaxInlineLength = 100; | 3451 const int kMaxInlineLength = 100; |
| 3450 Label slowcase; | 3452 Label slowcase; |
| 3451 NearLabel done; | 3453 Label done; |
| 3452 __ mov(ebx, Operand(esp, kPointerSize * 3)); | 3454 __ mov(ebx, Operand(esp, kPointerSize * 3)); |
| 3453 __ test(ebx, Immediate(kSmiTagMask)); | 3455 __ test(ebx, Immediate(kSmiTagMask)); |
| 3454 __ j(not_zero, &slowcase); | 3456 __ j(not_zero, &slowcase); |
| 3455 __ cmp(Operand(ebx), Immediate(Smi::FromInt(kMaxInlineLength))); | 3457 __ cmp(Operand(ebx), Immediate(Smi::FromInt(kMaxInlineLength))); |
| 3456 __ j(above, &slowcase); | 3458 __ j(above, &slowcase); |
| 3457 // Smi-tagging is equivalent to multiplying by 2. | 3459 // Smi-tagging is equivalent to multiplying by 2. |
| 3458 STATIC_ASSERT(kSmiTag == 0); | 3460 STATIC_ASSERT(kSmiTag == 0); |
| 3459 STATIC_ASSERT(kSmiTagSize == 1); | 3461 STATIC_ASSERT(kSmiTagSize == 1); |
| 3460 // Allocate RegExpResult followed by FixedArray with size in ebx. | 3462 // Allocate RegExpResult followed by FixedArray with size in ebx. |
| 3461 // JSArray: [Map][empty properties][Elements][Length-smi][index][input] | 3463 // JSArray: [Map][empty properties][Elements][Length-smi][index][input] |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3507 __ mov(edx, Immediate(factory->the_hole_value())); | 3509 __ mov(edx, Immediate(factory->the_hole_value())); |
| 3508 __ lea(ebx, FieldOperand(ebx, FixedArray::kHeaderSize)); | 3510 __ lea(ebx, FieldOperand(ebx, FixedArray::kHeaderSize)); |
| 3509 // Fill fixed array elements with hole. | 3511 // Fill fixed array elements with hole. |
| 3510 // eax: JSArray. | 3512 // eax: JSArray. |
| 3511 // ecx: Number of elements to fill. | 3513 // ecx: Number of elements to fill. |
| 3512 // ebx: Start of elements in FixedArray. | 3514 // ebx: Start of elements in FixedArray. |
| 3513 // edx: the hole. | 3515 // edx: the hole. |
| 3514 Label loop; | 3516 Label loop; |
| 3515 __ test(ecx, Operand(ecx)); | 3517 __ test(ecx, Operand(ecx)); |
| 3516 __ bind(&loop); | 3518 __ bind(&loop); |
| 3517 __ j(less_equal, &done); // Jump if ecx is negative or zero. | 3519 __ j(less_equal, &done, Label::kNear); // Jump if ecx is negative or zero. |
| 3518 __ sub(Operand(ecx), Immediate(1)); | 3520 __ sub(Operand(ecx), Immediate(1)); |
| 3519 __ mov(Operand(ebx, ecx, times_pointer_size, 0), edx); | 3521 __ mov(Operand(ebx, ecx, times_pointer_size, 0), edx); |
| 3520 __ jmp(&loop); | 3522 __ jmp(&loop); |
| 3521 | 3523 |
| 3522 __ bind(&done); | 3524 __ bind(&done); |
| 3523 __ ret(3 * kPointerSize); | 3525 __ ret(3 * kPointerSize); |
| 3524 | 3526 |
| 3525 __ bind(&slowcase); | 3527 __ bind(&slowcase); |
| 3526 __ TailCallRuntime(Runtime::kRegExpConstructResult, 3, 1); | 3528 __ TailCallRuntime(Runtime::kRegExpConstructResult, 3, 1); |
| 3527 } | 3529 } |
| (...skipping 20 matching lines...) Expand all Loading... |
| 3548 // Make the hash mask from the length of the number string cache. It | 3550 // Make the hash mask from the length of the number string cache. It |
| 3549 // contains two elements (number and string) for each cache entry. | 3551 // contains two elements (number and string) for each cache entry. |
| 3550 __ mov(mask, FieldOperand(number_string_cache, FixedArray::kLengthOffset)); | 3552 __ mov(mask, FieldOperand(number_string_cache, FixedArray::kLengthOffset)); |
| 3551 __ shr(mask, kSmiTagSize + 1); // Untag length and divide it by two. | 3553 __ shr(mask, kSmiTagSize + 1); // Untag length and divide it by two. |
| 3552 __ sub(Operand(mask), Immediate(1)); // Make mask. | 3554 __ sub(Operand(mask), Immediate(1)); // Make mask. |
| 3553 | 3555 |
| 3554 // Calculate the entry in the number string cache. The hash value in the | 3556 // Calculate the entry in the number string cache. The hash value in the |
| 3555 // number string cache for smis is just the smi value, and the hash for | 3557 // number string cache for smis is just the smi value, and the hash for |
| 3556 // doubles is the xor of the upper and lower words. See | 3558 // doubles is the xor of the upper and lower words. See |
| 3557 // Heap::GetNumberStringCache. | 3559 // Heap::GetNumberStringCache. |
| 3558 NearLabel smi_hash_calculated; | 3560 Label smi_hash_calculated; |
| 3559 NearLabel load_result_from_cache; | 3561 Label load_result_from_cache; |
| 3560 if (object_is_smi) { | 3562 if (object_is_smi) { |
| 3561 __ mov(scratch, object); | 3563 __ mov(scratch, object); |
| 3562 __ SmiUntag(scratch); | 3564 __ SmiUntag(scratch); |
| 3563 } else { | 3565 } else { |
| 3564 NearLabel not_smi, hash_calculated; | 3566 Label not_smi; |
| 3565 STATIC_ASSERT(kSmiTag == 0); | 3567 STATIC_ASSERT(kSmiTag == 0); |
| 3566 __ test(object, Immediate(kSmiTagMask)); | 3568 __ test(object, Immediate(kSmiTagMask)); |
| 3567 __ j(not_zero, ¬_smi); | 3569 __ j(not_zero, ¬_smi, Label::kNear); |
| 3568 __ mov(scratch, object); | 3570 __ mov(scratch, object); |
| 3569 __ SmiUntag(scratch); | 3571 __ SmiUntag(scratch); |
| 3570 __ jmp(&smi_hash_calculated); | 3572 __ jmp(&smi_hash_calculated, Label::kNear); |
| 3571 __ bind(¬_smi); | 3573 __ bind(¬_smi); |
| 3572 __ cmp(FieldOperand(object, HeapObject::kMapOffset), | 3574 __ cmp(FieldOperand(object, HeapObject::kMapOffset), |
| 3573 masm->isolate()->factory()->heap_number_map()); | 3575 masm->isolate()->factory()->heap_number_map()); |
| 3574 __ j(not_equal, not_found); | 3576 __ j(not_equal, not_found); |
| 3575 STATIC_ASSERT(8 == kDoubleSize); | 3577 STATIC_ASSERT(8 == kDoubleSize); |
| 3576 __ mov(scratch, FieldOperand(object, HeapNumber::kValueOffset)); | 3578 __ mov(scratch, FieldOperand(object, HeapNumber::kValueOffset)); |
| 3577 __ xor_(scratch, FieldOperand(object, HeapNumber::kValueOffset + 4)); | 3579 __ xor_(scratch, FieldOperand(object, HeapNumber::kValueOffset + 4)); |
| 3578 // Object is heap number and hash is now in scratch. Calculate cache index. | 3580 // Object is heap number and hash is now in scratch. Calculate cache index. |
| 3579 __ and_(scratch, Operand(mask)); | 3581 __ and_(scratch, Operand(mask)); |
| 3580 Register index = scratch; | 3582 Register index = scratch; |
| (...skipping 10 matching lines...) Expand all Loading... |
| 3591 __ movdbl(xmm0, FieldOperand(object, HeapNumber::kValueOffset)); | 3593 __ movdbl(xmm0, FieldOperand(object, HeapNumber::kValueOffset)); |
| 3592 __ movdbl(xmm1, FieldOperand(probe, HeapNumber::kValueOffset)); | 3594 __ movdbl(xmm1, FieldOperand(probe, HeapNumber::kValueOffset)); |
| 3593 __ ucomisd(xmm0, xmm1); | 3595 __ ucomisd(xmm0, xmm1); |
| 3594 } else { | 3596 } else { |
| 3595 __ fld_d(FieldOperand(object, HeapNumber::kValueOffset)); | 3597 __ fld_d(FieldOperand(object, HeapNumber::kValueOffset)); |
| 3596 __ fld_d(FieldOperand(probe, HeapNumber::kValueOffset)); | 3598 __ fld_d(FieldOperand(probe, HeapNumber::kValueOffset)); |
| 3597 __ FCmp(); | 3599 __ FCmp(); |
| 3598 } | 3600 } |
| 3599 __ j(parity_even, not_found); // Bail out if NaN is involved. | 3601 __ j(parity_even, not_found); // Bail out if NaN is involved. |
| 3600 __ j(not_equal, not_found); // The cache did not contain this value. | 3602 __ j(not_equal, not_found); // The cache did not contain this value. |
| 3601 __ jmp(&load_result_from_cache); | 3603 __ jmp(&load_result_from_cache, Label::kNear); |
| 3602 } | 3604 } |
| 3603 | 3605 |
| 3604 __ bind(&smi_hash_calculated); | 3606 __ bind(&smi_hash_calculated); |
| 3605 // Object is smi and hash is now in scratch. Calculate cache index. | 3607 // Object is smi and hash is now in scratch. Calculate cache index. |
| 3606 __ and_(scratch, Operand(mask)); | 3608 __ and_(scratch, Operand(mask)); |
| 3607 Register index = scratch; | 3609 Register index = scratch; |
| 3608 // Check if the entry is the smi we are looking for. | 3610 // Check if the entry is the smi we are looking for. |
| 3609 __ cmp(object, | 3611 __ cmp(object, |
| 3610 FieldOperand(number_string_cache, | 3612 FieldOperand(number_string_cache, |
| 3611 index, | 3613 index, |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3679 // Identical objects can be compared fast, but there are some tricky cases | 3681 // Identical objects can be compared fast, but there are some tricky cases |
| 3680 // for NaN and undefined. | 3682 // for NaN and undefined. |
| 3681 { | 3683 { |
| 3682 Label not_identical; | 3684 Label not_identical; |
| 3683 __ cmp(eax, Operand(edx)); | 3685 __ cmp(eax, Operand(edx)); |
| 3684 __ j(not_equal, ¬_identical); | 3686 __ j(not_equal, ¬_identical); |
| 3685 | 3687 |
| 3686 if (cc_ != equal) { | 3688 if (cc_ != equal) { |
| 3687 // Check for undefined. undefined OP undefined is false even though | 3689 // Check for undefined. undefined OP undefined is false even though |
| 3688 // undefined == undefined. | 3690 // undefined == undefined. |
| 3689 NearLabel check_for_nan; | 3691 Label check_for_nan; |
| 3690 __ cmp(edx, masm->isolate()->factory()->undefined_value()); | 3692 __ cmp(edx, masm->isolate()->factory()->undefined_value()); |
| 3691 __ j(not_equal, &check_for_nan); | 3693 __ j(not_equal, &check_for_nan, Label::kNear); |
| 3692 __ Set(eax, Immediate(Smi::FromInt(NegativeComparisonResult(cc_)))); | 3694 __ Set(eax, Immediate(Smi::FromInt(NegativeComparisonResult(cc_)))); |
| 3693 __ ret(0); | 3695 __ ret(0); |
| 3694 __ bind(&check_for_nan); | 3696 __ bind(&check_for_nan); |
| 3695 } | 3697 } |
| 3696 | 3698 |
| 3697 // Test for NaN. Sadly, we can't just compare to factory->nan_value(), | 3699 // Test for NaN. Sadly, we can't just compare to factory->nan_value(), |
| 3698 // so we do the second best thing - test it ourselves. | 3700 // so we do the second best thing - test it ourselves. |
| 3699 // Note: if cc_ != equal, never_nan_nan_ is not used. | 3701 // Note: if cc_ != equal, never_nan_nan_ is not used. |
| 3700 if (never_nan_nan_ && (cc_ == equal)) { | 3702 if (never_nan_nan_ && (cc_ == equal)) { |
| 3701 __ Set(eax, Immediate(Smi::FromInt(EQUAL))); | 3703 __ Set(eax, Immediate(Smi::FromInt(EQUAL))); |
| 3702 __ ret(0); | 3704 __ ret(0); |
| 3703 } else { | 3705 } else { |
| 3704 NearLabel heap_number; | 3706 Label heap_number; |
| 3705 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), | 3707 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), |
| 3706 Immediate(masm->isolate()->factory()->heap_number_map())); | 3708 Immediate(masm->isolate()->factory()->heap_number_map())); |
| 3707 __ j(equal, &heap_number); | 3709 __ j(equal, &heap_number, Label::kNear); |
| 3708 if (cc_ != equal) { | 3710 if (cc_ != equal) { |
| 3709 // Call runtime on identical JSObjects. Otherwise return equal. | 3711 // Call runtime on identical JSObjects. Otherwise return equal. |
| 3710 __ CmpObjectType(eax, FIRST_JS_OBJECT_TYPE, ecx); | 3712 __ CmpObjectType(eax, FIRST_JS_OBJECT_TYPE, ecx); |
| 3711 __ j(above_equal, ¬_identical); | 3713 __ j(above_equal, ¬_identical); |
| 3712 } | 3714 } |
| 3713 __ Set(eax, Immediate(Smi::FromInt(EQUAL))); | 3715 __ Set(eax, Immediate(Smi::FromInt(EQUAL))); |
| 3714 __ ret(0); | 3716 __ ret(0); |
| 3715 | 3717 |
| 3716 __ bind(&heap_number); | 3718 __ bind(&heap_number); |
| 3717 // It is a heap number, so return non-equal if it's NaN and equal if | 3719 // It is a heap number, so return non-equal if it's NaN and equal if |
| (...skipping 11 matching lines...) Expand all Loading... |
| 3729 __ Set(eax, Immediate(0)); | 3731 __ Set(eax, Immediate(0)); |
| 3730 // Shift value and mask so kQuietNaNHighBitsMask applies to topmost | 3732 // Shift value and mask so kQuietNaNHighBitsMask applies to topmost |
| 3731 // bits. | 3733 // bits. |
| 3732 __ add(edx, Operand(edx)); | 3734 __ add(edx, Operand(edx)); |
| 3733 __ cmp(edx, kQuietNaNHighBitsMask << 1); | 3735 __ cmp(edx, kQuietNaNHighBitsMask << 1); |
| 3734 if (cc_ == equal) { | 3736 if (cc_ == equal) { |
| 3735 STATIC_ASSERT(EQUAL != 1); | 3737 STATIC_ASSERT(EQUAL != 1); |
| 3736 __ setcc(above_equal, eax); | 3738 __ setcc(above_equal, eax); |
| 3737 __ ret(0); | 3739 __ ret(0); |
| 3738 } else { | 3740 } else { |
| 3739 NearLabel nan; | 3741 Label nan; |
| 3740 __ j(above_equal, &nan); | 3742 __ j(above_equal, &nan, Label::kNear); |
| 3741 __ Set(eax, Immediate(Smi::FromInt(EQUAL))); | 3743 __ Set(eax, Immediate(Smi::FromInt(EQUAL))); |
| 3742 __ ret(0); | 3744 __ ret(0); |
| 3743 __ bind(&nan); | 3745 __ bind(&nan); |
| 3744 __ Set(eax, Immediate(Smi::FromInt(NegativeComparisonResult(cc_)))); | 3746 __ Set(eax, Immediate(Smi::FromInt(NegativeComparisonResult(cc_)))); |
| 3745 __ ret(0); | 3747 __ ret(0); |
| 3746 } | 3748 } |
| 3747 } | 3749 } |
| 3748 | 3750 |
| 3749 __ bind(¬_identical); | 3751 __ bind(¬_identical); |
| 3750 } | 3752 } |
| 3751 | 3753 |
| 3752 // Strict equality can quickly decide whether objects are equal. | 3754 // Strict equality can quickly decide whether objects are equal. |
| 3753 // Non-strict object equality is slower, so it is handled later in the stub. | 3755 // Non-strict object equality is slower, so it is handled later in the stub. |
| 3754 if (cc_ == equal && strict_) { | 3756 if (cc_ == equal && strict_) { |
| 3755 Label slow; // Fallthrough label. | 3757 Label slow; // Fallthrough label. |
| 3756 NearLabel not_smis; | 3758 Label not_smis; |
| 3757 // If we're doing a strict equality comparison, we don't have to do | 3759 // If we're doing a strict equality comparison, we don't have to do |
| 3758 // type conversion, so we generate code to do fast comparison for objects | 3760 // type conversion, so we generate code to do fast comparison for objects |
| 3759 // and oddballs. Non-smi numbers and strings still go through the usual | 3761 // and oddballs. Non-smi numbers and strings still go through the usual |
| 3760 // slow-case code. | 3762 // slow-case code. |
| 3761 // If either is a Smi (we know that not both are), then they can only | 3763 // If either is a Smi (we know that not both are), then they can only |
| 3762 // be equal if the other is a HeapNumber. If so, use the slow case. | 3764 // be equal if the other is a HeapNumber. If so, use the slow case. |
| 3763 STATIC_ASSERT(kSmiTag == 0); | 3765 STATIC_ASSERT(kSmiTag == 0); |
| 3764 ASSERT_EQ(0, Smi::FromInt(0)); | 3766 ASSERT_EQ(0, Smi::FromInt(0)); |
| 3765 __ mov(ecx, Immediate(kSmiTagMask)); | 3767 __ mov(ecx, Immediate(kSmiTagMask)); |
| 3766 __ and_(ecx, Operand(eax)); | 3768 __ and_(ecx, Operand(eax)); |
| 3767 __ test(ecx, Operand(edx)); | 3769 __ test(ecx, Operand(edx)); |
| 3768 __ j(not_zero, ¬_smis); | 3770 __ j(not_zero, ¬_smis, Label::kNear); |
| 3769 // One operand is a smi. | 3771 // One operand is a smi. |
| 3770 | 3772 |
| 3771 // Check whether the non-smi is a heap number. | 3773 // Check whether the non-smi is a heap number. |
| 3772 STATIC_ASSERT(kSmiTagMask == 1); | 3774 STATIC_ASSERT(kSmiTagMask == 1); |
| 3773 // ecx still holds eax & kSmiTag, which is either zero or one. | 3775 // ecx still holds eax & kSmiTag, which is either zero or one. |
| 3774 __ sub(Operand(ecx), Immediate(0x01)); | 3776 __ sub(Operand(ecx), Immediate(0x01)); |
| 3775 __ mov(ebx, edx); | 3777 __ mov(ebx, edx); |
| 3776 __ xor_(ebx, Operand(eax)); | 3778 __ xor_(ebx, Operand(eax)); |
| 3777 __ and_(ebx, Operand(ecx)); // ebx holds either 0 or eax ^ edx. | 3779 __ and_(ebx, Operand(ecx)); // ebx holds either 0 or eax ^ edx. |
| 3778 __ xor_(ebx, Operand(eax)); | 3780 __ xor_(ebx, Operand(eax)); |
| 3779 // if eax was smi, ebx is now edx, else eax. | 3781 // if eax was smi, ebx is now edx, else eax. |
| 3780 | 3782 |
| 3781 // Check if the non-smi operand is a heap number. | 3783 // Check if the non-smi operand is a heap number. |
| 3782 __ cmp(FieldOperand(ebx, HeapObject::kMapOffset), | 3784 __ cmp(FieldOperand(ebx, HeapObject::kMapOffset), |
| 3783 Immediate(masm->isolate()->factory()->heap_number_map())); | 3785 Immediate(masm->isolate()->factory()->heap_number_map())); |
| 3784 // If heap number, handle it in the slow case. | 3786 // If heap number, handle it in the slow case. |
| 3785 __ j(equal, &slow); | 3787 __ j(equal, &slow); |
| 3786 // Return non-equal (ebx is not zero) | 3788 // Return non-equal (ebx is not zero) |
| 3787 __ mov(eax, ebx); | 3789 __ mov(eax, ebx); |
| 3788 __ ret(0); | 3790 __ ret(0); |
| 3789 | 3791 |
| 3790 __ bind(¬_smis); | 3792 __ bind(¬_smis); |
| 3791 // If either operand is a JSObject or an oddball value, then they are not | 3793 // If either operand is a JSObject or an oddball value, then they are not |
| 3792 // equal since their pointers are different | 3794 // equal since their pointers are different |
| 3793 // There is no test for undetectability in strict equality. | 3795 // There is no test for undetectability in strict equality. |
| 3794 | 3796 |
| 3795 // Get the type of the first operand. | 3797 // Get the type of the first operand. |
| 3796 // If the first object is a JS object, we have done pointer comparison. | 3798 // If the first object is a JS object, we have done pointer comparison. |
| 3797 NearLabel first_non_object; | 3799 Label first_non_object; |
| 3798 STATIC_ASSERT(LAST_TYPE == JS_FUNCTION_TYPE); | 3800 STATIC_ASSERT(LAST_TYPE == JS_FUNCTION_TYPE); |
| 3799 __ CmpObjectType(eax, FIRST_JS_OBJECT_TYPE, ecx); | 3801 __ CmpObjectType(eax, FIRST_JS_OBJECT_TYPE, ecx); |
| 3800 __ j(below, &first_non_object); | 3802 __ j(below, &first_non_object, Label::kNear); |
| 3801 | 3803 |
| 3802 // Return non-zero (eax is not zero) | 3804 // Return non-zero (eax is not zero) |
| 3803 NearLabel return_not_equal; | 3805 Label return_not_equal; |
| 3804 STATIC_ASSERT(kHeapObjectTag != 0); | 3806 STATIC_ASSERT(kHeapObjectTag != 0); |
| 3805 __ bind(&return_not_equal); | 3807 __ bind(&return_not_equal); |
| 3806 __ ret(0); | 3808 __ ret(0); |
| 3807 | 3809 |
| 3808 __ bind(&first_non_object); | 3810 __ bind(&first_non_object); |
| 3809 // Check for oddballs: true, false, null, undefined. | 3811 // Check for oddballs: true, false, null, undefined. |
| 3810 __ CmpInstanceType(ecx, ODDBALL_TYPE); | 3812 __ CmpInstanceType(ecx, ODDBALL_TYPE); |
| 3811 __ j(equal, &return_not_equal); | 3813 __ j(equal, &return_not_equal); |
| 3812 | 3814 |
| 3813 __ CmpObjectType(edx, FIRST_JS_OBJECT_TYPE, ecx); | 3815 __ CmpObjectType(edx, FIRST_JS_OBJECT_TYPE, ecx); |
| (...skipping 30 matching lines...) Expand all Loading... |
| 3844 } else { | 3846 } else { |
| 3845 FloatingPointHelper::CheckFloatOperands( | 3847 FloatingPointHelper::CheckFloatOperands( |
| 3846 masm, &non_number_comparison, ebx); | 3848 masm, &non_number_comparison, ebx); |
| 3847 FloatingPointHelper::LoadFloatOperand(masm, eax); | 3849 FloatingPointHelper::LoadFloatOperand(masm, eax); |
| 3848 FloatingPointHelper::LoadFloatOperand(masm, edx); | 3850 FloatingPointHelper::LoadFloatOperand(masm, edx); |
| 3849 __ FCmp(); | 3851 __ FCmp(); |
| 3850 | 3852 |
| 3851 // Don't base result on EFLAGS when a NaN is involved. | 3853 // Don't base result on EFLAGS when a NaN is involved. |
| 3852 __ j(parity_even, &unordered, not_taken); | 3854 __ j(parity_even, &unordered, not_taken); |
| 3853 | 3855 |
| 3854 NearLabel below_label, above_label; | 3856 Label below_label, above_label; |
| 3855 // Return a result of -1, 0, or 1, based on EFLAGS. | 3857 // Return a result of -1, 0, or 1, based on EFLAGS. |
| 3856 __ j(below, &below_label, not_taken); | 3858 __ j(below, &below_label, not_taken); |
| 3857 __ j(above, &above_label, not_taken); | 3859 __ j(above, &above_label, not_taken); |
| 3858 | 3860 |
| 3859 __ Set(eax, Immediate(0)); | 3861 __ Set(eax, Immediate(0)); |
| 3860 __ ret(0); | 3862 __ ret(0); |
| 3861 | 3863 |
| 3862 __ bind(&below_label); | 3864 __ bind(&below_label); |
| 3863 __ mov(eax, Immediate(Smi::FromInt(-1))); | 3865 __ mov(eax, Immediate(Smi::FromInt(-1))); |
| 3864 __ ret(0); | 3866 __ ret(0); |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3917 } | 3919 } |
| 3918 #ifdef DEBUG | 3920 #ifdef DEBUG |
| 3919 __ Abort("Unexpected fall-through from string comparison"); | 3921 __ Abort("Unexpected fall-through from string comparison"); |
| 3920 #endif | 3922 #endif |
| 3921 | 3923 |
| 3922 __ bind(&check_unequal_objects); | 3924 __ bind(&check_unequal_objects); |
| 3923 if (cc_ == equal && !strict_) { | 3925 if (cc_ == equal && !strict_) { |
| 3924 // Non-strict equality. Objects are unequal if | 3926 // Non-strict equality. Objects are unequal if |
| 3925 // they are both JSObjects and not undetectable, | 3927 // they are both JSObjects and not undetectable, |
| 3926 // and their pointers are different. | 3928 // and their pointers are different. |
| 3927 NearLabel not_both_objects; | 3929 Label not_both_objects; |
| 3928 NearLabel return_unequal; | 3930 Label return_unequal; |
| 3929 // At most one is a smi, so we can test for smi by adding the two. | 3931 // At most one is a smi, so we can test for smi by adding the two. |
| 3930 // A smi plus a heap object has the low bit set, a heap object plus | 3932 // A smi plus a heap object has the low bit set, a heap object plus |
| 3931 // a heap object has the low bit clear. | 3933 // a heap object has the low bit clear. |
| 3932 STATIC_ASSERT(kSmiTag == 0); | 3934 STATIC_ASSERT(kSmiTag == 0); |
| 3933 STATIC_ASSERT(kSmiTagMask == 1); | 3935 STATIC_ASSERT(kSmiTagMask == 1); |
| 3934 __ lea(ecx, Operand(eax, edx, times_1, 0)); | 3936 __ lea(ecx, Operand(eax, edx, times_1, 0)); |
| 3935 __ test(ecx, Immediate(kSmiTagMask)); | 3937 __ test(ecx, Immediate(kSmiTagMask)); |
| 3936 __ j(not_zero, ¬_both_objects); | 3938 __ j(not_zero, ¬_both_objects, Label::kNear); |
| 3937 __ CmpObjectType(eax, FIRST_JS_OBJECT_TYPE, ecx); | 3939 __ CmpObjectType(eax, FIRST_JS_OBJECT_TYPE, ecx); |
| 3938 __ j(below, ¬_both_objects); | 3940 __ j(below, ¬_both_objects, Label::kNear); |
| 3939 __ CmpObjectType(edx, FIRST_JS_OBJECT_TYPE, ebx); | 3941 __ CmpObjectType(edx, FIRST_JS_OBJECT_TYPE, ebx); |
| 3940 __ j(below, ¬_both_objects); | 3942 __ j(below, ¬_both_objects, Label::kNear); |
| 3941 // We do not bail out after this point. Both are JSObjects, and | 3943 // We do not bail out after this point. Both are JSObjects, and |
| 3942 // they are equal if and only if both are undetectable. | 3944 // they are equal if and only if both are undetectable. |
| 3943 // The and of the undetectable flags is 1 if and only if they are equal. | 3945 // The and of the undetectable flags is 1 if and only if they are equal. |
| 3944 __ test_b(FieldOperand(ecx, Map::kBitFieldOffset), | 3946 __ test_b(FieldOperand(ecx, Map::kBitFieldOffset), |
| 3945 1 << Map::kIsUndetectable); | 3947 1 << Map::kIsUndetectable); |
| 3946 __ j(zero, &return_unequal); | 3948 __ j(zero, &return_unequal, Label::kNear); |
| 3947 __ test_b(FieldOperand(ebx, Map::kBitFieldOffset), | 3949 __ test_b(FieldOperand(ebx, Map::kBitFieldOffset), |
| 3948 1 << Map::kIsUndetectable); | 3950 1 << Map::kIsUndetectable); |
| 3949 __ j(zero, &return_unequal); | 3951 __ j(zero, &return_unequal, Label::kNear); |
| 3950 // The objects are both undetectable, so they both compare as the value | 3952 // The objects are both undetectable, so they both compare as the value |
| 3951 // undefined, and are equal. | 3953 // undefined, and are equal. |
| 3952 __ Set(eax, Immediate(EQUAL)); | 3954 __ Set(eax, Immediate(EQUAL)); |
| 3953 __ bind(&return_unequal); | 3955 __ bind(&return_unequal); |
| 3954 // Return non-equal by returning the non-zero object pointer in eax, | 3956 // Return non-equal by returning the non-zero object pointer in eax, |
| 3955 // or return equal if we fell through to here. | 3957 // or return equal if we fell through to here. |
| 3956 __ ret(0); // rax, rdx were pushed | 3958 __ ret(0); // rax, rdx were pushed |
| 3957 __ bind(¬_both_objects); | 3959 __ bind(¬_both_objects); |
| 3958 } | 3960 } |
| 3959 | 3961 |
| (...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4112 __ call(Operand(ebx)); | 4114 __ call(Operand(ebx)); |
| 4113 // Result is in eax or edx:eax - do not destroy these registers! | 4115 // Result is in eax or edx:eax - do not destroy these registers! |
| 4114 | 4116 |
| 4115 if (always_allocate_scope) { | 4117 if (always_allocate_scope) { |
| 4116 __ dec(Operand::StaticVariable(scope_depth)); | 4118 __ dec(Operand::StaticVariable(scope_depth)); |
| 4117 } | 4119 } |
| 4118 | 4120 |
| 4119 // Make sure we're not trying to return 'the hole' from the runtime | 4121 // Make sure we're not trying to return 'the hole' from the runtime |
| 4120 // call as this may lead to crashes in the IC code later. | 4122 // call as this may lead to crashes in the IC code later. |
| 4121 if (FLAG_debug_code) { | 4123 if (FLAG_debug_code) { |
| 4122 NearLabel okay; | 4124 Label okay; |
| 4123 __ cmp(eax, masm->isolate()->factory()->the_hole_value()); | 4125 __ cmp(eax, masm->isolate()->factory()->the_hole_value()); |
| 4124 __ j(not_equal, &okay); | 4126 __ j(not_equal, &okay, Label::kNear); |
| 4125 __ int3(); | 4127 __ int3(); |
| 4126 __ bind(&okay); | 4128 __ bind(&okay); |
| 4127 } | 4129 } |
| 4128 | 4130 |
| 4129 // Check for failure result. | 4131 // Check for failure result. |
| 4130 Label failure_returned; | 4132 Label failure_returned; |
| 4131 STATIC_ASSERT(((kFailureTag + 1) & kFailureTagMask) == 0); | 4133 STATIC_ASSERT(((kFailureTag + 1) & kFailureTagMask) == 0); |
| 4132 __ lea(ecx, Operand(eax, 1)); | 4134 __ lea(ecx, Operand(eax, 1)); |
| 4133 // Lower 2 bits of ecx are 0 iff eax has failure tag. | 4135 // Lower 2 bits of ecx are 0 iff eax has failure tag. |
| 4134 __ test(ecx, Immediate(kFailureTagMask)); | 4136 __ test(ecx, Immediate(kFailureTagMask)); |
| 4135 __ j(zero, &failure_returned, not_taken); | 4137 __ j(zero, &failure_returned, not_taken); |
| 4136 | 4138 |
| 4137 ExternalReference pending_exception_address( | 4139 ExternalReference pending_exception_address( |
| 4138 Isolate::k_pending_exception_address, masm->isolate()); | 4140 Isolate::k_pending_exception_address, masm->isolate()); |
| 4139 | 4141 |
| 4140 // Check that there is no pending exception, otherwise we | 4142 // Check that there is no pending exception, otherwise we |
| 4141 // should have returned some failure value. | 4143 // should have returned some failure value. |
| 4142 if (FLAG_debug_code) { | 4144 if (FLAG_debug_code) { |
| 4143 __ push(edx); | 4145 __ push(edx); |
| 4144 __ mov(edx, Operand::StaticVariable( | 4146 __ mov(edx, Operand::StaticVariable( |
| 4145 ExternalReference::the_hole_value_location(masm->isolate()))); | 4147 ExternalReference::the_hole_value_location(masm->isolate()))); |
| 4146 NearLabel okay; | 4148 Label okay; |
| 4147 __ cmp(edx, Operand::StaticVariable(pending_exception_address)); | 4149 __ cmp(edx, Operand::StaticVariable(pending_exception_address)); |
| 4148 // Cannot use check here as it attempts to generate call into runtime. | 4150 // Cannot use check here as it attempts to generate call into runtime. |
| 4149 __ j(equal, &okay); | 4151 __ j(equal, &okay, Label::kNear); |
| 4150 __ int3(); | 4152 __ int3(); |
| 4151 __ bind(&okay); | 4153 __ bind(&okay); |
| 4152 __ pop(edx); | 4154 __ pop(edx); |
| 4153 } | 4155 } |
| 4154 | 4156 |
| 4155 // Exit the JavaScript to C++ exit frame. | 4157 // Exit the JavaScript to C++ exit frame. |
| 4156 __ LeaveExitFrame(save_doubles_); | 4158 __ LeaveExitFrame(save_doubles_); |
| 4157 __ ret(0); | 4159 __ ret(0); |
| 4158 | 4160 |
| 4159 // Handling of failure. | 4161 // Handling of failure. |
| (...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4417 | 4419 |
| 4418 // Check that the left hand is a JS object. | 4420 // Check that the left hand is a JS object. |
| 4419 __ test(object, Immediate(kSmiTagMask)); | 4421 __ test(object, Immediate(kSmiTagMask)); |
| 4420 __ j(zero, ¬_js_object, not_taken); | 4422 __ j(zero, ¬_js_object, not_taken); |
| 4421 __ IsObjectJSObjectType(object, map, scratch, ¬_js_object); | 4423 __ IsObjectJSObjectType(object, map, scratch, ¬_js_object); |
| 4422 | 4424 |
| 4423 // If there is a call site cache don't look in the global cache, but do the | 4425 // If there is a call site cache don't look in the global cache, but do the |
| 4424 // real lookup and update the call site cache. | 4426 // real lookup and update the call site cache. |
| 4425 if (!HasCallSiteInlineCheck()) { | 4427 if (!HasCallSiteInlineCheck()) { |
| 4426 // Look up the function and the map in the instanceof cache. | 4428 // Look up the function and the map in the instanceof cache. |
| 4427 NearLabel miss; | 4429 Label miss; |
| 4428 __ mov(scratch, Immediate(Heap::kInstanceofCacheFunctionRootIndex)); | 4430 __ mov(scratch, Immediate(Heap::kInstanceofCacheFunctionRootIndex)); |
| 4429 __ cmp(function, | 4431 __ cmp(function, |
| 4430 Operand::StaticArray(scratch, times_pointer_size, roots_address)); | 4432 Operand::StaticArray(scratch, times_pointer_size, roots_address)); |
| 4431 __ j(not_equal, &miss); | 4433 __ j(not_equal, &miss, Label::kNear); |
| 4432 __ mov(scratch, Immediate(Heap::kInstanceofCacheMapRootIndex)); | 4434 __ mov(scratch, Immediate(Heap::kInstanceofCacheMapRootIndex)); |
| 4433 __ cmp(map, Operand::StaticArray( | 4435 __ cmp(map, Operand::StaticArray( |
| 4434 scratch, times_pointer_size, roots_address)); | 4436 scratch, times_pointer_size, roots_address)); |
| 4435 __ j(not_equal, &miss); | 4437 __ j(not_equal, &miss, Label::kNear); |
| 4436 __ mov(scratch, Immediate(Heap::kInstanceofCacheAnswerRootIndex)); | 4438 __ mov(scratch, Immediate(Heap::kInstanceofCacheAnswerRootIndex)); |
| 4437 __ mov(eax, Operand::StaticArray( | 4439 __ mov(eax, Operand::StaticArray( |
| 4438 scratch, times_pointer_size, roots_address)); | 4440 scratch, times_pointer_size, roots_address)); |
| 4439 __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize); | 4441 __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize); |
| 4440 __ bind(&miss); | 4442 __ bind(&miss); |
| 4441 } | 4443 } |
| 4442 | 4444 |
| 4443 // Get the prototype of the function. | 4445 // Get the prototype of the function. |
| 4444 __ TryGetFunctionPrototype(function, prototype, scratch, &slow); | 4446 __ TryGetFunctionPrototype(function, prototype, scratch, &slow); |
| 4445 | 4447 |
| (...skipping 22 matching lines...) Expand all Loading... |
| 4468 __ Assert(equal, "InstanceofStub unexpected call site cache (cmp 1)"); | 4470 __ Assert(equal, "InstanceofStub unexpected call site cache (cmp 1)"); |
| 4469 __ cmpb(Operand(scratch, 1), kCmpEdiImmediateByte2); | 4471 __ cmpb(Operand(scratch, 1), kCmpEdiImmediateByte2); |
| 4470 __ Assert(equal, "InstanceofStub unexpected call site cache (cmp 2)"); | 4472 __ Assert(equal, "InstanceofStub unexpected call site cache (cmp 2)"); |
| 4471 } | 4473 } |
| 4472 __ mov(Operand(scratch, kDeltaToCmpImmediate), map); | 4474 __ mov(Operand(scratch, kDeltaToCmpImmediate), map); |
| 4473 } | 4475 } |
| 4474 | 4476 |
| 4475 // Loop through the prototype chain of the object looking for the function | 4477 // Loop through the prototype chain of the object looking for the function |
| 4476 // prototype. | 4478 // prototype. |
| 4477 __ mov(scratch, FieldOperand(map, Map::kPrototypeOffset)); | 4479 __ mov(scratch, FieldOperand(map, Map::kPrototypeOffset)); |
| 4478 NearLabel loop, is_instance, is_not_instance; | 4480 Label loop, is_instance, is_not_instance; |
| 4479 __ bind(&loop); | 4481 __ bind(&loop); |
| 4480 __ cmp(scratch, Operand(prototype)); | 4482 __ cmp(scratch, Operand(prototype)); |
| 4481 __ j(equal, &is_instance); | 4483 __ j(equal, &is_instance, Label::kNear); |
| 4482 Factory* factory = masm->isolate()->factory(); | 4484 Factory* factory = masm->isolate()->factory(); |
| 4483 __ cmp(Operand(scratch), Immediate(factory->null_value())); | 4485 __ cmp(Operand(scratch), Immediate(factory->null_value())); |
| 4484 __ j(equal, &is_not_instance); | 4486 __ j(equal, &is_not_instance, Label::kNear); |
| 4485 __ mov(scratch, FieldOperand(scratch, HeapObject::kMapOffset)); | 4487 __ mov(scratch, FieldOperand(scratch, HeapObject::kMapOffset)); |
| 4486 __ mov(scratch, FieldOperand(scratch, Map::kPrototypeOffset)); | 4488 __ mov(scratch, FieldOperand(scratch, Map::kPrototypeOffset)); |
| 4487 __ jmp(&loop); | 4489 __ jmp(&loop); |
| 4488 | 4490 |
| 4489 __ bind(&is_instance); | 4491 __ bind(&is_instance); |
| 4490 if (!HasCallSiteInlineCheck()) { | 4492 if (!HasCallSiteInlineCheck()) { |
| 4491 __ Set(eax, Immediate(0)); | 4493 __ Set(eax, Immediate(0)); |
| 4492 __ mov(scratch, Immediate(Heap::kInstanceofCacheAnswerRootIndex)); | 4494 __ mov(scratch, Immediate(Heap::kInstanceofCacheAnswerRootIndex)); |
| 4493 __ mov(Operand::StaticArray(scratch, | 4495 __ mov(Operand::StaticArray(scratch, |
| 4494 times_pointer_size, roots_address), eax); | 4496 times_pointer_size, roots_address), eax); |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4571 __ push(scratch); | 4573 __ push(scratch); |
| 4572 } | 4574 } |
| 4573 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); | 4575 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); |
| 4574 } else { | 4576 } else { |
| 4575 // Call the builtin and convert 0/1 to true/false. | 4577 // Call the builtin and convert 0/1 to true/false. |
| 4576 __ EnterInternalFrame(); | 4578 __ EnterInternalFrame(); |
| 4577 __ push(object); | 4579 __ push(object); |
| 4578 __ push(function); | 4580 __ push(function); |
| 4579 __ InvokeBuiltin(Builtins::INSTANCE_OF, CALL_FUNCTION); | 4581 __ InvokeBuiltin(Builtins::INSTANCE_OF, CALL_FUNCTION); |
| 4580 __ LeaveInternalFrame(); | 4582 __ LeaveInternalFrame(); |
| 4581 NearLabel true_value, done; | 4583 Label true_value, done; |
| 4582 __ test(eax, Operand(eax)); | 4584 __ test(eax, Operand(eax)); |
| 4583 __ j(zero, &true_value); | 4585 __ j(zero, &true_value, Label::kNear); |
| 4584 __ mov(eax, factory->false_value()); | 4586 __ mov(eax, factory->false_value()); |
| 4585 __ jmp(&done); | 4587 __ jmp(&done, Label::kNear); |
| 4586 __ bind(&true_value); | 4588 __ bind(&true_value); |
| 4587 __ mov(eax, factory->true_value()); | 4589 __ mov(eax, factory->true_value()); |
| 4588 __ bind(&done); | 4590 __ bind(&done); |
| 4589 __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize); | 4591 __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize); |
| 4590 } | 4592 } |
| 4591 } | 4593 } |
| 4592 | 4594 |
| 4593 | 4595 |
| 4594 Register InstanceofStub::left() { return eax; } | 4596 Register InstanceofStub::left() { return eax; } |
| 4595 | 4597 |
| (...skipping 308 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4904 GenerateConvertArgument(masm, 1 * kPointerSize, edx, ebx, ecx, edi, | 4906 GenerateConvertArgument(masm, 1 * kPointerSize, edx, ebx, ecx, edi, |
| 4905 &call_builtin); | 4907 &call_builtin); |
| 4906 builtin_id = Builtins::STRING_ADD_LEFT; | 4908 builtin_id = Builtins::STRING_ADD_LEFT; |
| 4907 } | 4909 } |
| 4908 } | 4910 } |
| 4909 | 4911 |
| 4910 // Both arguments are strings. | 4912 // Both arguments are strings. |
| 4911 // eax: first string | 4913 // eax: first string |
| 4912 // edx: second string | 4914 // edx: second string |
| 4913 // Check if either of the strings are empty. In that case return the other. | 4915 // Check if either of the strings are empty. In that case return the other. |
| 4914 NearLabel second_not_zero_length, both_not_zero_length; | 4916 Label second_not_zero_length, both_not_zero_length; |
| 4915 __ mov(ecx, FieldOperand(edx, String::kLengthOffset)); | 4917 __ mov(ecx, FieldOperand(edx, String::kLengthOffset)); |
| 4916 STATIC_ASSERT(kSmiTag == 0); | 4918 STATIC_ASSERT(kSmiTag == 0); |
| 4917 __ test(ecx, Operand(ecx)); | 4919 __ test(ecx, Operand(ecx)); |
| 4918 __ j(not_zero, &second_not_zero_length); | 4920 __ j(not_zero, &second_not_zero_length, Label::kNear); |
| 4919 // Second string is empty, result is first string which is already in eax. | 4921 // Second string is empty, result is first string which is already in eax. |
| 4920 Counters* counters = masm->isolate()->counters(); | 4922 Counters* counters = masm->isolate()->counters(); |
| 4921 __ IncrementCounter(counters->string_add_native(), 1); | 4923 __ IncrementCounter(counters->string_add_native(), 1); |
| 4922 __ ret(2 * kPointerSize); | 4924 __ ret(2 * kPointerSize); |
| 4923 __ bind(&second_not_zero_length); | 4925 __ bind(&second_not_zero_length); |
| 4924 __ mov(ebx, FieldOperand(eax, String::kLengthOffset)); | 4926 __ mov(ebx, FieldOperand(eax, String::kLengthOffset)); |
| 4925 STATIC_ASSERT(kSmiTag == 0); | 4927 STATIC_ASSERT(kSmiTag == 0); |
| 4926 __ test(ebx, Operand(ebx)); | 4928 __ test(ebx, Operand(ebx)); |
| 4927 __ j(not_zero, &both_not_zero_length); | 4929 __ j(not_zero, &both_not_zero_length, Label::kNear); |
| 4928 // First string is empty, result is second string which is in edx. | 4930 // First string is empty, result is second string which is in edx. |
| 4929 __ mov(eax, edx); | 4931 __ mov(eax, edx); |
| 4930 __ IncrementCounter(counters->string_add_native(), 1); | 4932 __ IncrementCounter(counters->string_add_native(), 1); |
| 4931 __ ret(2 * kPointerSize); | 4933 __ ret(2 * kPointerSize); |
| 4932 | 4934 |
| 4933 // Both strings are non-empty. | 4935 // Both strings are non-empty. |
| 4934 // eax: first string | 4936 // eax: first string |
| 4935 // ebx: length of first string as a smi | 4937 // ebx: length of first string as a smi |
| 4936 // ecx: length of second string as a smi | 4938 // ecx: length of second string as a smi |
| 4937 // edx: second string | 4939 // edx: second string |
| (...skipping 253 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5191 __ bind(&done); | 5193 __ bind(&done); |
| 5192 } | 5194 } |
| 5193 | 5195 |
| 5194 | 5196 |
| 5195 void StringHelper::GenerateCopyCharacters(MacroAssembler* masm, | 5197 void StringHelper::GenerateCopyCharacters(MacroAssembler* masm, |
| 5196 Register dest, | 5198 Register dest, |
| 5197 Register src, | 5199 Register src, |
| 5198 Register count, | 5200 Register count, |
| 5199 Register scratch, | 5201 Register scratch, |
| 5200 bool ascii) { | 5202 bool ascii) { |
| 5201 NearLabel loop; | 5203 Label loop; |
| 5202 __ bind(&loop); | 5204 __ bind(&loop); |
| 5203 // This loop just copies one character at a time, as it is only used for very | 5205 // This loop just copies one character at a time, as it is only used for very |
| 5204 // short strings. | 5206 // short strings. |
| 5205 if (ascii) { | 5207 if (ascii) { |
| 5206 __ mov_b(scratch, Operand(src, 0)); | 5208 __ mov_b(scratch, Operand(src, 0)); |
| 5207 __ mov_b(Operand(dest, 0), scratch); | 5209 __ mov_b(Operand(dest, 0), scratch); |
| 5208 __ add(Operand(src), Immediate(1)); | 5210 __ add(Operand(src), Immediate(1)); |
| 5209 __ add(Operand(dest), Immediate(1)); | 5211 __ add(Operand(dest), Immediate(1)); |
| 5210 } else { | 5212 } else { |
| 5211 __ mov_w(scratch, Operand(src, 0)); | 5213 __ mov_w(scratch, Operand(src, 0)); |
| (...skipping 26 matching lines...) Expand all Loading... |
| 5238 Label done; | 5240 Label done; |
| 5239 __ test(count, Operand(count)); | 5241 __ test(count, Operand(count)); |
| 5240 __ j(zero, &done); | 5242 __ j(zero, &done); |
| 5241 | 5243 |
| 5242 // Make count the number of bytes to copy. | 5244 // Make count the number of bytes to copy. |
| 5243 if (!ascii) { | 5245 if (!ascii) { |
| 5244 __ shl(count, 1); | 5246 __ shl(count, 1); |
| 5245 } | 5247 } |
| 5246 | 5248 |
| 5247 // Don't enter the rep movs if there are less than 4 bytes to copy. | 5249 // Don't enter the rep movs if there are less than 4 bytes to copy. |
| 5248 NearLabel last_bytes; | 5250 Label last_bytes; |
| 5249 __ test(count, Immediate(~3)); | 5251 __ test(count, Immediate(~3)); |
| 5250 __ j(zero, &last_bytes); | 5252 __ j(zero, &last_bytes, Label::kNear); |
| 5251 | 5253 |
| 5252 // Copy from edi to esi using rep movs instruction. | 5254 // Copy from edi to esi using rep movs instruction. |
| 5253 __ mov(scratch, count); | 5255 __ mov(scratch, count); |
| 5254 __ sar(count, 2); // Number of doublewords to copy. | 5256 __ sar(count, 2); // Number of doublewords to copy. |
| 5255 __ cld(); | 5257 __ cld(); |
| 5256 __ rep_movs(); | 5258 __ rep_movs(); |
| 5257 | 5259 |
| 5258 // Find number of bytes left. | 5260 // Find number of bytes left. |
| 5259 __ mov(count, scratch); | 5261 __ mov(count, scratch); |
| 5260 __ and_(count, 3); | 5262 __ and_(count, 3); |
| 5261 | 5263 |
| 5262 // Check if there are more bytes to copy. | 5264 // Check if there are more bytes to copy. |
| 5263 __ bind(&last_bytes); | 5265 __ bind(&last_bytes); |
| 5264 __ test(count, Operand(count)); | 5266 __ test(count, Operand(count)); |
| 5265 __ j(zero, &done); | 5267 __ j(zero, &done); |
| 5266 | 5268 |
| 5267 // Copy remaining characters. | 5269 // Copy remaining characters. |
| 5268 NearLabel loop; | 5270 Label loop; |
| 5269 __ bind(&loop); | 5271 __ bind(&loop); |
| 5270 __ mov_b(scratch, Operand(src, 0)); | 5272 __ mov_b(scratch, Operand(src, 0)); |
| 5271 __ mov_b(Operand(dest, 0), scratch); | 5273 __ mov_b(Operand(dest, 0), scratch); |
| 5272 __ add(Operand(src), Immediate(1)); | 5274 __ add(Operand(src), Immediate(1)); |
| 5273 __ add(Operand(dest), Immediate(1)); | 5275 __ add(Operand(dest), Immediate(1)); |
| 5274 __ sub(Operand(count), Immediate(1)); | 5276 __ sub(Operand(count), Immediate(1)); |
| 5275 __ j(not_zero, &loop); | 5277 __ j(not_zero, &loop); |
| 5276 | 5278 |
| 5277 __ bind(&done); | 5279 __ bind(&done); |
| 5278 } | 5280 } |
| 5279 | 5281 |
| 5280 | 5282 |
| 5281 void StringHelper::GenerateTwoCharacterSymbolTableProbe(MacroAssembler* masm, | 5283 void StringHelper::GenerateTwoCharacterSymbolTableProbe(MacroAssembler* masm, |
| 5282 Register c1, | 5284 Register c1, |
| 5283 Register c2, | 5285 Register c2, |
| 5284 Register scratch1, | 5286 Register scratch1, |
| 5285 Register scratch2, | 5287 Register scratch2, |
| 5286 Register scratch3, | 5288 Register scratch3, |
| 5287 Label* not_probed, | 5289 Label* not_probed, |
| 5288 Label* not_found) { | 5290 Label* not_found) { |
| 5289 // Register scratch3 is the general scratch register in this function. | 5291 // Register scratch3 is the general scratch register in this function. |
| 5290 Register scratch = scratch3; | 5292 Register scratch = scratch3; |
| 5291 | 5293 |
| 5292 // Make sure that both characters are not digits as such strings has a | 5294 // Make sure that both characters are not digits as such strings has a |
| 5293 // different hash algorithm. Don't try to look for these in the symbol table. | 5295 // different hash algorithm. Don't try to look for these in the symbol table. |
| 5294 NearLabel not_array_index; | 5296 Label not_array_index; |
| 5295 __ mov(scratch, c1); | 5297 __ mov(scratch, c1); |
| 5296 __ sub(Operand(scratch), Immediate(static_cast<int>('0'))); | 5298 __ sub(Operand(scratch), Immediate(static_cast<int>('0'))); |
| 5297 __ cmp(Operand(scratch), Immediate(static_cast<int>('9' - '0'))); | 5299 __ cmp(Operand(scratch), Immediate(static_cast<int>('9' - '0'))); |
| 5298 __ j(above, ¬_array_index); | 5300 __ j(above, ¬_array_index, Label::kNear); |
| 5299 __ mov(scratch, c2); | 5301 __ mov(scratch, c2); |
| 5300 __ sub(Operand(scratch), Immediate(static_cast<int>('0'))); | 5302 __ sub(Operand(scratch), Immediate(static_cast<int>('0'))); |
| 5301 __ cmp(Operand(scratch), Immediate(static_cast<int>('9' - '0'))); | 5303 __ cmp(Operand(scratch), Immediate(static_cast<int>('9' - '0'))); |
| 5302 __ j(below_equal, not_probed); | 5304 __ j(below_equal, not_probed); |
| 5303 | 5305 |
| 5304 __ bind(¬_array_index); | 5306 __ bind(¬_array_index); |
| 5305 // Calculate the two character string hash. | 5307 // Calculate the two character string hash. |
| 5306 Register hash = scratch1; | 5308 Register hash = scratch1; |
| 5307 GenerateHashInit(masm, hash, c1, scratch); | 5309 GenerateHashInit(masm, hash, c1, scratch); |
| 5308 GenerateHashAddCharacter(masm, hash, c2, scratch); | 5310 GenerateHashAddCharacter(masm, hash, c2, scratch); |
| (...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5446 // hash ^= hash >> 11; | 5448 // hash ^= hash >> 11; |
| 5447 __ mov(scratch, hash); | 5449 __ mov(scratch, hash); |
| 5448 __ sar(scratch, 11); | 5450 __ sar(scratch, 11); |
| 5449 __ xor_(hash, Operand(scratch)); | 5451 __ xor_(hash, Operand(scratch)); |
| 5450 // hash += hash << 15; | 5452 // hash += hash << 15; |
| 5451 __ mov(scratch, hash); | 5453 __ mov(scratch, hash); |
| 5452 __ shl(scratch, 15); | 5454 __ shl(scratch, 15); |
| 5453 __ add(hash, Operand(scratch)); | 5455 __ add(hash, Operand(scratch)); |
| 5454 | 5456 |
| 5455 // if (hash == 0) hash = 27; | 5457 // if (hash == 0) hash = 27; |
| 5456 NearLabel hash_not_zero; | 5458 Label hash_not_zero; |
| 5457 __ test(hash, Operand(hash)); | 5459 __ test(hash, Operand(hash)); |
| 5458 __ j(not_zero, &hash_not_zero); | 5460 __ j(not_zero, &hash_not_zero, Label::kNear); |
| 5459 __ mov(hash, Immediate(27)); | 5461 __ mov(hash, Immediate(27)); |
| 5460 __ bind(&hash_not_zero); | 5462 __ bind(&hash_not_zero); |
| 5461 } | 5463 } |
| 5462 | 5464 |
| 5463 | 5465 |
| 5464 void SubStringStub::Generate(MacroAssembler* masm) { | 5466 void SubStringStub::Generate(MacroAssembler* masm) { |
| 5465 Label runtime; | 5467 Label runtime; |
| 5466 | 5468 |
| 5467 // Stack frame on entry. | 5469 // Stack frame on entry. |
| 5468 // esp[0]: return address | 5470 // esp[0]: return address |
| (...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5671 Register scratch2, | 5673 Register scratch2, |
| 5672 Register scratch3) { | 5674 Register scratch3) { |
| 5673 Label result_not_equal; | 5675 Label result_not_equal; |
| 5674 Label result_greater; | 5676 Label result_greater; |
| 5675 Label compare_lengths; | 5677 Label compare_lengths; |
| 5676 | 5678 |
| 5677 Counters* counters = masm->isolate()->counters(); | 5679 Counters* counters = masm->isolate()->counters(); |
| 5678 __ IncrementCounter(counters->string_compare_native(), 1); | 5680 __ IncrementCounter(counters->string_compare_native(), 1); |
| 5679 | 5681 |
| 5680 // Find minimum length. | 5682 // Find minimum length. |
| 5681 NearLabel left_shorter; | 5683 Label left_shorter; |
| 5682 __ mov(scratch1, FieldOperand(left, String::kLengthOffset)); | 5684 __ mov(scratch1, FieldOperand(left, String::kLengthOffset)); |
| 5683 __ mov(scratch3, scratch1); | 5685 __ mov(scratch3, scratch1); |
| 5684 __ sub(scratch3, FieldOperand(right, String::kLengthOffset)); | 5686 __ sub(scratch3, FieldOperand(right, String::kLengthOffset)); |
| 5685 | 5687 |
| 5686 Register length_delta = scratch3; | 5688 Register length_delta = scratch3; |
| 5687 | 5689 |
| 5688 __ j(less_equal, &left_shorter); | 5690 __ j(less_equal, &left_shorter, Label::kNear); |
| 5689 // Right string is shorter. Change scratch1 to be length of right string. | 5691 // Right string is shorter. Change scratch1 to be length of right string. |
| 5690 __ sub(scratch1, Operand(length_delta)); | 5692 __ sub(scratch1, Operand(length_delta)); |
| 5691 __ bind(&left_shorter); | 5693 __ bind(&left_shorter); |
| 5692 | 5694 |
| 5693 Register min_length = scratch1; | 5695 Register min_length = scratch1; |
| 5694 | 5696 |
| 5695 // If either length is zero, just compare lengths. | 5697 // If either length is zero, just compare lengths. |
| 5696 __ test(min_length, Operand(min_length)); | 5698 __ test(min_length, Operand(min_length)); |
| 5697 __ j(zero, &compare_lengths); | 5699 __ j(zero, &compare_lengths); |
| 5698 | 5700 |
| 5699 // Change index to run from -min_length to -1 by adding min_length | 5701 // Change index to run from -min_length to -1 by adding min_length |
| 5700 // to string start. This means that loop ends when index reaches zero, | 5702 // to string start. This means that loop ends when index reaches zero, |
| 5701 // which doesn't need an additional compare. | 5703 // which doesn't need an additional compare. |
| 5702 __ SmiUntag(min_length); | 5704 __ SmiUntag(min_length); |
| 5703 __ lea(left, | 5705 __ lea(left, |
| 5704 FieldOperand(left, | 5706 FieldOperand(left, |
| 5705 min_length, times_1, | 5707 min_length, times_1, |
| 5706 SeqAsciiString::kHeaderSize)); | 5708 SeqAsciiString::kHeaderSize)); |
| 5707 __ lea(right, | 5709 __ lea(right, |
| 5708 FieldOperand(right, | 5710 FieldOperand(right, |
| 5709 min_length, times_1, | 5711 min_length, times_1, |
| 5710 SeqAsciiString::kHeaderSize)); | 5712 SeqAsciiString::kHeaderSize)); |
| 5711 __ neg(min_length); | 5713 __ neg(min_length); |
| 5712 | 5714 |
| 5713 Register index = min_length; // index = -min_length; | 5715 Register index = min_length; // index = -min_length; |
| 5714 | 5716 |
| 5715 { | 5717 { |
| 5716 // Compare loop. | 5718 // Compare loop. |
| 5717 NearLabel loop; | 5719 Label loop; |
| 5718 __ bind(&loop); | 5720 __ bind(&loop); |
| 5719 // Compare characters. | 5721 // Compare characters. |
| 5720 __ mov_b(scratch2, Operand(left, index, times_1, 0)); | 5722 __ mov_b(scratch2, Operand(left, index, times_1, 0)); |
| 5721 __ cmpb(scratch2, Operand(right, index, times_1, 0)); | 5723 __ cmpb(scratch2, Operand(right, index, times_1, 0)); |
| 5722 __ j(not_equal, &result_not_equal); | 5724 __ j(not_equal, &result_not_equal); |
| 5723 __ add(Operand(index), Immediate(1)); | 5725 __ add(Operand(index), Immediate(1)); |
| 5724 __ j(not_zero, &loop); | 5726 __ j(not_zero, &loop); |
| 5725 } | 5727 } |
| 5726 | 5728 |
| 5727 // Compare lengths - strings up to min-length are equal. | 5729 // Compare lengths - strings up to min-length are equal. |
| (...skipping 25 matching lines...) Expand all Loading... |
| 5753 Label runtime; | 5755 Label runtime; |
| 5754 | 5756 |
| 5755 // Stack frame on entry. | 5757 // Stack frame on entry. |
| 5756 // esp[0]: return address | 5758 // esp[0]: return address |
| 5757 // esp[4]: right string | 5759 // esp[4]: right string |
| 5758 // esp[8]: left string | 5760 // esp[8]: left string |
| 5759 | 5761 |
| 5760 __ mov(edx, Operand(esp, 2 * kPointerSize)); // left | 5762 __ mov(edx, Operand(esp, 2 * kPointerSize)); // left |
| 5761 __ mov(eax, Operand(esp, 1 * kPointerSize)); // right | 5763 __ mov(eax, Operand(esp, 1 * kPointerSize)); // right |
| 5762 | 5764 |
| 5763 NearLabel not_same; | 5765 Label not_same; |
| 5764 __ cmp(edx, Operand(eax)); | 5766 __ cmp(edx, Operand(eax)); |
| 5765 __ j(not_equal, ¬_same); | 5767 __ j(not_equal, ¬_same, Label::kNear); |
| 5766 STATIC_ASSERT(EQUAL == 0); | 5768 STATIC_ASSERT(EQUAL == 0); |
| 5767 STATIC_ASSERT(kSmiTag == 0); | 5769 STATIC_ASSERT(kSmiTag == 0); |
| 5768 __ Set(eax, Immediate(Smi::FromInt(EQUAL))); | 5770 __ Set(eax, Immediate(Smi::FromInt(EQUAL))); |
| 5769 __ IncrementCounter(masm->isolate()->counters()->string_compare_native(), 1); | 5771 __ IncrementCounter(masm->isolate()->counters()->string_compare_native(), 1); |
| 5770 __ ret(2 * kPointerSize); | 5772 __ ret(2 * kPointerSize); |
| 5771 | 5773 |
| 5772 __ bind(¬_same); | 5774 __ bind(¬_same); |
| 5773 | 5775 |
| 5774 // Check that both objects are sequential ascii strings. | 5776 // Check that both objects are sequential ascii strings. |
| 5775 __ JumpIfNotBothSequentialAsciiStrings(edx, eax, ecx, ebx, &runtime); | 5777 __ JumpIfNotBothSequentialAsciiStrings(edx, eax, ecx, ebx, &runtime); |
| 5776 | 5778 |
| 5777 // Compare flat ascii strings. | 5779 // Compare flat ascii strings. |
| 5778 // Drop arguments from the stack. | 5780 // Drop arguments from the stack. |
| 5779 __ pop(ecx); | 5781 __ pop(ecx); |
| 5780 __ add(Operand(esp), Immediate(2 * kPointerSize)); | 5782 __ add(Operand(esp), Immediate(2 * kPointerSize)); |
| 5781 __ push(ecx); | 5783 __ push(ecx); |
| 5782 GenerateCompareFlatAsciiStrings(masm, edx, eax, ecx, ebx, edi); | 5784 GenerateCompareFlatAsciiStrings(masm, edx, eax, ecx, ebx, edi); |
| 5783 | 5785 |
| 5784 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater) | 5786 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater) |
| 5785 // tagged as a small integer. | 5787 // tagged as a small integer. |
| 5786 __ bind(&runtime); | 5788 __ bind(&runtime); |
| 5787 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); | 5789 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); |
| 5788 } | 5790 } |
| 5789 | 5791 |
| 5790 | 5792 |
| 5791 void ICCompareStub::GenerateSmis(MacroAssembler* masm) { | 5793 void ICCompareStub::GenerateSmis(MacroAssembler* masm) { |
| 5792 ASSERT(state_ == CompareIC::SMIS); | 5794 ASSERT(state_ == CompareIC::SMIS); |
| 5793 NearLabel miss; | 5795 Label miss; |
| 5794 __ mov(ecx, Operand(edx)); | 5796 __ mov(ecx, Operand(edx)); |
| 5795 __ or_(ecx, Operand(eax)); | 5797 __ or_(ecx, Operand(eax)); |
| 5796 __ test(ecx, Immediate(kSmiTagMask)); | 5798 __ test(ecx, Immediate(kSmiTagMask)); |
| 5797 __ j(not_zero, &miss, not_taken); | 5799 __ j(not_zero, &miss, not_taken, Label::kNear); |
| 5798 | 5800 |
| 5799 if (GetCondition() == equal) { | 5801 if (GetCondition() == equal) { |
| 5800 // For equality we do not care about the sign of the result. | 5802 // For equality we do not care about the sign of the result. |
| 5801 __ sub(eax, Operand(edx)); | 5803 __ sub(eax, Operand(edx)); |
| 5802 } else { | 5804 } else { |
| 5803 NearLabel done; | 5805 Label done; |
| 5804 __ sub(edx, Operand(eax)); | 5806 __ sub(edx, Operand(eax)); |
| 5805 __ j(no_overflow, &done); | 5807 __ j(no_overflow, &done, Label::kNear); |
| 5806 // Correct sign of result in case of overflow. | 5808 // Correct sign of result in case of overflow. |
| 5807 __ not_(edx); | 5809 __ not_(edx); |
| 5808 __ bind(&done); | 5810 __ bind(&done); |
| 5809 __ mov(eax, edx); | 5811 __ mov(eax, edx); |
| 5810 } | 5812 } |
| 5811 __ ret(0); | 5813 __ ret(0); |
| 5812 | 5814 |
| 5813 __ bind(&miss); | 5815 __ bind(&miss); |
| 5814 GenerateMiss(masm); | 5816 GenerateMiss(masm); |
| 5815 } | 5817 } |
| 5816 | 5818 |
| 5817 | 5819 |
| 5818 void ICCompareStub::GenerateHeapNumbers(MacroAssembler* masm) { | 5820 void ICCompareStub::GenerateHeapNumbers(MacroAssembler* masm) { |
| 5819 ASSERT(state_ == CompareIC::HEAP_NUMBERS); | 5821 ASSERT(state_ == CompareIC::HEAP_NUMBERS); |
| 5820 | 5822 |
| 5821 NearLabel generic_stub; | 5823 Label generic_stub; |
| 5822 NearLabel unordered; | 5824 Label unordered; |
| 5823 NearLabel miss; | 5825 Label miss; |
| 5824 __ mov(ecx, Operand(edx)); | 5826 __ mov(ecx, Operand(edx)); |
| 5825 __ and_(ecx, Operand(eax)); | 5827 __ and_(ecx, Operand(eax)); |
| 5826 __ test(ecx, Immediate(kSmiTagMask)); | 5828 __ test(ecx, Immediate(kSmiTagMask)); |
| 5827 __ j(zero, &generic_stub, not_taken); | 5829 __ j(zero, &generic_stub, not_taken, Label::kNear); |
| 5828 | 5830 |
| 5829 __ CmpObjectType(eax, HEAP_NUMBER_TYPE, ecx); | 5831 __ CmpObjectType(eax, HEAP_NUMBER_TYPE, ecx); |
| 5830 __ j(not_equal, &miss, not_taken); | 5832 __ j(not_equal, &miss, not_taken, Label::kNear); |
| 5831 __ CmpObjectType(edx, HEAP_NUMBER_TYPE, ecx); | 5833 __ CmpObjectType(edx, HEAP_NUMBER_TYPE, ecx); |
| 5832 __ j(not_equal, &miss, not_taken); | 5834 __ j(not_equal, &miss, not_taken, Label::kNear); |
| 5833 | 5835 |
| 5834 // Inlining the double comparison and falling back to the general compare | 5836 // Inlining the double comparison and falling back to the general compare |
| 5835 // stub if NaN is involved or SS2 or CMOV is unsupported. | 5837 // stub if NaN is involved or SS2 or CMOV is unsupported. |
| 5836 if (CpuFeatures::IsSupported(SSE2) && CpuFeatures::IsSupported(CMOV)) { | 5838 if (CpuFeatures::IsSupported(SSE2) && CpuFeatures::IsSupported(CMOV)) { |
| 5837 CpuFeatures::Scope scope1(SSE2); | 5839 CpuFeatures::Scope scope1(SSE2); |
| 5838 CpuFeatures::Scope scope2(CMOV); | 5840 CpuFeatures::Scope scope2(CMOV); |
| 5839 | 5841 |
| 5840 // Load left and right operand | 5842 // Load left and right operand |
| 5841 __ movdbl(xmm0, FieldOperand(edx, HeapNumber::kValueOffset)); | 5843 __ movdbl(xmm0, FieldOperand(edx, HeapNumber::kValueOffset)); |
| 5842 __ movdbl(xmm1, FieldOperand(eax, HeapNumber::kValueOffset)); | 5844 __ movdbl(xmm1, FieldOperand(eax, HeapNumber::kValueOffset)); |
| 5843 | 5845 |
| 5844 // Compare operands | 5846 // Compare operands |
| 5845 __ ucomisd(xmm0, xmm1); | 5847 __ ucomisd(xmm0, xmm1); |
| 5846 | 5848 |
| 5847 // Don't base result on EFLAGS when a NaN is involved. | 5849 // Don't base result on EFLAGS when a NaN is involved. |
| 5848 __ j(parity_even, &unordered, not_taken); | 5850 __ j(parity_even, &unordered, not_taken, Label::kNear); |
| 5849 | 5851 |
| 5850 // Return a result of -1, 0, or 1, based on EFLAGS. | 5852 // Return a result of -1, 0, or 1, based on EFLAGS. |
| 5851 // Performing mov, because xor would destroy the flag register. | 5853 // Performing mov, because xor would destroy the flag register. |
| 5852 __ mov(eax, 0); // equal | 5854 __ mov(eax, 0); // equal |
| 5853 __ mov(ecx, Immediate(Smi::FromInt(1))); | 5855 __ mov(ecx, Immediate(Smi::FromInt(1))); |
| 5854 __ cmov(above, eax, Operand(ecx)); | 5856 __ cmov(above, eax, Operand(ecx)); |
| 5855 __ mov(ecx, Immediate(Smi::FromInt(-1))); | 5857 __ mov(ecx, Immediate(Smi::FromInt(-1))); |
| 5856 __ cmov(below, eax, Operand(ecx)); | 5858 __ cmov(below, eax, Operand(ecx)); |
| 5857 __ ret(0); | 5859 __ ret(0); |
| 5858 | 5860 |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5940 __ push(tmp1); | 5942 __ push(tmp1); |
| 5941 __ TailCallRuntime(Runtime::kStringEquals, 2, 1); | 5943 __ TailCallRuntime(Runtime::kStringEquals, 2, 1); |
| 5942 | 5944 |
| 5943 __ bind(&miss); | 5945 __ bind(&miss); |
| 5944 GenerateMiss(masm); | 5946 GenerateMiss(masm); |
| 5945 } | 5947 } |
| 5946 | 5948 |
| 5947 | 5949 |
| 5948 void ICCompareStub::GenerateObjects(MacroAssembler* masm) { | 5950 void ICCompareStub::GenerateObjects(MacroAssembler* masm) { |
| 5949 ASSERT(state_ == CompareIC::OBJECTS); | 5951 ASSERT(state_ == CompareIC::OBJECTS); |
| 5950 NearLabel miss; | 5952 Label miss; |
| 5951 __ mov(ecx, Operand(edx)); | 5953 __ mov(ecx, Operand(edx)); |
| 5952 __ and_(ecx, Operand(eax)); | 5954 __ and_(ecx, Operand(eax)); |
| 5953 __ test(ecx, Immediate(kSmiTagMask)); | 5955 __ test(ecx, Immediate(kSmiTagMask)); |
| 5954 __ j(zero, &miss, not_taken); | 5956 __ j(zero, &miss, not_taken, Label::kNear); |
| 5955 | 5957 |
| 5956 __ CmpObjectType(eax, JS_OBJECT_TYPE, ecx); | 5958 __ CmpObjectType(eax, JS_OBJECT_TYPE, ecx); |
| 5957 __ j(not_equal, &miss, not_taken); | 5959 __ j(not_equal, &miss, not_taken, Label::kNear); |
| 5958 __ CmpObjectType(edx, JS_OBJECT_TYPE, ecx); | 5960 __ CmpObjectType(edx, JS_OBJECT_TYPE, ecx); |
| 5959 __ j(not_equal, &miss, not_taken); | 5961 __ j(not_equal, &miss, not_taken, Label::kNear); |
| 5960 | 5962 |
| 5961 ASSERT(GetCondition() == equal); | 5963 ASSERT(GetCondition() == equal); |
| 5962 __ sub(eax, Operand(edx)); | 5964 __ sub(eax, Operand(edx)); |
| 5963 __ ret(0); | 5965 __ ret(0); |
| 5964 | 5966 |
| 5965 __ bind(&miss); | 5967 __ bind(&miss); |
| 5966 GenerateMiss(masm); | 5968 GenerateMiss(masm); |
| 5967 } | 5969 } |
| 5968 | 5970 |
| 5969 | 5971 |
| (...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6205 __ Drop(1); | 6207 __ Drop(1); |
| 6206 __ ret(2 * kPointerSize); | 6208 __ ret(2 * kPointerSize); |
| 6207 } | 6209 } |
| 6208 | 6210 |
| 6209 | 6211 |
| 6210 #undef __ | 6212 #undef __ |
| 6211 | 6213 |
| 6212 } } // namespace v8::internal | 6214 } } // namespace v8::internal |
| 6213 | 6215 |
| 6214 #endif // V8_TARGET_ARCH_IA32 | 6216 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |