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 |