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

Side by Side Diff: src/ia32/codegen-ia32.cc

Issue 125121: Optimize Math.sin and Math.cos by avoiding runtime calls. (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 11 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/ia32/codegen-ia32.h ('k') | src/ia32/codegen-ia32-inl.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/ia32/codegen-ia32.h ('k') | src/ia32/codegen-ia32-inl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698