| OLD | NEW |
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 475 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 486 __ xor_(ecx, Operand(ecx)); | 486 __ xor_(ecx, Operand(ecx)); |
| 487 // Check whether the exponent matches a 32 bit signed int that cannot be | 487 // Check whether the exponent matches a 32 bit signed int that cannot be |
| 488 // represented by a Smi. A non-smi 32 bit integer is 1.xxx * 2^30 so the | 488 // represented by a Smi. A non-smi 32 bit integer is 1.xxx * 2^30 so the |
| 489 // exponent is 30 (biased). This is the exponent that we are fastest at and | 489 // exponent is 30 (biased). This is the exponent that we are fastest at and |
| 490 // also the highest exponent we can handle here. | 490 // also the highest exponent we can handle here. |
| 491 const uint32_t non_smi_exponent = | 491 const uint32_t non_smi_exponent = |
| 492 (HeapNumber::kExponentBias + 30) << HeapNumber::kExponentShift; | 492 (HeapNumber::kExponentBias + 30) << HeapNumber::kExponentShift; |
| 493 __ cmp(Operand(scratch2), Immediate(non_smi_exponent)); | 493 __ cmp(Operand(scratch2), Immediate(non_smi_exponent)); |
| 494 // If we have a match of the int32-but-not-Smi exponent then skip some | 494 // If we have a match of the int32-but-not-Smi exponent then skip some |
| 495 // logic. | 495 // logic. |
| 496 __ j(equal, &right_exponent); | 496 __ j(equal, &right_exponent, Label::kNear); |
| 497 // If the exponent is higher than that then go to slow case. This catches | 497 // If the exponent is higher than that then go to slow case. This catches |
| 498 // numbers that don't fit in a signed int32, infinities and NaNs. | 498 // numbers that don't fit in a signed int32, infinities and NaNs. |
| 499 __ j(less, &normal_exponent); | 499 __ j(less, &normal_exponent, Label::kNear); |
| 500 | 500 |
| 501 { | 501 { |
| 502 // Handle a big exponent. The only reason we have this code is that the | 502 // Handle a big exponent. The only reason we have this code is that the |
| 503 // >>> operator has a tendency to generate numbers with an exponent of 31. | 503 // >>> operator has a tendency to generate numbers with an exponent of 31. |
| 504 const uint32_t big_non_smi_exponent = | 504 const uint32_t big_non_smi_exponent = |
| 505 (HeapNumber::kExponentBias + 31) << HeapNumber::kExponentShift; | 505 (HeapNumber::kExponentBias + 31) << HeapNumber::kExponentShift; |
| 506 __ cmp(Operand(scratch2), Immediate(big_non_smi_exponent)); | 506 __ cmp(Operand(scratch2), Immediate(big_non_smi_exponent)); |
| 507 __ j(not_equal, conversion_failure); | 507 __ j(not_equal, conversion_failure); |
| 508 // We have the big exponent, typically from >>>. This means the number is | 508 // We have the big exponent, typically from >>>. This means the number is |
| 509 // in the range 2^31 to 2^32 - 1. Get the top bits of the mantissa. | 509 // in the range 2^31 to 2^32 - 1. Get the top bits of the mantissa. |
| 510 __ mov(scratch2, scratch); | 510 __ mov(scratch2, scratch); |
| 511 __ and_(scratch2, HeapNumber::kMantissaMask); | 511 __ and_(scratch2, HeapNumber::kMantissaMask); |
| 512 // Put back the implicit 1. | 512 // Put back the implicit 1. |
| 513 __ or_(scratch2, 1 << HeapNumber::kExponentShift); | 513 __ or_(scratch2, 1 << HeapNumber::kExponentShift); |
| 514 // Shift up the mantissa bits to take up the space the exponent used to | 514 // Shift up the mantissa bits to take up the space the exponent used to |
| 515 // take. We just orred in the implicit bit so that took care of one and | 515 // take. We just orred in the implicit bit so that took care of one and |
| 516 // we want to use the full unsigned range so we subtract 1 bit from the | 516 // we want to use the full unsigned range so we subtract 1 bit from the |
| 517 // shift distance. | 517 // shift distance. |
| 518 const int big_shift_distance = HeapNumber::kNonMantissaBitsInTopWord - 1; | 518 const int big_shift_distance = HeapNumber::kNonMantissaBitsInTopWord - 1; |
| 519 __ shl(scratch2, big_shift_distance); | 519 __ shl(scratch2, big_shift_distance); |
| 520 // Get the second half of the double. | 520 // Get the second half of the double. |
| 521 __ mov(ecx, FieldOperand(source, HeapNumber::kMantissaOffset)); | 521 __ mov(ecx, FieldOperand(source, HeapNumber::kMantissaOffset)); |
| 522 // Shift down 21 bits to get the most significant 11 bits or the low | 522 // Shift down 21 bits to get the most significant 11 bits or the low |
| 523 // mantissa word. | 523 // mantissa word. |
| 524 __ shr(ecx, 32 - big_shift_distance); | 524 __ shr(ecx, 32 - big_shift_distance); |
| 525 __ or_(ecx, Operand(scratch2)); | 525 __ or_(ecx, Operand(scratch2)); |
| 526 // We have the answer in ecx, but we may need to negate it. | 526 // We have the answer in ecx, but we may need to negate it. |
| 527 __ test(scratch, Operand(scratch)); | 527 __ test(scratch, Operand(scratch)); |
| 528 __ j(positive, &done); | 528 __ j(positive, &done, Label::kNear); |
| 529 __ neg(ecx); | 529 __ neg(ecx); |
| 530 __ jmp(&done); | 530 __ jmp(&done, Label::kNear); |
| 531 } | 531 } |
| 532 | 532 |
| 533 __ bind(&normal_exponent); | 533 __ bind(&normal_exponent); |
| 534 // Exponent word in scratch, exponent part of exponent word in scratch2. | 534 // Exponent word in scratch, exponent part of exponent word in scratch2. |
| 535 // Zero in ecx. | 535 // Zero in ecx. |
| 536 // We know the exponent is smaller than 30 (biased). If it is less than | 536 // We know the exponent is smaller than 30 (biased). If it is less than |
| 537 // 0 (biased) then the number is smaller in magnitude than 1.0 * 2^0, ie | 537 // 0 (biased) then the number is smaller in magnitude than 1.0 * 2^0, ie |
| 538 // it rounds to zero. | 538 // it rounds to zero. |
| 539 const uint32_t zero_exponent = | 539 const uint32_t zero_exponent = |
| 540 (HeapNumber::kExponentBias + 0) << HeapNumber::kExponentShift; | 540 (HeapNumber::kExponentBias + 0) << HeapNumber::kExponentShift; |
| 541 __ sub(Operand(scratch2), Immediate(zero_exponent)); | 541 __ sub(Operand(scratch2), Immediate(zero_exponent)); |
| 542 // ecx already has a Smi zero. | 542 // ecx already has a Smi zero. |
| 543 __ j(less, &done); | 543 __ j(less, &done, Label::kNear); |
| 544 | 544 |
| 545 // We have a shifted exponent between 0 and 30 in scratch2. | 545 // We have a shifted exponent between 0 and 30 in scratch2. |
| 546 __ shr(scratch2, HeapNumber::kExponentShift); | 546 __ shr(scratch2, HeapNumber::kExponentShift); |
| 547 __ mov(ecx, Immediate(30)); | 547 __ mov(ecx, Immediate(30)); |
| 548 __ sub(ecx, Operand(scratch2)); | 548 __ sub(ecx, Operand(scratch2)); |
| 549 | 549 |
| 550 __ bind(&right_exponent); | 550 __ bind(&right_exponent); |
| 551 // Here ecx is the shift, scratch is the exponent word. | 551 // Here ecx is the shift, scratch is the exponent word. |
| 552 // Get the top bits of the mantissa. | 552 // Get the top bits of the mantissa. |
| 553 __ and_(scratch, HeapNumber::kMantissaMask); | 553 __ and_(scratch, HeapNumber::kMantissaMask); |
| (...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 758 | 758 |
| 759 if (mode_ == UNARY_OVERWRITE) { | 759 if (mode_ == UNARY_OVERWRITE) { |
| 760 __ xor_(FieldOperand(eax, HeapNumber::kExponentOffset), | 760 __ xor_(FieldOperand(eax, HeapNumber::kExponentOffset), |
| 761 Immediate(HeapNumber::kSignMask)); // Flip sign. | 761 Immediate(HeapNumber::kSignMask)); // Flip sign. |
| 762 } else { | 762 } else { |
| 763 __ mov(edx, Operand(eax)); | 763 __ mov(edx, Operand(eax)); |
| 764 // edx: operand | 764 // edx: operand |
| 765 | 765 |
| 766 Label slow_allocate_heapnumber, heapnumber_allocated; | 766 Label slow_allocate_heapnumber, heapnumber_allocated; |
| 767 __ AllocateHeapNumber(eax, ebx, ecx, &slow_allocate_heapnumber); | 767 __ AllocateHeapNumber(eax, ebx, ecx, &slow_allocate_heapnumber); |
| 768 __ jmp(&heapnumber_allocated); | 768 __ jmp(&heapnumber_allocated, Label::kNear); |
| 769 | 769 |
| 770 __ bind(&slow_allocate_heapnumber); | 770 __ bind(&slow_allocate_heapnumber); |
| 771 __ EnterInternalFrame(); | 771 __ EnterInternalFrame(); |
| 772 __ push(edx); | 772 __ push(edx); |
| 773 __ CallRuntime(Runtime::kNumberAlloc, 0); | 773 __ CallRuntime(Runtime::kNumberAlloc, 0); |
| 774 __ pop(edx); | 774 __ pop(edx); |
| 775 __ LeaveInternalFrame(); | 775 __ LeaveInternalFrame(); |
| 776 | 776 |
| 777 __ bind(&heapnumber_allocated); | 777 __ bind(&heapnumber_allocated); |
| 778 // eax: allocated 'empty' number | 778 // eax: allocated 'empty' number |
| (...skipping 656 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1435 ASSERT(operands_type_ == BinaryOpIC::BOTH_STRING); | 1435 ASSERT(operands_type_ == BinaryOpIC::BOTH_STRING); |
| 1436 ASSERT(op_ == Token::ADD); | 1436 ASSERT(op_ == Token::ADD); |
| 1437 // If both arguments are strings, call the string add stub. | 1437 // If both arguments are strings, call the string add stub. |
| 1438 // Otherwise, do a transition. | 1438 // Otherwise, do a transition. |
| 1439 | 1439 |
| 1440 // Registers containing left and right operands respectively. | 1440 // Registers containing left and right operands respectively. |
| 1441 Register left = edx; | 1441 Register left = edx; |
| 1442 Register right = eax; | 1442 Register right = eax; |
| 1443 | 1443 |
| 1444 // Test if left operand is a string. | 1444 // Test if left operand is a string. |
| 1445 __ JumpIfSmi(left, &call_runtime); | 1445 __ JumpIfSmi(left, &call_runtime, Label::kNear); |
| 1446 __ CmpObjectType(left, FIRST_NONSTRING_TYPE, ecx); | 1446 __ CmpObjectType(left, FIRST_NONSTRING_TYPE, ecx); |
| 1447 __ j(above_equal, &call_runtime); | 1447 __ j(above_equal, &call_runtime, Label::kNear); |
| 1448 | 1448 |
| 1449 // Test if right operand is a string. | 1449 // Test if right operand is a string. |
| 1450 __ JumpIfSmi(right, &call_runtime); | 1450 __ JumpIfSmi(right, &call_runtime, Label::kNear); |
| 1451 __ CmpObjectType(right, FIRST_NONSTRING_TYPE, ecx); | 1451 __ CmpObjectType(right, FIRST_NONSTRING_TYPE, ecx); |
| 1452 __ j(above_equal, &call_runtime); | 1452 __ j(above_equal, &call_runtime, Label::kNear); |
| 1453 | 1453 |
| 1454 StringAddStub string_add_stub(NO_STRING_CHECK_IN_STUB); | 1454 StringAddStub string_add_stub(NO_STRING_CHECK_IN_STUB); |
| 1455 GenerateRegisterArgsPush(masm); | 1455 GenerateRegisterArgsPush(masm); |
| 1456 __ TailCallStub(&string_add_stub); | 1456 __ TailCallStub(&string_add_stub); |
| 1457 | 1457 |
| 1458 __ bind(&call_runtime); | 1458 __ bind(&call_runtime); |
| 1459 GenerateTypeTransition(masm); | 1459 GenerateTypeTransition(masm); |
| 1460 } | 1460 } |
| 1461 | 1461 |
| 1462 | 1462 |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1556 case Token::SHR: __ shr_cl(eax); break; | 1556 case Token::SHR: __ shr_cl(eax); break; |
| 1557 default: UNREACHABLE(); | 1557 default: UNREACHABLE(); |
| 1558 } | 1558 } |
| 1559 if (op_ == Token::SHR) { | 1559 if (op_ == Token::SHR) { |
| 1560 // Check if result is non-negative and fits in a smi. | 1560 // Check if result is non-negative and fits in a smi. |
| 1561 __ test(eax, Immediate(0xc0000000)); | 1561 __ test(eax, Immediate(0xc0000000)); |
| 1562 __ j(not_zero, &call_runtime); | 1562 __ j(not_zero, &call_runtime); |
| 1563 } else { | 1563 } else { |
| 1564 // Check if result fits in a smi. | 1564 // Check if result fits in a smi. |
| 1565 __ cmp(eax, 0xc0000000); | 1565 __ cmp(eax, 0xc0000000); |
| 1566 __ j(negative, &non_smi_result); | 1566 __ j(negative, &non_smi_result, Label::kNear); |
| 1567 } | 1567 } |
| 1568 // Tag smi result and return. | 1568 // Tag smi result and return. |
| 1569 __ SmiTag(eax); | 1569 __ SmiTag(eax); |
| 1570 __ ret(2 * kPointerSize); // Drop two pushed arguments from the stack. | 1570 __ ret(2 * kPointerSize); // Drop two pushed arguments from the stack. |
| 1571 | 1571 |
| 1572 // All ops except SHR return a signed int32 that we load in | 1572 // All ops except SHR return a signed int32 that we load in |
| 1573 // a HeapNumber. | 1573 // a HeapNumber. |
| 1574 if (op_ != Token::SHR) { | 1574 if (op_ != Token::SHR) { |
| 1575 __ bind(&non_smi_result); | 1575 __ bind(&non_smi_result); |
| 1576 // Allocate a heap number if needed. | 1576 // Allocate a heap number if needed. |
| (...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1770 case Token::SHR: __ shr_cl(eax); break; | 1770 case Token::SHR: __ shr_cl(eax); break; |
| 1771 default: UNREACHABLE(); | 1771 default: UNREACHABLE(); |
| 1772 } | 1772 } |
| 1773 if (op_ == Token::SHR) { | 1773 if (op_ == Token::SHR) { |
| 1774 // Check if result is non-negative and fits in a smi. | 1774 // Check if result is non-negative and fits in a smi. |
| 1775 __ test(eax, Immediate(0xc0000000)); | 1775 __ test(eax, Immediate(0xc0000000)); |
| 1776 __ j(not_zero, &call_runtime); | 1776 __ j(not_zero, &call_runtime); |
| 1777 } else { | 1777 } else { |
| 1778 // Check if result fits in a smi. | 1778 // Check if result fits in a smi. |
| 1779 __ cmp(eax, 0xc0000000); | 1779 __ cmp(eax, 0xc0000000); |
| 1780 __ j(negative, &non_smi_result); | 1780 __ j(negative, &non_smi_result, Label::kNear); |
| 1781 } | 1781 } |
| 1782 // Tag smi result and return. | 1782 // Tag smi result and return. |
| 1783 __ SmiTag(eax); | 1783 __ SmiTag(eax); |
| 1784 __ ret(2 * kPointerSize); // Drop two pushed arguments from the stack. | 1784 __ ret(2 * kPointerSize); // Drop two pushed arguments from the stack. |
| 1785 | 1785 |
| 1786 // All ops except SHR return a signed int32 that we load in | 1786 // All ops except SHR return a signed int32 that we load in |
| 1787 // a HeapNumber. | 1787 // a HeapNumber. |
| 1788 if (op_ != Token::SHR) { | 1788 if (op_ != Token::SHR) { |
| 1789 __ bind(&non_smi_result); | 1789 __ bind(&non_smi_result); |
| 1790 // Allocate a heap number if needed. | 1790 // Allocate a heap number if needed. |
| (...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1969 case Token::SHR: __ shr_cl(eax); break; | 1969 case Token::SHR: __ shr_cl(eax); break; |
| 1970 default: UNREACHABLE(); | 1970 default: UNREACHABLE(); |
| 1971 } | 1971 } |
| 1972 if (op_ == Token::SHR) { | 1972 if (op_ == Token::SHR) { |
| 1973 // Check if result is non-negative and fits in a smi. | 1973 // Check if result is non-negative and fits in a smi. |
| 1974 __ test(eax, Immediate(0xc0000000)); | 1974 __ test(eax, Immediate(0xc0000000)); |
| 1975 __ j(not_zero, &call_runtime); | 1975 __ j(not_zero, &call_runtime); |
| 1976 } else { | 1976 } else { |
| 1977 // Check if result fits in a smi. | 1977 // Check if result fits in a smi. |
| 1978 __ cmp(eax, 0xc0000000); | 1978 __ cmp(eax, 0xc0000000); |
| 1979 __ j(negative, &non_smi_result); | 1979 __ j(negative, &non_smi_result, Label::kNear); |
| 1980 } | 1980 } |
| 1981 // Tag smi result and return. | 1981 // Tag smi result and return. |
| 1982 __ SmiTag(eax); | 1982 __ SmiTag(eax); |
| 1983 __ ret(2 * kPointerSize); // Drop the arguments from the stack. | 1983 __ ret(2 * kPointerSize); // Drop the arguments from the stack. |
| 1984 | 1984 |
| 1985 // All ops except SHR return a signed int32 that we load in | 1985 // All ops except SHR return a signed int32 that we load in |
| 1986 // a HeapNumber. | 1986 // a HeapNumber. |
| 1987 if (op_ != Token::SHR) { | 1987 if (op_ != Token::SHR) { |
| 1988 __ bind(&non_smi_result); | 1988 __ bind(&non_smi_result); |
| 1989 // Allocate a heap number if needed. | 1989 // Allocate a heap number if needed. |
| (...skipping 454 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2444 // Output: eax, ecx are left and right integers for a bit op. | 2444 // Output: eax, ecx are left and right integers for a bit op. |
| 2445 void FloatingPointHelper::LoadUnknownsAsIntegers(MacroAssembler* masm, | 2445 void FloatingPointHelper::LoadUnknownsAsIntegers(MacroAssembler* masm, |
| 2446 bool use_sse3, | 2446 bool use_sse3, |
| 2447 Label* conversion_failure) { | 2447 Label* conversion_failure) { |
| 2448 // Check float operands. | 2448 // Check float operands. |
| 2449 Label arg1_is_object, check_undefined_arg1; | 2449 Label arg1_is_object, check_undefined_arg1; |
| 2450 Label arg2_is_object, check_undefined_arg2; | 2450 Label arg2_is_object, check_undefined_arg2; |
| 2451 Label load_arg2, done; | 2451 Label load_arg2, done; |
| 2452 | 2452 |
| 2453 // Test if arg1 is a Smi. | 2453 // Test if arg1 is a Smi. |
| 2454 __ JumpIfNotSmi(edx, &arg1_is_object); | 2454 __ JumpIfNotSmi(edx, &arg1_is_object, Label::kNear); |
| 2455 | 2455 |
| 2456 __ SmiUntag(edx); | 2456 __ SmiUntag(edx); |
| 2457 __ jmp(&load_arg2); | 2457 __ jmp(&load_arg2, Label::kNear); |
| 2458 | 2458 |
| 2459 // If the argument is undefined it converts to zero (ECMA-262, section 9.5). | 2459 // If the argument is undefined it converts to zero (ECMA-262, section 9.5). |
| 2460 __ bind(&check_undefined_arg1); | 2460 __ bind(&check_undefined_arg1); |
| 2461 Factory* factory = masm->isolate()->factory(); | 2461 Factory* factory = masm->isolate()->factory(); |
| 2462 __ cmp(edx, factory->undefined_value()); | 2462 __ cmp(edx, factory->undefined_value()); |
| 2463 __ j(not_equal, conversion_failure); | 2463 __ j(not_equal, conversion_failure); |
| 2464 __ mov(edx, Immediate(0)); | 2464 __ mov(edx, Immediate(0)); |
| 2465 __ jmp(&load_arg2); | 2465 __ jmp(&load_arg2, Label::kNear); |
| 2466 | 2466 |
| 2467 __ bind(&arg1_is_object); | 2467 __ bind(&arg1_is_object); |
| 2468 __ mov(ebx, FieldOperand(edx, HeapObject::kMapOffset)); | 2468 __ mov(ebx, FieldOperand(edx, HeapObject::kMapOffset)); |
| 2469 __ cmp(ebx, factory->heap_number_map()); | 2469 __ cmp(ebx, factory->heap_number_map()); |
| 2470 __ j(not_equal, &check_undefined_arg1); | 2470 __ j(not_equal, &check_undefined_arg1); |
| 2471 | 2471 |
| 2472 // Get the untagged integer version of the edx heap number in ecx. | 2472 // Get the untagged integer version of the edx heap number in ecx. |
| 2473 IntegerConvert(masm, edx, use_sse3, conversion_failure); | 2473 IntegerConvert(masm, edx, use_sse3, conversion_failure); |
| 2474 __ mov(edx, ecx); | 2474 __ mov(edx, ecx); |
| 2475 | 2475 |
| 2476 // Here edx has the untagged integer, eax has a Smi or a heap number. | 2476 // Here edx has the untagged integer, eax has a Smi or a heap number. |
| 2477 __ bind(&load_arg2); | 2477 __ bind(&load_arg2); |
| 2478 | 2478 |
| 2479 // Test if arg2 is a Smi. | 2479 // Test if arg2 is a Smi. |
| 2480 __ JumpIfNotSmi(eax, &arg2_is_object); | 2480 __ JumpIfNotSmi(eax, &arg2_is_object, Label::kNear); |
| 2481 | 2481 |
| 2482 __ SmiUntag(eax); | 2482 __ SmiUntag(eax); |
| 2483 __ mov(ecx, eax); | 2483 __ mov(ecx, eax); |
| 2484 __ jmp(&done); | 2484 __ jmp(&done, Label::kNear); |
| 2485 | 2485 |
| 2486 // If the argument is undefined it converts to zero (ECMA-262, section 9.5). | 2486 // If the argument is undefined it converts to zero (ECMA-262, section 9.5). |
| 2487 __ bind(&check_undefined_arg2); | 2487 __ bind(&check_undefined_arg2); |
| 2488 __ cmp(eax, factory->undefined_value()); | 2488 __ cmp(eax, factory->undefined_value()); |
| 2489 __ j(not_equal, conversion_failure); | 2489 __ j(not_equal, conversion_failure); |
| 2490 __ mov(ecx, Immediate(0)); | 2490 __ mov(ecx, Immediate(0)); |
| 2491 __ jmp(&done); | 2491 __ jmp(&done, Label::kNear); |
| 2492 | 2492 |
| 2493 __ bind(&arg2_is_object); | 2493 __ bind(&arg2_is_object); |
| 2494 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); | 2494 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); |
| 2495 __ cmp(ebx, factory->heap_number_map()); | 2495 __ cmp(ebx, factory->heap_number_map()); |
| 2496 __ j(not_equal, &check_undefined_arg2); | 2496 __ j(not_equal, &check_undefined_arg2); |
| 2497 | 2497 |
| 2498 // Get the untagged integer version of the eax heap number in ecx. | 2498 // Get the untagged integer version of the eax heap number in ecx. |
| 2499 IntegerConvert(masm, eax, use_sse3, conversion_failure); | 2499 IntegerConvert(masm, eax, use_sse3, conversion_failure); |
| 2500 __ bind(&done); | 2500 __ bind(&done); |
| 2501 __ mov(eax, edx); | 2501 __ mov(eax, edx); |
| (...skipping 358 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2860 void ArgumentsAccessStub::GenerateReadElement(MacroAssembler* masm) { | 2860 void ArgumentsAccessStub::GenerateReadElement(MacroAssembler* masm) { |
| 2861 // The key is in edx and the parameter count is in eax. | 2861 // The key is in edx and the parameter count is in eax. |
| 2862 | 2862 |
| 2863 // The displacement is used for skipping the frame pointer on the | 2863 // The displacement is used for skipping the frame pointer on the |
| 2864 // stack. It is the offset of the last parameter (if any) relative | 2864 // stack. It is the offset of the last parameter (if any) relative |
| 2865 // to the frame pointer. | 2865 // to the frame pointer. |
| 2866 static const int kDisplacement = 1 * kPointerSize; | 2866 static const int kDisplacement = 1 * kPointerSize; |
| 2867 | 2867 |
| 2868 // Check that the key is a smi. | 2868 // Check that the key is a smi. |
| 2869 Label slow; | 2869 Label slow; |
| 2870 __ JumpIfNotSmi(edx, &slow); | 2870 __ JumpIfNotSmi(edx, &slow, Label::kNear); |
| 2871 | 2871 |
| 2872 // Check if the calling frame is an arguments adaptor frame. | 2872 // Check if the calling frame is an arguments adaptor frame. |
| 2873 Label adaptor; | 2873 Label adaptor; |
| 2874 __ mov(ebx, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); | 2874 __ mov(ebx, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); |
| 2875 __ mov(ecx, Operand(ebx, StandardFrameConstants::kContextOffset)); | 2875 __ mov(ecx, Operand(ebx, StandardFrameConstants::kContextOffset)); |
| 2876 __ cmp(Operand(ecx), Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); | 2876 __ cmp(Operand(ecx), Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); |
| 2877 __ j(equal, &adaptor, Label::kNear); | 2877 __ j(equal, &adaptor, Label::kNear); |
| 2878 | 2878 |
| 2879 // Check index against formal parameters count limit passed in | 2879 // Check index against formal parameters count limit passed in |
| 2880 // through register eax. Use unsigned comparison to get negative | 2880 // through register eax. Use unsigned comparison to get negative |
| 2881 // check for free. | 2881 // check for free. |
| 2882 __ cmp(edx, Operand(eax)); | 2882 __ cmp(edx, Operand(eax)); |
| 2883 __ j(above_equal, &slow); | 2883 __ j(above_equal, &slow, Label::kNear); |
| 2884 | 2884 |
| 2885 // Read the argument from the stack and return it. | 2885 // Read the argument from the stack and return it. |
| 2886 STATIC_ASSERT(kSmiTagSize == 1); | 2886 STATIC_ASSERT(kSmiTagSize == 1); |
| 2887 STATIC_ASSERT(kSmiTag == 0); // Shifting code depends on these. | 2887 STATIC_ASSERT(kSmiTag == 0); // Shifting code depends on these. |
| 2888 __ lea(ebx, Operand(ebp, eax, times_2, 0)); | 2888 __ lea(ebx, Operand(ebp, eax, times_2, 0)); |
| 2889 __ neg(edx); | 2889 __ neg(edx); |
| 2890 __ mov(eax, Operand(ebx, edx, times_2, kDisplacement)); | 2890 __ mov(eax, Operand(ebx, edx, times_2, kDisplacement)); |
| 2891 __ ret(0); | 2891 __ ret(0); |
| 2892 | 2892 |
| 2893 // Arguments adaptor case: Check index against actual arguments | 2893 // Arguments adaptor case: Check index against actual arguments |
| 2894 // limit found in the arguments adaptor frame. Use unsigned | 2894 // limit found in the arguments adaptor frame. Use unsigned |
| 2895 // comparison to get negative check for free. | 2895 // comparison to get negative check for free. |
| 2896 __ bind(&adaptor); | 2896 __ bind(&adaptor); |
| 2897 __ mov(ecx, Operand(ebx, ArgumentsAdaptorFrameConstants::kLengthOffset)); | 2897 __ mov(ecx, Operand(ebx, ArgumentsAdaptorFrameConstants::kLengthOffset)); |
| 2898 __ cmp(edx, Operand(ecx)); | 2898 __ cmp(edx, Operand(ecx)); |
| 2899 __ j(above_equal, &slow); | 2899 __ j(above_equal, &slow, Label::kNear); |
| 2900 | 2900 |
| 2901 // Read the argument from the stack and return it. | 2901 // Read the argument from the stack and return it. |
| 2902 STATIC_ASSERT(kSmiTagSize == 1); | 2902 STATIC_ASSERT(kSmiTagSize == 1); |
| 2903 STATIC_ASSERT(kSmiTag == 0); // Shifting code depends on these. | 2903 STATIC_ASSERT(kSmiTag == 0); // Shifting code depends on these. |
| 2904 __ lea(ebx, Operand(ebx, ecx, times_2, 0)); | 2904 __ lea(ebx, Operand(ebx, ecx, times_2, 0)); |
| 2905 __ neg(edx); | 2905 __ neg(edx); |
| 2906 __ mov(eax, Operand(ebx, edx, times_2, kDisplacement)); | 2906 __ mov(eax, Operand(ebx, edx, times_2, kDisplacement)); |
| 2907 __ ret(0); | 2907 __ ret(0); |
| 2908 | 2908 |
| 2909 // Slow-case: Handle non-smi or out-of-bounds access to arguments | 2909 // Slow-case: Handle non-smi or out-of-bounds access to arguments |
| (...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3168 // esp[0] : return address | 3168 // esp[0] : return address |
| 3169 // esp[4] : number of parameters | 3169 // esp[4] : number of parameters |
| 3170 // esp[8] : receiver displacement | 3170 // esp[8] : receiver displacement |
| 3171 // esp[12] : function | 3171 // esp[12] : function |
| 3172 | 3172 |
| 3173 // Check if the calling frame is an arguments adaptor frame. | 3173 // Check if the calling frame is an arguments adaptor frame. |
| 3174 Label adaptor_frame, try_allocate, runtime; | 3174 Label adaptor_frame, try_allocate, runtime; |
| 3175 __ mov(edx, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); | 3175 __ mov(edx, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); |
| 3176 __ mov(ecx, Operand(edx, StandardFrameConstants::kContextOffset)); | 3176 __ mov(ecx, Operand(edx, StandardFrameConstants::kContextOffset)); |
| 3177 __ cmp(Operand(ecx), Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); | 3177 __ cmp(Operand(ecx), Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); |
| 3178 __ j(equal, &adaptor_frame); | 3178 __ j(equal, &adaptor_frame, Label::kNear); |
| 3179 | 3179 |
| 3180 // Get the length from the frame. | 3180 // Get the length from the frame. |
| 3181 __ mov(ecx, Operand(esp, 1 * kPointerSize)); | 3181 __ mov(ecx, Operand(esp, 1 * kPointerSize)); |
| 3182 __ jmp(&try_allocate); | 3182 __ jmp(&try_allocate, Label::kNear); |
| 3183 | 3183 |
| 3184 // Patch the arguments.length and the parameters pointer. | 3184 // Patch the arguments.length and the parameters pointer. |
| 3185 __ bind(&adaptor_frame); | 3185 __ bind(&adaptor_frame); |
| 3186 __ mov(ecx, Operand(edx, ArgumentsAdaptorFrameConstants::kLengthOffset)); | 3186 __ mov(ecx, Operand(edx, ArgumentsAdaptorFrameConstants::kLengthOffset)); |
| 3187 __ mov(Operand(esp, 1 * kPointerSize), ecx); | 3187 __ mov(Operand(esp, 1 * kPointerSize), ecx); |
| 3188 __ lea(edx, Operand(edx, ecx, times_2, | 3188 __ lea(edx, Operand(edx, ecx, times_2, |
| 3189 StandardFrameConstants::kCallerSPOffset)); | 3189 StandardFrameConstants::kCallerSPOffset)); |
| 3190 __ mov(Operand(esp, 2 * kPointerSize), edx); | 3190 __ mov(Operand(esp, 2 * kPointerSize), edx); |
| 3191 | 3191 |
| 3192 // Try the new space allocation. Start out with computing the size of | 3192 // Try the new space allocation. Start out with computing the size of |
| (...skipping 25 matching lines...) Expand all Loading... |
| 3218 // Get the length (smi tagged) and set that as an in-object property too. | 3218 // Get the length (smi tagged) and set that as an in-object property too. |
| 3219 STATIC_ASSERT(Heap::kArgumentsLengthIndex == 0); | 3219 STATIC_ASSERT(Heap::kArgumentsLengthIndex == 0); |
| 3220 __ mov(ecx, Operand(esp, 1 * kPointerSize)); | 3220 __ mov(ecx, Operand(esp, 1 * kPointerSize)); |
| 3221 __ mov(FieldOperand(eax, JSObject::kHeaderSize + | 3221 __ mov(FieldOperand(eax, JSObject::kHeaderSize + |
| 3222 Heap::kArgumentsLengthIndex * kPointerSize), | 3222 Heap::kArgumentsLengthIndex * kPointerSize), |
| 3223 ecx); | 3223 ecx); |
| 3224 | 3224 |
| 3225 // If there are no actual arguments, we're done. | 3225 // If there are no actual arguments, we're done. |
| 3226 Label done; | 3226 Label done; |
| 3227 __ test(ecx, Operand(ecx)); | 3227 __ test(ecx, Operand(ecx)); |
| 3228 __ j(zero, &done); | 3228 __ j(zero, &done, Label::kNear); |
| 3229 | 3229 |
| 3230 // Get the parameters pointer from the stack. | 3230 // Get the parameters pointer from the stack. |
| 3231 __ mov(edx, Operand(esp, 2 * kPointerSize)); | 3231 __ mov(edx, Operand(esp, 2 * kPointerSize)); |
| 3232 | 3232 |
| 3233 // Setup the elements pointer in the allocated arguments object and | 3233 // Setup the elements pointer in the allocated arguments object and |
| 3234 // initialize the header in the elements fixed array. | 3234 // initialize the header in the elements fixed array. |
| 3235 __ lea(edi, Operand(eax, Heap::kArgumentsObjectSizeStrict)); | 3235 __ lea(edi, Operand(eax, Heap::kArgumentsObjectSizeStrict)); |
| 3236 __ mov(FieldOperand(eax, JSObject::kElementsOffset), edi); | 3236 __ mov(FieldOperand(eax, JSObject::kElementsOffset), edi); |
| 3237 __ mov(FieldOperand(edi, FixedArray::kMapOffset), | 3237 __ mov(FieldOperand(edi, FixedArray::kMapOffset), |
| 3238 Immediate(FACTORY->fixed_array_map())); | 3238 Immediate(FACTORY->fixed_array_map())); |
| (...skipping 576 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3815 static int NegativeComparisonResult(Condition cc) { | 3815 static int NegativeComparisonResult(Condition cc) { |
| 3816 ASSERT(cc != equal); | 3816 ASSERT(cc != equal); |
| 3817 ASSERT((cc == less) || (cc == less_equal) | 3817 ASSERT((cc == less) || (cc == less_equal) |
| 3818 || (cc == greater) || (cc == greater_equal)); | 3818 || (cc == greater) || (cc == greater_equal)); |
| 3819 return (cc == greater || cc == greater_equal) ? LESS : GREATER; | 3819 return (cc == greater || cc == greater_equal) ? LESS : GREATER; |
| 3820 } | 3820 } |
| 3821 | 3821 |
| 3822 void CompareStub::Generate(MacroAssembler* masm) { | 3822 void CompareStub::Generate(MacroAssembler* masm) { |
| 3823 ASSERT(lhs_.is(no_reg) && rhs_.is(no_reg)); | 3823 ASSERT(lhs_.is(no_reg) && rhs_.is(no_reg)); |
| 3824 | 3824 |
| 3825 Label check_unequal_objects, done; | 3825 Label check_unequal_objects; |
| 3826 | 3826 |
| 3827 // Compare two smis if required. | 3827 // Compare two smis if required. |
| 3828 if (include_smi_compare_) { | 3828 if (include_smi_compare_) { |
| 3829 Label non_smi, smi_done; | 3829 Label non_smi, smi_done; |
| 3830 __ mov(ecx, Operand(edx)); | 3830 __ mov(ecx, Operand(edx)); |
| 3831 __ or_(ecx, Operand(eax)); | 3831 __ or_(ecx, Operand(eax)); |
| 3832 __ JumpIfNotSmi(ecx, &non_smi); | 3832 __ JumpIfNotSmi(ecx, &non_smi, Label::kNear); |
| 3833 __ sub(edx, Operand(eax)); // Return on the result of the subtraction. | 3833 __ sub(edx, Operand(eax)); // Return on the result of the subtraction. |
| 3834 __ j(no_overflow, &smi_done); | 3834 __ j(no_overflow, &smi_done, Label::kNear); |
| 3835 __ not_(edx); // Correct sign in case of overflow. edx is never 0 here. | 3835 __ not_(edx); // Correct sign in case of overflow. edx is never 0 here. |
| 3836 __ bind(&smi_done); | 3836 __ bind(&smi_done); |
| 3837 __ mov(eax, edx); | 3837 __ mov(eax, edx); |
| 3838 __ ret(0); | 3838 __ ret(0); |
| 3839 __ bind(&non_smi); | 3839 __ bind(&non_smi); |
| 3840 } else if (FLAG_debug_code) { | 3840 } else if (FLAG_debug_code) { |
| 3841 __ mov(ecx, Operand(edx)); | 3841 __ mov(ecx, Operand(edx)); |
| 3842 __ or_(ecx, Operand(eax)); | 3842 __ or_(ecx, Operand(eax)); |
| 3843 __ test(ecx, Immediate(kSmiTagMask)); | 3843 __ test(ecx, Immediate(kSmiTagMask)); |
| 3844 __ Assert(not_zero, "Unexpected smi operands."); | 3844 __ Assert(not_zero, "Unexpected smi operands."); |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3946 __ mov(ebx, edx); | 3946 __ mov(ebx, edx); |
| 3947 __ xor_(ebx, Operand(eax)); | 3947 __ xor_(ebx, Operand(eax)); |
| 3948 __ and_(ebx, Operand(ecx)); // ebx holds either 0 or eax ^ edx. | 3948 __ and_(ebx, Operand(ecx)); // ebx holds either 0 or eax ^ edx. |
| 3949 __ xor_(ebx, Operand(eax)); | 3949 __ xor_(ebx, Operand(eax)); |
| 3950 // if eax was smi, ebx is now edx, else eax. | 3950 // if eax was smi, ebx is now edx, else eax. |
| 3951 | 3951 |
| 3952 // Check if the non-smi operand is a heap number. | 3952 // Check if the non-smi operand is a heap number. |
| 3953 __ cmp(FieldOperand(ebx, HeapObject::kMapOffset), | 3953 __ cmp(FieldOperand(ebx, HeapObject::kMapOffset), |
| 3954 Immediate(masm->isolate()->factory()->heap_number_map())); | 3954 Immediate(masm->isolate()->factory()->heap_number_map())); |
| 3955 // If heap number, handle it in the slow case. | 3955 // If heap number, handle it in the slow case. |
| 3956 __ j(equal, &slow); | 3956 __ j(equal, &slow, Label::kNear); |
| 3957 // Return non-equal (ebx is not zero) | 3957 // Return non-equal (ebx is not zero) |
| 3958 __ mov(eax, ebx); | 3958 __ mov(eax, ebx); |
| 3959 __ ret(0); | 3959 __ ret(0); |
| 3960 | 3960 |
| 3961 __ bind(¬_smis); | 3961 __ bind(¬_smis); |
| 3962 // If either operand is a JSObject or an oddball value, then they are not | 3962 // If either operand is a JSObject or an oddball value, then they are not |
| 3963 // equal since their pointers are different | 3963 // equal since their pointers are different |
| 3964 // There is no test for undetectability in strict equality. | 3964 // There is no test for undetectability in strict equality. |
| 3965 | 3965 |
| 3966 // Get the type of the first operand. | 3966 // Get the type of the first operand. |
| (...skipping 30 matching lines...) Expand all Loading... |
| 3997 Label non_number_comparison; | 3997 Label non_number_comparison; |
| 3998 Label unordered; | 3998 Label unordered; |
| 3999 if (CpuFeatures::IsSupported(SSE2)) { | 3999 if (CpuFeatures::IsSupported(SSE2)) { |
| 4000 CpuFeatures::Scope use_sse2(SSE2); | 4000 CpuFeatures::Scope use_sse2(SSE2); |
| 4001 CpuFeatures::Scope use_cmov(CMOV); | 4001 CpuFeatures::Scope use_cmov(CMOV); |
| 4002 | 4002 |
| 4003 FloatingPointHelper::LoadSSE2Operands(masm, &non_number_comparison); | 4003 FloatingPointHelper::LoadSSE2Operands(masm, &non_number_comparison); |
| 4004 __ ucomisd(xmm0, xmm1); | 4004 __ ucomisd(xmm0, xmm1); |
| 4005 | 4005 |
| 4006 // Don't base result on EFLAGS when a NaN is involved. | 4006 // Don't base result on EFLAGS when a NaN is involved. |
| 4007 __ j(parity_even, &unordered); | 4007 __ j(parity_even, &unordered, Label::kNear); |
| 4008 // Return a result of -1, 0, or 1, based on EFLAGS. | 4008 // Return a result of -1, 0, or 1, based on EFLAGS. |
| 4009 __ mov(eax, 0); // equal | 4009 __ mov(eax, 0); // equal |
| 4010 __ mov(ecx, Immediate(Smi::FromInt(1))); | 4010 __ mov(ecx, Immediate(Smi::FromInt(1))); |
| 4011 __ cmov(above, eax, Operand(ecx)); | 4011 __ cmov(above, eax, Operand(ecx)); |
| 4012 __ mov(ecx, Immediate(Smi::FromInt(-1))); | 4012 __ mov(ecx, Immediate(Smi::FromInt(-1))); |
| 4013 __ cmov(below, eax, Operand(ecx)); | 4013 __ cmov(below, eax, Operand(ecx)); |
| 4014 __ ret(0); | 4014 __ ret(0); |
| 4015 } else { | 4015 } else { |
| 4016 FloatingPointHelper::CheckFloatOperands( | 4016 FloatingPointHelper::CheckFloatOperands( |
| 4017 masm, &non_number_comparison, ebx); | 4017 masm, &non_number_comparison, ebx); |
| 4018 FloatingPointHelper::LoadFloatOperand(masm, eax); | 4018 FloatingPointHelper::LoadFloatOperand(masm, eax); |
| 4019 FloatingPointHelper::LoadFloatOperand(masm, edx); | 4019 FloatingPointHelper::LoadFloatOperand(masm, edx); |
| 4020 __ FCmp(); | 4020 __ FCmp(); |
| 4021 | 4021 |
| 4022 // Don't base result on EFLAGS when a NaN is involved. | 4022 // Don't base result on EFLAGS when a NaN is involved. |
| 4023 __ j(parity_even, &unordered); | 4023 __ j(parity_even, &unordered, Label::kNear); |
| 4024 | 4024 |
| 4025 Label below_label, above_label; | 4025 Label below_label, above_label; |
| 4026 // Return a result of -1, 0, or 1, based on EFLAGS. | 4026 // Return a result of -1, 0, or 1, based on EFLAGS. |
| 4027 __ j(below, &below_label); | 4027 __ j(below, &below_label, Label::kNear); |
| 4028 __ j(above, &above_label); | 4028 __ j(above, &above_label, Label::kNear); |
| 4029 | 4029 |
| 4030 __ Set(eax, Immediate(0)); | 4030 __ Set(eax, Immediate(0)); |
| 4031 __ ret(0); | 4031 __ ret(0); |
| 4032 | 4032 |
| 4033 __ bind(&below_label); | 4033 __ bind(&below_label); |
| 4034 __ mov(eax, Immediate(Smi::FromInt(-1))); | 4034 __ mov(eax, Immediate(Smi::FromInt(-1))); |
| 4035 __ ret(0); | 4035 __ ret(0); |
| 4036 | 4036 |
| 4037 __ bind(&above_label); | 4037 __ bind(&above_label); |
| 4038 __ mov(eax, Immediate(Smi::FromInt(1))); | 4038 __ mov(eax, Immediate(Smi::FromInt(1))); |
| (...skipping 294 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4333 __ LeaveExitFrame(save_doubles_); | 4333 __ LeaveExitFrame(save_doubles_); |
| 4334 __ ret(0); | 4334 __ ret(0); |
| 4335 | 4335 |
| 4336 // Handling of failure. | 4336 // Handling of failure. |
| 4337 __ bind(&failure_returned); | 4337 __ bind(&failure_returned); |
| 4338 | 4338 |
| 4339 Label retry; | 4339 Label retry; |
| 4340 // If the returned exception is RETRY_AFTER_GC continue at retry label | 4340 // If the returned exception is RETRY_AFTER_GC continue at retry label |
| 4341 STATIC_ASSERT(Failure::RETRY_AFTER_GC == 0); | 4341 STATIC_ASSERT(Failure::RETRY_AFTER_GC == 0); |
| 4342 __ test(eax, Immediate(((1 << kFailureTypeTagSize) - 1) << kFailureTagSize)); | 4342 __ test(eax, Immediate(((1 << kFailureTypeTagSize) - 1) << kFailureTagSize)); |
| 4343 __ j(zero, &retry); | 4343 __ j(zero, &retry, Label::kNear); |
| 4344 | 4344 |
| 4345 // Special handling of out of memory exceptions. | 4345 // Special handling of out of memory exceptions. |
| 4346 __ cmp(eax, reinterpret_cast<int32_t>(Failure::OutOfMemoryException())); | 4346 __ cmp(eax, reinterpret_cast<int32_t>(Failure::OutOfMemoryException())); |
| 4347 __ j(equal, throw_out_of_memory_exception); | 4347 __ j(equal, throw_out_of_memory_exception); |
| 4348 | 4348 |
| 4349 // Retrieve the pending exception and clear the variable. | 4349 // Retrieve the pending exception and clear the variable. |
| 4350 ExternalReference the_hole_location = | 4350 ExternalReference the_hole_location = |
| 4351 ExternalReference::the_hole_value_location(masm->isolate()); | 4351 ExternalReference::the_hole_value_location(masm->isolate()); |
| 4352 __ mov(eax, Operand::StaticVariable(pending_exception_address)); | 4352 __ mov(eax, Operand::StaticVariable(pending_exception_address)); |
| 4353 __ mov(edx, Operand::StaticVariable(the_hole_location)); | 4353 __ mov(edx, Operand::StaticVariable(the_hole_location)); |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4453 __ push(ebx); | 4453 __ push(ebx); |
| 4454 | 4454 |
| 4455 // Save copies of the top frame descriptor on the stack. | 4455 // Save copies of the top frame descriptor on the stack. |
| 4456 ExternalReference c_entry_fp(Isolate::k_c_entry_fp_address, masm->isolate()); | 4456 ExternalReference c_entry_fp(Isolate::k_c_entry_fp_address, masm->isolate()); |
| 4457 __ push(Operand::StaticVariable(c_entry_fp)); | 4457 __ push(Operand::StaticVariable(c_entry_fp)); |
| 4458 | 4458 |
| 4459 // If this is the outermost JS call, set js_entry_sp value. | 4459 // If this is the outermost JS call, set js_entry_sp value. |
| 4460 ExternalReference js_entry_sp(Isolate::k_js_entry_sp_address, | 4460 ExternalReference js_entry_sp(Isolate::k_js_entry_sp_address, |
| 4461 masm->isolate()); | 4461 masm->isolate()); |
| 4462 __ cmp(Operand::StaticVariable(js_entry_sp), Immediate(0)); | 4462 __ cmp(Operand::StaticVariable(js_entry_sp), Immediate(0)); |
| 4463 __ j(not_equal, ¬_outermost_js); | 4463 __ j(not_equal, ¬_outermost_js, Label::kNear); |
| 4464 __ mov(Operand::StaticVariable(js_entry_sp), ebp); | 4464 __ mov(Operand::StaticVariable(js_entry_sp), ebp); |
| 4465 __ push(Immediate(Smi::FromInt(StackFrame::OUTERMOST_JSENTRY_FRAME))); | 4465 __ push(Immediate(Smi::FromInt(StackFrame::OUTERMOST_JSENTRY_FRAME))); |
| 4466 Label cont; | 4466 Label cont; |
| 4467 __ jmp(&cont); | 4467 __ jmp(&cont, Label::kNear); |
| 4468 __ bind(¬_outermost_js); | 4468 __ bind(¬_outermost_js); |
| 4469 __ push(Immediate(Smi::FromInt(StackFrame::INNER_JSENTRY_FRAME))); | 4469 __ push(Immediate(Smi::FromInt(StackFrame::INNER_JSENTRY_FRAME))); |
| 4470 __ bind(&cont); | 4470 __ bind(&cont); |
| 4471 | 4471 |
| 4472 // Call a faked try-block that does the invoke. | 4472 // Call a faked try-block that does the invoke. |
| 4473 __ call(&invoke); | 4473 __ call(&invoke); |
| 4474 | 4474 |
| 4475 // Caught exception: Store result (exception) in the pending | 4475 // Caught exception: Store result (exception) in the pending |
| 4476 // exception field in the JSEnv and return a failure sentinel. | 4476 // exception field in the JSEnv and return a failure sentinel. |
| 4477 ExternalReference pending_exception(Isolate::k_pending_exception_address, | 4477 ExternalReference pending_exception(Isolate::k_pending_exception_address, |
| (...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4698 if (!ReturnTrueFalseObject()) { | 4698 if (!ReturnTrueFalseObject()) { |
| 4699 __ Set(eax, Immediate(Smi::FromInt(1))); | 4699 __ Set(eax, Immediate(Smi::FromInt(1))); |
| 4700 } | 4700 } |
| 4701 } | 4701 } |
| 4702 __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize); | 4702 __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize); |
| 4703 | 4703 |
| 4704 Label object_not_null, object_not_null_or_smi; | 4704 Label object_not_null, object_not_null_or_smi; |
| 4705 __ bind(¬_js_object); | 4705 __ bind(¬_js_object); |
| 4706 // Before null, smi and string value checks, check that the rhs is a function | 4706 // Before null, smi and string value checks, check that the rhs is a function |
| 4707 // as for a non-function rhs an exception needs to be thrown. | 4707 // as for a non-function rhs an exception needs to be thrown. |
| 4708 __ JumpIfSmi(function, &slow); | 4708 __ JumpIfSmi(function, &slow, Label::kNear); |
| 4709 __ CmpObjectType(function, JS_FUNCTION_TYPE, scratch); | 4709 __ CmpObjectType(function, JS_FUNCTION_TYPE, scratch); |
| 4710 __ j(not_equal, &slow); | 4710 __ j(not_equal, &slow, Label::kNear); |
| 4711 | 4711 |
| 4712 // Null is not instance of anything. | 4712 // Null is not instance of anything. |
| 4713 __ cmp(object, factory->null_value()); | 4713 __ cmp(object, factory->null_value()); |
| 4714 __ j(not_equal, &object_not_null); | 4714 __ j(not_equal, &object_not_null, Label::kNear); |
| 4715 __ Set(eax, Immediate(Smi::FromInt(1))); | 4715 __ Set(eax, Immediate(Smi::FromInt(1))); |
| 4716 __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize); | 4716 __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize); |
| 4717 | 4717 |
| 4718 __ bind(&object_not_null); | 4718 __ bind(&object_not_null); |
| 4719 // Smi values is not instance of anything. | 4719 // Smi values is not instance of anything. |
| 4720 __ JumpIfNotSmi(object, &object_not_null_or_smi); | 4720 __ JumpIfNotSmi(object, &object_not_null_or_smi, Label::kNear); |
| 4721 __ Set(eax, Immediate(Smi::FromInt(1))); | 4721 __ Set(eax, Immediate(Smi::FromInt(1))); |
| 4722 __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize); | 4722 __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize); |
| 4723 | 4723 |
| 4724 __ bind(&object_not_null_or_smi); | 4724 __ bind(&object_not_null_or_smi); |
| 4725 // String values is not instance of anything. | 4725 // String values is not instance of anything. |
| 4726 Condition is_string = masm->IsObjectStringType(object, scratch, scratch); | 4726 Condition is_string = masm->IsObjectStringType(object, scratch, scratch); |
| 4727 __ j(NegateCondition(is_string), &slow); | 4727 __ j(NegateCondition(is_string), &slow, Label::kNear); |
| 4728 __ Set(eax, Immediate(Smi::FromInt(1))); | 4728 __ Set(eax, Immediate(Smi::FromInt(1))); |
| 4729 __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize); | 4729 __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize); |
| 4730 | 4730 |
| 4731 // Slow-case: Go through the JavaScript implementation. | 4731 // Slow-case: Go through the JavaScript implementation. |
| 4732 __ bind(&slow); | 4732 __ bind(&slow); |
| 4733 if (!ReturnTrueFalseObject()) { | 4733 if (!ReturnTrueFalseObject()) { |
| 4734 // Tail call the builtin which returns 0 or 1. | 4734 // Tail call the builtin which returns 0 or 1. |
| 4735 if (HasArgsInRegisters()) { | 4735 if (HasArgsInRegisters()) { |
| 4736 // Push arguments below return address. | 4736 // Push arguments below return address. |
| 4737 __ pop(scratch); | 4737 __ pop(scratch); |
| (...skipping 1627 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6365 __ Drop(1); | 6365 __ Drop(1); |
| 6366 __ ret(2 * kPointerSize); | 6366 __ ret(2 * kPointerSize); |
| 6367 } | 6367 } |
| 6368 | 6368 |
| 6369 | 6369 |
| 6370 #undef __ | 6370 #undef __ |
| 6371 | 6371 |
| 6372 } } // namespace v8::internal | 6372 } } // namespace v8::internal |
| 6373 | 6373 |
| 6374 #endif // V8_TARGET_ARCH_IA32 | 6374 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |