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 |