Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(80)

Side by Side Diff: src/ia32/code-stubs-ia32.cc

Issue 6928060: Merge Label and NearLabel (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: address comments Created 9 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/ia32/builtins-ia32.cc ('k') | src/ia32/full-codegen-ia32.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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, &not_string); 268 __ j(above_equal, &not_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(&not_string); 274 __ bind(&not_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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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, &not_minus_half); 2881 __ j(not_equal, &not_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
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
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
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
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
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
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
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, &not_smi); 3569 __ j(not_zero, &not_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(&not_smi); 3573 __ bind(&not_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
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
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, &not_identical); 3686 __ j(not_equal, &not_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, &not_identical); 3713 __ j(above_equal, &not_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
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(&not_identical); 3751 __ bind(&not_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, &not_smis); 3770 __ j(not_zero, &not_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(&not_smis); 3792 __ bind(&not_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
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
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, &not_both_objects); 3938 __ j(not_zero, &not_both_objects, Label::kNear);
3937 __ CmpObjectType(eax, FIRST_JS_OBJECT_TYPE, ecx); 3939 __ CmpObjectType(eax, FIRST_JS_OBJECT_TYPE, ecx);
3938 __ j(below, &not_both_objects); 3940 __ j(below, &not_both_objects, Label::kNear);
3939 __ CmpObjectType(edx, FIRST_JS_OBJECT_TYPE, ebx); 3941 __ CmpObjectType(edx, FIRST_JS_OBJECT_TYPE, ebx);
3940 __ j(below, &not_both_objects); 3942 __ j(below, &not_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(&not_both_objects); 3959 __ bind(&not_both_objects);
3958 } 3960 }
3959 3961
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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, &not_js_object, not_taken); 4422 __ j(zero, &not_js_object, not_taken);
4421 __ IsObjectJSObjectType(object, map, scratch, &not_js_object); 4423 __ IsObjectJSObjectType(object, map, scratch, &not_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
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
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
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
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
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, &not_array_index); 5300 __ j(above, &not_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(&not_array_index); 5306 __ bind(&not_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
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
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
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, &not_same); 5767 __ j(not_equal, &not_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(&not_same); 5774 __ bind(&not_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
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
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
OLDNEW
« no previous file with comments | « src/ia32/builtins-ia32.cc ('k') | src/ia32/full-codegen-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698