OLD | NEW |
1 // Copyright 2006-2009 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2009 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 696 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
707 Result temp = frame_->CallStub(&stub, 1); | 707 Result temp = frame_->CallStub(&stub, 1); |
708 // Convert the result to a condition code. | 708 // Convert the result to a condition code. |
709 __ test(temp.reg(), Operand(temp.reg())); | 709 __ test(temp.reg(), Operand(temp.reg())); |
710 temp.Unuse(); | 710 temp.Unuse(); |
711 dest->Split(not_equal); | 711 dest->Split(not_equal); |
712 } | 712 } |
713 | 713 |
714 | 714 |
715 class FloatingPointHelper : public AllStatic { | 715 class FloatingPointHelper : public AllStatic { |
716 public: | 716 public: |
| 717 // Code pattern for loading a floating point value. Input value must |
| 718 // be either a smi or a heap number object (fp value). Requirements: |
| 719 // operand on TOS+1. Returns operand as floating point number on FPU |
| 720 // stack. |
| 721 static void LoadFloatOperand(MacroAssembler* masm, Register scratch); |
717 // Code pattern for loading floating point values. Input values must | 722 // Code pattern for loading floating point values. Input values must |
718 // be either smi or heap number objects (fp values). Requirements: | 723 // be either smi or heap number objects (fp values). Requirements: |
719 // operand_1 on TOS+1 , operand_2 on TOS+2; Returns operands as | 724 // operand_1 on TOS+1 , operand_2 on TOS+2; Returns operands as |
720 // floating point numbers on FPU stack. | 725 // floating point numbers on FPU stack. |
721 static void LoadFloatOperands(MacroAssembler* masm, Register scratch); | 726 static void LoadFloatOperands(MacroAssembler* masm, Register scratch); |
722 // Test if operands are smi or number objects (fp). Requirements: | 727 // Test if operands are smi or number objects (fp). Requirements: |
723 // operand_1 in eax, operand_2 in edx; falls through on float | 728 // operand_1 in eax, operand_2 in edx; falls through on float |
724 // operands, jumps to the non_float label otherwise. | 729 // operands, jumps to the non_float label otherwise. |
725 static void CheckFloatOperands(MacroAssembler* masm, | 730 static void CheckFloatOperands(MacroAssembler* masm, |
726 Label* non_float, | 731 Label* non_float, |
727 Register scratch); | 732 Register scratch); |
728 // Allocate a heap number in new space with undefined value. | 733 // Allocate a heap number in new space with undefined value. |
729 // Returns tagged pointer in eax, or jumps to need_gc if new space is full. | 734 // Returns tagged pointer in eax, or jumps to need_gc if new space is full. |
730 static void AllocateHeapNumber(MacroAssembler* masm, | 735 static void AllocateHeapNumber(MacroAssembler* masm, |
731 Label* need_gc, | 736 Label* need_gc, |
732 Register scratch1, | 737 Register scratch1, |
733 Register scratch2); | 738 Register scratch2, |
| 739 Register result); |
734 }; | 740 }; |
735 | 741 |
736 | 742 |
737 // Flag that indicates whether or not the code that handles smi arguments | 743 // Flag that indicates whether or not the code that handles smi arguments |
738 // should be placed in the stub, inlined, or omitted entirely. | 744 // should be placed in the stub, inlined, or omitted entirely. |
739 enum GenericBinaryFlags { | 745 enum GenericBinaryFlags { |
740 SMI_CODE_IN_STUB, | 746 SMI_CODE_IN_STUB, |
741 SMI_CODE_INLINED | 747 SMI_CODE_INLINED |
742 }; | 748 }; |
743 | 749 |
(...skipping 4192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4936 | 4942 |
4937 void CodeGenerator::GenerateRandomPositiveSmi(ZoneList<Expression*>* args) { | 4943 void CodeGenerator::GenerateRandomPositiveSmi(ZoneList<Expression*>* args) { |
4938 ASSERT(args->length() == 0); | 4944 ASSERT(args->length() == 0); |
4939 frame_->SpillAll(); | 4945 frame_->SpillAll(); |
4940 __ call(FUNCTION_ADDR(V8::RandomPositiveSmi), RelocInfo::RUNTIME_ENTRY); | 4946 __ call(FUNCTION_ADDR(V8::RandomPositiveSmi), RelocInfo::RUNTIME_ENTRY); |
4941 Result result = allocator_->Allocate(eax); | 4947 Result result = allocator_->Allocate(eax); |
4942 frame_->Push(&result); | 4948 frame_->Push(&result); |
4943 } | 4949 } |
4944 | 4950 |
4945 | 4951 |
| 4952 void CodeGenerator::GenerateFastMathOp(MathOp op, ZoneList<Expression*>* args) { |
| 4953 JumpTarget done; |
| 4954 JumpTarget call_runtime; |
| 4955 ASSERT(args->length() == 1); |
| 4956 |
| 4957 // Load number and duplicate it. |
| 4958 Load(args->at(0)); |
| 4959 frame_->Dup(); |
| 4960 |
| 4961 // Get the number into an unaliased register and load it onto the |
| 4962 // floating point stack still leaving one copy on the frame. |
| 4963 Result number = frame_->Pop(); |
| 4964 number.ToRegister(); |
| 4965 frame_->Spill(number.reg()); |
| 4966 FloatingPointHelper::LoadFloatOperand(masm_, number.reg()); |
| 4967 number.Unuse(); |
| 4968 |
| 4969 // Perform the operation on the number. |
| 4970 switch (op) { |
| 4971 case SIN: |
| 4972 __ fsin(); |
| 4973 break; |
| 4974 case COS: |
| 4975 __ fcos(); |
| 4976 break; |
| 4977 } |
| 4978 |
| 4979 // Go slow case if argument to operation is out of range. |
| 4980 __ fnstsw_ax(); |
| 4981 __ sahf(); |
| 4982 call_runtime.Branch(parity_even, not_taken); |
| 4983 |
| 4984 // Allocate heap number for result if possible. |
| 4985 Result scratch1 = allocator()->Allocate(); |
| 4986 Result scratch2 = allocator()->Allocate(); |
| 4987 Result heap_number = allocator()->Allocate(); |
| 4988 FloatingPointHelper::AllocateHeapNumber(masm_, |
| 4989 call_runtime.entry_label(), |
| 4990 scratch1.reg(), |
| 4991 scratch2.reg(), |
| 4992 heap_number.reg()); |
| 4993 scratch1.Unuse(); |
| 4994 scratch2.Unuse(); |
| 4995 |
| 4996 // Store the result in the allocated heap number. |
| 4997 __ fstp_d(FieldOperand(heap_number.reg(), HeapNumber::kValueOffset)); |
| 4998 // Pop the extra copy of the argument. |
| 4999 frame_->Pop(); |
| 5000 // Push the result on the frame. |
| 5001 frame_->Push(&heap_number); |
| 5002 heap_number.Unuse(); |
| 5003 done.Jump(); |
| 5004 |
| 5005 call_runtime.Bind(); |
| 5006 // Free ST(0) which was not popped before calling into the runtime. |
| 5007 __ ffree(0); |
| 5008 Result answer; |
| 5009 switch (op) { |
| 5010 case SIN: |
| 5011 answer = frame_->CallRuntime(Runtime::kMath_sin, 1); |
| 5012 break; |
| 5013 case COS: |
| 5014 answer = frame_->CallRuntime(Runtime::kMath_cos, 1); |
| 5015 break; |
| 5016 } |
| 5017 frame_->Push(&answer); |
| 5018 done.Bind(); |
| 5019 } |
| 5020 |
| 5021 |
4946 void CodeGenerator::VisitCallRuntime(CallRuntime* node) { | 5022 void CodeGenerator::VisitCallRuntime(CallRuntime* node) { |
4947 if (CheckForInlineRuntimeCall(node)) { | 5023 if (CheckForInlineRuntimeCall(node)) { |
4948 return; | 5024 return; |
4949 } | 5025 } |
4950 | 5026 |
4951 ZoneList<Expression*>* args = node->arguments(); | 5027 ZoneList<Expression*>* args = node->arguments(); |
4952 Comment cmnt(masm_, "[ CallRuntime"); | 5028 Comment cmnt(masm_, "[ CallRuntime"); |
4953 Runtime::Function* function = node->function(); | 5029 Runtime::Function* function = node->function(); |
4954 | 5030 |
4955 if (function == NULL) { | 5031 if (function == NULL) { |
(...skipping 1483 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6439 case OVERWRITE_RIGHT: | 6515 case OVERWRITE_RIGHT: |
6440 // If the argument in eax is already an object, we skip the | 6516 // If the argument in eax is already an object, we skip the |
6441 // allocation of a heap number. | 6517 // allocation of a heap number. |
6442 __ test(eax, Immediate(kSmiTagMask)); | 6518 __ test(eax, Immediate(kSmiTagMask)); |
6443 __ j(not_zero, &skip_allocation, not_taken); | 6519 __ j(not_zero, &skip_allocation, not_taken); |
6444 // Fall through! | 6520 // Fall through! |
6445 case NO_OVERWRITE: | 6521 case NO_OVERWRITE: |
6446 FloatingPointHelper::AllocateHeapNumber(masm, | 6522 FloatingPointHelper::AllocateHeapNumber(masm, |
6447 &call_runtime, | 6523 &call_runtime, |
6448 ecx, | 6524 ecx, |
6449 edx); | 6525 edx, |
| 6526 eax); |
6450 __ bind(&skip_allocation); | 6527 __ bind(&skip_allocation); |
6451 break; | 6528 break; |
6452 default: UNREACHABLE(); | 6529 default: UNREACHABLE(); |
6453 } | 6530 } |
6454 FloatingPointHelper::LoadFloatOperands(masm, ecx); | 6531 FloatingPointHelper::LoadFloatOperands(masm, ecx); |
6455 | 6532 |
6456 switch (op_) { | 6533 switch (op_) { |
6457 case Token::ADD: __ faddp(1); break; | 6534 case Token::ADD: __ faddp(1); break; |
6458 case Token::SUB: __ fsubp(1); break; | 6535 case Token::SUB: __ fsubp(1); break; |
6459 case Token::MUL: __ fmulp(1); break; | 6536 case Token::MUL: __ fmulp(1); break; |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6547 case OVERWRITE_RIGHT: | 6624 case OVERWRITE_RIGHT: |
6548 // If the operand was an object, we skip the | 6625 // If the operand was an object, we skip the |
6549 // allocation of a heap number. | 6626 // allocation of a heap number. |
6550 __ mov(eax, Operand(esp, mode_ == OVERWRITE_RIGHT ? | 6627 __ mov(eax, Operand(esp, mode_ == OVERWRITE_RIGHT ? |
6551 1 * kPointerSize : 2 * kPointerSize)); | 6628 1 * kPointerSize : 2 * kPointerSize)); |
6552 __ test(eax, Immediate(kSmiTagMask)); | 6629 __ test(eax, Immediate(kSmiTagMask)); |
6553 __ j(not_zero, &skip_allocation, not_taken); | 6630 __ j(not_zero, &skip_allocation, not_taken); |
6554 // Fall through! | 6631 // Fall through! |
6555 case NO_OVERWRITE: | 6632 case NO_OVERWRITE: |
6556 FloatingPointHelper::AllocateHeapNumber(masm, &call_runtime, | 6633 FloatingPointHelper::AllocateHeapNumber(masm, &call_runtime, |
6557 ecx, edx); | 6634 ecx, edx, eax); |
6558 __ bind(&skip_allocation); | 6635 __ bind(&skip_allocation); |
6559 break; | 6636 break; |
6560 default: UNREACHABLE(); | 6637 default: UNREACHABLE(); |
6561 } | 6638 } |
6562 // Store the result in the HeapNumber and return. | 6639 // Store the result in the HeapNumber and return. |
6563 __ mov(Operand(esp, 1 * kPointerSize), ebx); | 6640 __ mov(Operand(esp, 1 * kPointerSize), ebx); |
6564 __ fild_s(Operand(esp, 1 * kPointerSize)); | 6641 __ fild_s(Operand(esp, 1 * kPointerSize)); |
6565 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset)); | 6642 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset)); |
6566 __ ret(2 * kPointerSize); | 6643 __ ret(2 * kPointerSize); |
6567 } | 6644 } |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6632 break; | 6709 break; |
6633 default: | 6710 default: |
6634 UNREACHABLE(); | 6711 UNREACHABLE(); |
6635 } | 6712 } |
6636 } | 6713 } |
6637 | 6714 |
6638 | 6715 |
6639 void FloatingPointHelper::AllocateHeapNumber(MacroAssembler* masm, | 6716 void FloatingPointHelper::AllocateHeapNumber(MacroAssembler* masm, |
6640 Label* need_gc, | 6717 Label* need_gc, |
6641 Register scratch1, | 6718 Register scratch1, |
6642 Register scratch2) { | 6719 Register scratch2, |
| 6720 Register result) { |
6643 ExternalReference allocation_top = | 6721 ExternalReference allocation_top = |
6644 ExternalReference::new_space_allocation_top_address(); | 6722 ExternalReference::new_space_allocation_top_address(); |
6645 ExternalReference allocation_limit = | 6723 ExternalReference allocation_limit = |
6646 ExternalReference::new_space_allocation_limit_address(); | 6724 ExternalReference::new_space_allocation_limit_address(); |
6647 __ mov(Operand(scratch1), Immediate(allocation_top)); | 6725 __ mov(Operand(scratch1), Immediate(allocation_top)); |
6648 __ mov(eax, Operand(scratch1, 0)); | 6726 __ mov(result, Operand(scratch1, 0)); |
6649 __ lea(scratch2, Operand(eax, HeapNumber::kSize)); // scratch2: new top | 6727 __ lea(scratch2, Operand(result, HeapNumber::kSize)); // scratch2: new top |
6650 __ cmp(scratch2, Operand::StaticVariable(allocation_limit)); | 6728 __ cmp(scratch2, Operand::StaticVariable(allocation_limit)); |
6651 __ j(above, need_gc, not_taken); | 6729 __ j(above, need_gc, not_taken); |
6652 | 6730 |
6653 __ mov(Operand(scratch1, 0), scratch2); // store new top | 6731 __ mov(Operand(scratch1, 0), scratch2); // store new top |
6654 __ mov(Operand(eax, HeapObject::kMapOffset), | 6732 __ mov(Operand(result, HeapObject::kMapOffset), |
6655 Immediate(Factory::heap_number_map())); | 6733 Immediate(Factory::heap_number_map())); |
6656 // Tag old top and use as result. | 6734 // Tag old top and use as result. |
6657 __ add(Operand(eax), Immediate(kHeapObjectTag)); | 6735 __ add(Operand(result), Immediate(kHeapObjectTag)); |
| 6736 } |
| 6737 |
| 6738 |
| 6739 void FloatingPointHelper::LoadFloatOperand(MacroAssembler* masm, |
| 6740 Register scratch) { |
| 6741 Label load_smi, done; |
| 6742 |
| 6743 __ test(scratch, Immediate(kSmiTagMask)); |
| 6744 __ j(zero, &load_smi, not_taken); |
| 6745 __ fld_d(FieldOperand(scratch, HeapNumber::kValueOffset)); |
| 6746 __ jmp(&done); |
| 6747 |
| 6748 __ bind(&load_smi); |
| 6749 __ sar(scratch, kSmiTagSize); |
| 6750 __ push(scratch); |
| 6751 __ fild_s(Operand(esp, 0)); |
| 6752 __ pop(scratch); |
| 6753 |
| 6754 __ bind(&done); |
6658 } | 6755 } |
6659 | 6756 |
6660 | 6757 |
6661 void FloatingPointHelper::LoadFloatOperands(MacroAssembler* masm, | 6758 void FloatingPointHelper::LoadFloatOperands(MacroAssembler* masm, |
6662 Register scratch) { | 6759 Register scratch) { |
6663 Label load_smi_1, load_smi_2, done_load_1, done; | 6760 Label load_smi_1, load_smi_2, done_load_1, done; |
6664 __ mov(scratch, Operand(esp, 2 * kPointerSize)); | 6761 __ mov(scratch, Operand(esp, 2 * kPointerSize)); |
6665 __ test(scratch, Immediate(kSmiTagMask)); | 6762 __ test(scratch, Immediate(kSmiTagMask)); |
6666 __ j(zero, &load_smi_1, not_taken); | 6763 __ j(zero, &load_smi_1, not_taken); |
6667 __ fld_d(FieldOperand(scratch, HeapNumber::kValueOffset)); | 6764 __ fld_d(FieldOperand(scratch, HeapNumber::kValueOffset)); |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6756 __ mov(edx, FieldOperand(eax, HeapObject::kMapOffset)); | 6853 __ mov(edx, FieldOperand(eax, HeapObject::kMapOffset)); |
6757 __ cmp(edx, Factory::heap_number_map()); | 6854 __ cmp(edx, Factory::heap_number_map()); |
6758 __ j(not_equal, &slow); | 6855 __ j(not_equal, &slow); |
6759 if (overwrite_) { | 6856 if (overwrite_) { |
6760 __ mov(edx, FieldOperand(eax, HeapNumber::kExponentOffset)); | 6857 __ mov(edx, FieldOperand(eax, HeapNumber::kExponentOffset)); |
6761 __ xor_(edx, HeapNumber::kSignMask); // Flip sign. | 6858 __ xor_(edx, HeapNumber::kSignMask); // Flip sign. |
6762 __ mov(FieldOperand(eax, HeapNumber::kExponentOffset), edx); | 6859 __ mov(FieldOperand(eax, HeapNumber::kExponentOffset), edx); |
6763 } else { | 6860 } else { |
6764 __ mov(edx, Operand(eax)); | 6861 __ mov(edx, Operand(eax)); |
6765 // edx: operand | 6862 // edx: operand |
6766 FloatingPointHelper::AllocateHeapNumber(masm, &undo, ebx, ecx); | 6863 FloatingPointHelper::AllocateHeapNumber(masm, &undo, ebx, ecx, eax); |
6767 // eax: allocated 'empty' number | 6864 // eax: allocated 'empty' number |
6768 __ mov(ecx, FieldOperand(edx, HeapNumber::kExponentOffset)); | 6865 __ mov(ecx, FieldOperand(edx, HeapNumber::kExponentOffset)); |
6769 __ xor_(ecx, HeapNumber::kSignMask); // Flip sign. | 6866 __ xor_(ecx, HeapNumber::kSignMask); // Flip sign. |
6770 __ mov(FieldOperand(eax, HeapNumber::kExponentOffset), ecx); | 6867 __ mov(FieldOperand(eax, HeapNumber::kExponentOffset), ecx); |
6771 __ mov(ecx, FieldOperand(edx, HeapNumber::kMantissaOffset)); | 6868 __ mov(ecx, FieldOperand(edx, HeapNumber::kMantissaOffset)); |
6772 __ mov(FieldOperand(eax, HeapNumber::kMantissaOffset), ecx); | 6869 __ mov(FieldOperand(eax, HeapNumber::kMantissaOffset), ecx); |
6773 } | 6870 } |
6774 | 6871 |
6775 __ bind(&done); | 6872 __ bind(&done); |
6776 | 6873 |
(...skipping 724 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7501 | 7598 |
7502 // Slow-case: Go through the JavaScript implementation. | 7599 // Slow-case: Go through the JavaScript implementation. |
7503 __ bind(&slow); | 7600 __ bind(&slow); |
7504 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); | 7601 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); |
7505 } | 7602 } |
7506 | 7603 |
7507 | 7604 |
7508 #undef __ | 7605 #undef __ |
7509 | 7606 |
7510 } } // namespace v8::internal | 7607 } } // namespace v8::internal |
OLD | NEW |