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

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

Issue 196139: X64: Convert smis to holding 32 bits of payload. (Closed)
Patch Set: Addressed review comments. Forwarded to head. Created 11 years, 2 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
« no previous file with comments | « src/x64/builtins-x64.cc ('k') | src/x64/ic-x64.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2009 the V8 project authors. All rights reserved. 1 // Copyright 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 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
47 for (int i = 0; i < RegisterAllocator::kNumRegisters; i++) { 47 for (int i = 0; i < RegisterAllocator::kNumRegisters; i++) {
48 int action = registers_[i]; 48 int action = registers_[i];
49 if (action == kPush) { 49 if (action == kPush) {
50 __ push(RegisterAllocator::ToRegister(i)); 50 __ push(RegisterAllocator::ToRegister(i));
51 } else if (action != kIgnore && (action & kSyncedFlag) == 0) { 51 } else if (action != kIgnore && (action & kSyncedFlag) == 0) {
52 __ movq(Operand(rbp, action), RegisterAllocator::ToRegister(i)); 52 __ movq(Operand(rbp, action), RegisterAllocator::ToRegister(i));
53 } 53 }
54 } 54 }
55 } 55 }
56 56
57
57 void DeferredCode::RestoreRegisters() { 58 void DeferredCode::RestoreRegisters() {
58 // Restore registers in reverse order due to the stack. 59 // Restore registers in reverse order due to the stack.
59 for (int i = RegisterAllocator::kNumRegisters - 1; i >= 0; i--) { 60 for (int i = RegisterAllocator::kNumRegisters - 1; i >= 0; i--) {
60 int action = registers_[i]; 61 int action = registers_[i];
61 if (action == kPush) { 62 if (action == kPush) {
62 __ pop(RegisterAllocator::ToRegister(i)); 63 __ pop(RegisterAllocator::ToRegister(i));
63 } else if (action != kIgnore) { 64 } else if (action != kIgnore) {
64 action &= ~kSyncedFlag; 65 action &= ~kSyncedFlag;
65 __ movq(RegisterAllocator::ToRegister(i), Operand(rbp, action)); 66 __ movq(RegisterAllocator::ToRegister(i), Operand(rbp, action));
66 } 67 }
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after
230 // object. 231 // object.
231 // Returns operands as 32-bit sign extended integers in a general purpose 232 // Returns operands as 32-bit sign extended integers in a general purpose
232 // registers. 233 // registers.
233 static void LoadInt32Operand(MacroAssembler* masm, 234 static void LoadInt32Operand(MacroAssembler* masm,
234 const Operand& src, 235 const Operand& src,
235 Register dst); 236 Register dst);
236 237
237 // Test if operands are smi or number objects (fp). Requirements: 238 // Test if operands are smi or number objects (fp). Requirements:
238 // operand_1 in rax, operand_2 in rdx; falls through on float or smi 239 // operand_1 in rax, operand_2 in rdx; falls through on float or smi
239 // operands, jumps to the non_float label otherwise. 240 // operands, jumps to the non_float label otherwise.
240 static void CheckFloatOperands(MacroAssembler* masm, 241 static void CheckNumberOperands(MacroAssembler* masm,
241 Label* non_float); 242 Label* non_float);
242 243
243 // Allocate a heap number in new space with undefined value. 244 // Allocate a heap number in new space with undefined value.
244 // Returns tagged pointer in result, or jumps to need_gc if new space is full. 245 // Returns tagged pointer in result, or jumps to need_gc if new space is full.
245 static void AllocateHeapNumber(MacroAssembler* masm, 246 static void AllocateHeapNumber(MacroAssembler* masm,
246 Label* need_gc, 247 Label* need_gc,
247 Register scratch, 248 Register scratch,
248 Register result); 249 Register result);
249 }; 250 };
250 251
251 252
(...skipping 19 matching lines...) Expand all
271 272
272 void CodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { 273 void CodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
273 // Call the runtime to declare the globals. The inevitable call 274 // Call the runtime to declare the globals. The inevitable call
274 // will sync frame elements to memory anyway, so we do it eagerly to 275 // will sync frame elements to memory anyway, so we do it eagerly to
275 // allow us to push the arguments directly into place. 276 // allow us to push the arguments directly into place.
276 frame_->SyncRange(0, frame_->element_count() - 1); 277 frame_->SyncRange(0, frame_->element_count() - 1);
277 278
278 __ movq(kScratchRegister, pairs, RelocInfo::EMBEDDED_OBJECT); 279 __ movq(kScratchRegister, pairs, RelocInfo::EMBEDDED_OBJECT);
279 frame_->EmitPush(kScratchRegister); 280 frame_->EmitPush(kScratchRegister);
280 frame_->EmitPush(rsi); // The context is the second argument. 281 frame_->EmitPush(rsi); // The context is the second argument.
281 frame_->EmitPush(Immediate(Smi::FromInt(is_eval() ? 1 : 0))); 282 frame_->EmitPush(Smi::FromInt(is_eval() ? 1 : 0));
282 Result ignored = frame_->CallRuntime(Runtime::kDeclareGlobals, 3); 283 Result ignored = frame_->CallRuntime(Runtime::kDeclareGlobals, 3);
283 // Return value is ignored. 284 // Return value is ignored.
284 } 285 }
285 286
286 287
287 void CodeGenerator::GenCode(FunctionLiteral* function) { 288 void CodeGenerator::GenCode(FunctionLiteral* function) {
288 // Record the position for debugging purposes. 289 // Record the position for debugging purposes.
289 CodeForFunctionPosition(function); 290 CodeForFunctionPosition(function);
290 ZoneList<Statement*>* body = function->body(); 291 ZoneList<Statement*>* body = function->body();
291 292
(...skipping 468 matching lines...) Expand 10 before | Expand all | Expand 10 after
760 __ movq(rdi, Operand(rsp, 2 * kPointerSize)); 761 __ movq(rdi, Operand(rsp, 2 * kPointerSize));
761 Condition is_smi = masm_->CheckSmi(rdi); 762 Condition is_smi = masm_->CheckSmi(rdi);
762 build_args.Branch(is_smi); 763 build_args.Branch(is_smi);
763 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx); 764 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx);
764 build_args.Branch(not_equal); 765 build_args.Branch(not_equal);
765 766
766 // Copy the arguments to this function possibly from the 767 // Copy the arguments to this function possibly from the
767 // adaptor frame below it. 768 // adaptor frame below it.
768 Label invoke, adapted; 769 Label invoke, adapted;
769 __ movq(rdx, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); 770 __ movq(rdx, Operand(rbp, StandardFrameConstants::kCallerFPOffset));
770 __ movq(rcx, Operand(rdx, StandardFrameConstants::kContextOffset)); 771 __ SmiCompare(Operand(rdx, StandardFrameConstants::kContextOffset),
771 __ cmpq(rcx, Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); 772 Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
772 __ j(equal, &adapted); 773 __ j(equal, &adapted);
773 774
774 // No arguments adaptor frame. Copy fixed number of arguments. 775 // No arguments adaptor frame. Copy fixed number of arguments.
775 __ movq(rax, Immediate(scope_->num_parameters())); 776 __ movq(rax, Immediate(scope_->num_parameters()));
776 for (int i = 0; i < scope_->num_parameters(); i++) { 777 for (int i = 0; i < scope_->num_parameters(); i++) {
777 __ push(frame_->ParameterAt(i)); 778 __ push(frame_->ParameterAt(i));
778 } 779 }
779 __ jmp(&invoke); 780 __ jmp(&invoke);
780 781
781 // Arguments adaptor frame present. Copy arguments from there, but 782 // Arguments adaptor frame present. Copy arguments from there, but
782 // avoid copying too many arguments to avoid stack overflows. 783 // avoid copying too many arguments to avoid stack overflows.
783 __ bind(&adapted); 784 __ bind(&adapted);
784 static const uint32_t kArgumentsLimit = 1 * KB; 785 static const uint32_t kArgumentsLimit = 1 * KB;
785 __ movq(rax, Operand(rdx, ArgumentsAdaptorFrameConstants::kLengthOffset)); 786 __ movq(rax, Operand(rdx, ArgumentsAdaptorFrameConstants::kLengthOffset));
786 __ SmiToInteger32(rax, rax); 787 __ SmiToInteger32(rax, rax);
787 __ movq(rcx, rax); 788 __ movq(rcx, rax);
788 __ cmpq(rax, Immediate(kArgumentsLimit)); 789 __ cmpq(rax, Immediate(kArgumentsLimit));
789 build_args.Branch(above); 790 build_args.Branch(above);
790 791
791 // Loop through the arguments pushing them onto the execution 792 // Loop through the arguments pushing them onto the execution
792 // stack. We don't inform the virtual frame of the push, so we don't 793 // stack. We don't inform the virtual frame of the push, so we don't
793 // have to worry about getting rid of the elements from the virtual 794 // have to worry about getting rid of the elements from the virtual
794 // frame. 795 // frame.
795 Label loop; 796 Label loop;
796 __ bind(&loop);
797 __ testl(rcx, rcx); 797 __ testl(rcx, rcx);
798 __ j(zero, &invoke); 798 __ j(zero, &invoke);
799 __ bind(&loop);
799 __ push(Operand(rdx, rcx, times_pointer_size, 1 * kPointerSize)); 800 __ push(Operand(rdx, rcx, times_pointer_size, 1 * kPointerSize));
800 __ decl(rcx); 801 __ decl(rcx);
801 __ jmp(&loop); 802 __ j(not_zero, &loop);
802 803
803 // Invoke the function. The virtual frame knows about the receiver 804 // Invoke the function. The virtual frame knows about the receiver
804 // so make sure to forget that explicitly. 805 // so make sure to forget that explicitly.
805 __ bind(&invoke); 806 __ bind(&invoke);
806 ParameterCount actual(rax); 807 ParameterCount actual(rax);
807 __ InvokeFunction(rdi, actual, CALL_FUNCTION); 808 __ InvokeFunction(rdi, actual, CALL_FUNCTION);
808 frame_->Forget(1); 809 frame_->Forget(1);
809 Result result = allocator()->Allocate(rax); 810 Result result = allocator()->Allocate(rax);
810 frame_->SetElementAt(0, &result); 811 frame_->SetElementAt(0, &result);
811 done.Jump(); 812 done.Jump();
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
926 ASSERT(var->is_dynamic()); 927 ASSERT(var->is_dynamic());
927 // For now, just do a runtime call. Sync the virtual frame eagerly 928 // For now, just do a runtime call. Sync the virtual frame eagerly
928 // so we can simply push the arguments into place. 929 // so we can simply push the arguments into place.
929 frame_->SyncRange(0, frame_->element_count() - 1); 930 frame_->SyncRange(0, frame_->element_count() - 1);
930 frame_->EmitPush(rsi); 931 frame_->EmitPush(rsi);
931 __ movq(kScratchRegister, var->name(), RelocInfo::EMBEDDED_OBJECT); 932 __ movq(kScratchRegister, var->name(), RelocInfo::EMBEDDED_OBJECT);
932 frame_->EmitPush(kScratchRegister); 933 frame_->EmitPush(kScratchRegister);
933 // Declaration nodes are always introduced in one of two modes. 934 // Declaration nodes are always introduced in one of two modes.
934 ASSERT(node->mode() == Variable::VAR || node->mode() == Variable::CONST); 935 ASSERT(node->mode() == Variable::VAR || node->mode() == Variable::CONST);
935 PropertyAttributes attr = node->mode() == Variable::VAR ? NONE : READ_ONLY; 936 PropertyAttributes attr = node->mode() == Variable::VAR ? NONE : READ_ONLY;
936 frame_->EmitPush(Immediate(Smi::FromInt(attr))); 937 frame_->EmitPush(Smi::FromInt(attr));
937 // Push initial value, if any. 938 // Push initial value, if any.
938 // Note: For variables we must not push an initial value (such as 939 // Note: For variables we must not push an initial value (such as
939 // 'undefined') because we may have a (legal) redeclaration and we 940 // 'undefined') because we may have a (legal) redeclaration and we
940 // must not destroy the current value. 941 // must not destroy the current value.
941 if (node->mode() == Variable::CONST) { 942 if (node->mode() == Variable::CONST) {
942 frame_->EmitPush(Heap::kTheHoleValueRootIndex); 943 frame_->EmitPush(Heap::kTheHoleValueRootIndex);
943 } else if (node->fun() != NULL) { 944 } else if (node->fun() != NULL) {
944 Load(node->fun()); 945 Load(node->fun());
945 } else { 946 } else {
946 frame_->EmitPush(Immediate(Smi::FromInt(0))); // no initial value! 947 frame_->EmitPush(Smi::FromInt(0)); // no initial value!
947 } 948 }
948 Result ignored = frame_->CallRuntime(Runtime::kDeclareContextSlot, 4); 949 Result ignored = frame_->CallRuntime(Runtime::kDeclareContextSlot, 4);
949 // Ignore the return value (declarations are statements). 950 // Ignore the return value (declarations are statements).
950 return; 951 return;
951 } 952 }
952 953
953 ASSERT(!var->is_global()); 954 ASSERT(!var->is_global());
954 955
955 // If we have a function or a constant, we need to initialize the variable. 956 // If we have a function or a constant, we need to initialize the variable.
956 Expression* val = NULL; 957 Expression* val = NULL;
(...skipping 736 matching lines...) Expand 10 before | Expand all | Expand 10 after
1693 // Get the bridge array held in the enumeration index field. 1694 // Get the bridge array held in the enumeration index field.
1694 __ movq(rcx, FieldOperand(rcx, DescriptorArray::kEnumerationIndexOffset)); 1695 __ movq(rcx, FieldOperand(rcx, DescriptorArray::kEnumerationIndexOffset));
1695 // Get the cache from the bridge array. 1696 // Get the cache from the bridge array.
1696 __ movq(rdx, FieldOperand(rcx, DescriptorArray::kEnumCacheBridgeCacheOffset)); 1697 __ movq(rdx, FieldOperand(rcx, DescriptorArray::kEnumCacheBridgeCacheOffset));
1697 1698
1698 frame_->EmitPush(rax); // <- slot 3 1699 frame_->EmitPush(rax); // <- slot 3
1699 frame_->EmitPush(rdx); // <- slot 2 1700 frame_->EmitPush(rdx); // <- slot 2
1700 __ movl(rax, FieldOperand(rdx, FixedArray::kLengthOffset)); 1701 __ movl(rax, FieldOperand(rdx, FixedArray::kLengthOffset));
1701 __ Integer32ToSmi(rax, rax); 1702 __ Integer32ToSmi(rax, rax);
1702 frame_->EmitPush(rax); // <- slot 1 1703 frame_->EmitPush(rax); // <- slot 1
1703 frame_->EmitPush(Immediate(Smi::FromInt(0))); // <- slot 0 1704 frame_->EmitPush(Smi::FromInt(0)); // <- slot 0
1704 entry.Jump(); 1705 entry.Jump();
1705 1706
1706 fixed_array.Bind(); 1707 fixed_array.Bind();
1707 // rax: fixed array (result from call to Runtime::kGetPropertyNamesFast) 1708 // rax: fixed array (result from call to Runtime::kGetPropertyNamesFast)
1708 frame_->EmitPush(Immediate(Smi::FromInt(0))); // <- slot 3 1709 frame_->EmitPush(Smi::FromInt(0)); // <- slot 3
1709 frame_->EmitPush(rax); // <- slot 2 1710 frame_->EmitPush(rax); // <- slot 2
1710 1711
1711 // Push the length of the array and the initial index onto the stack. 1712 // Push the length of the array and the initial index onto the stack.
1712 __ movl(rax, FieldOperand(rax, FixedArray::kLengthOffset)); 1713 __ movl(rax, FieldOperand(rax, FixedArray::kLengthOffset));
1713 __ Integer32ToSmi(rax, rax); 1714 __ Integer32ToSmi(rax, rax);
1714 frame_->EmitPush(rax); // <- slot 1 1715 frame_->EmitPush(rax); // <- slot 1
1715 frame_->EmitPush(Immediate(Smi::FromInt(0))); // <- slot 0 1716 frame_->EmitPush(Smi::FromInt(0)); // <- slot 0
1716 1717
1717 // Condition. 1718 // Condition.
1718 entry.Bind(); 1719 entry.Bind();
1719 // Grab the current frame's height for the break and continue 1720 // Grab the current frame's height for the break and continue
1720 // targets only after all the state is pushed on the frame. 1721 // targets only after all the state is pushed on the frame.
1721 node->break_target()->set_direction(JumpTarget::FORWARD_ONLY); 1722 node->break_target()->set_direction(JumpTarget::FORWARD_ONLY);
1722 node->continue_target()->set_direction(JumpTarget::FORWARD_ONLY); 1723 node->continue_target()->set_direction(JumpTarget::FORWARD_ONLY);
1723 1724
1724 __ movq(rax, frame_->ElementAt(0)); // load the current count 1725 __ movq(rax, frame_->ElementAt(0)); // load the current count
1725 __ cmpl(rax, frame_->ElementAt(1)); // compare to the array length 1726 __ SmiCompare(frame_->ElementAt(1), rax); // compare to the array length
1726 node->break_target()->Branch(above_equal); 1727 node->break_target()->Branch(below_equal);
1727 1728
1728 // Get the i'th entry of the array. 1729 // Get the i'th entry of the array.
1729 __ movq(rdx, frame_->ElementAt(2)); 1730 __ movq(rdx, frame_->ElementAt(2));
1730 SmiIndex index = masm_->SmiToIndex(rbx, rax, kPointerSizeLog2); 1731 SmiIndex index = masm_->SmiToIndex(rbx, rax, kPointerSizeLog2);
1731 __ movq(rbx, 1732 __ movq(rbx,
1732 FieldOperand(rdx, index.reg, index.scale, FixedArray::kHeaderSize)); 1733 FieldOperand(rdx, index.reg, index.scale, FixedArray::kHeaderSize));
1733 1734
1734 // Get the expected map from the stack or a zero map in the 1735 // Get the expected map from the stack or a zero map in the
1735 // permanent slow case rax: current iteration count rbx: i'th entry 1736 // permanent slow case rax: current iteration count rbx: i'th entry
1736 // of the enum cache 1737 // of the enum cache
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
1789 1790
1790 // Body. 1791 // Body.
1791 CheckStack(); // TODO(1222600): ignore if body contains calls. 1792 CheckStack(); // TODO(1222600): ignore if body contains calls.
1792 VisitAndSpill(node->body()); 1793 VisitAndSpill(node->body());
1793 1794
1794 // Next. Reestablish a spilled frame in case we are coming here via 1795 // Next. Reestablish a spilled frame in case we are coming here via
1795 // a continue in the body. 1796 // a continue in the body.
1796 node->continue_target()->Bind(); 1797 node->continue_target()->Bind();
1797 frame_->SpillAll(); 1798 frame_->SpillAll();
1798 frame_->EmitPop(rax); 1799 frame_->EmitPop(rax);
1799 __ addq(rax, Immediate(Smi::FromInt(1))); 1800 __ SmiAddConstant(rax, rax, Smi::FromInt(1));
1800 frame_->EmitPush(rax); 1801 frame_->EmitPush(rax);
1801 entry.Jump(); 1802 entry.Jump();
1802 1803
1803 // Cleanup. No need to spill because VirtualFrame::Drop is safe for 1804 // Cleanup. No need to spill because VirtualFrame::Drop is safe for
1804 // any frame. 1805 // any frame.
1805 node->break_target()->Bind(); 1806 node->break_target()->Bind();
1806 frame_->Drop(5); 1807 frame_->Drop(5);
1807 1808
1808 // Exit. 1809 // Exit.
1809 exit.Bind(); 1810 exit.Bind();
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after
1962 // break/continue from within the try block. 1963 // break/continue from within the try block.
1963 enum { FALLING, THROWING, JUMPING }; 1964 enum { FALLING, THROWING, JUMPING };
1964 1965
1965 JumpTarget try_block; 1966 JumpTarget try_block;
1966 JumpTarget finally_block; 1967 JumpTarget finally_block;
1967 1968
1968 try_block.Call(); 1969 try_block.Call();
1969 1970
1970 frame_->EmitPush(rax); 1971 frame_->EmitPush(rax);
1971 // In case of thrown exceptions, this is where we continue. 1972 // In case of thrown exceptions, this is where we continue.
1972 __ movq(rcx, Immediate(Smi::FromInt(THROWING))); 1973 __ Move(rcx, Smi::FromInt(THROWING));
1973 finally_block.Jump(); 1974 finally_block.Jump();
1974 1975
1975 // --- Try block --- 1976 // --- Try block ---
1976 try_block.Bind(); 1977 try_block.Bind();
1977 1978
1978 frame_->PushTryHandler(TRY_FINALLY_HANDLER); 1979 frame_->PushTryHandler(TRY_FINALLY_HANDLER);
1979 int handler_height = frame_->height(); 1980 int handler_height = frame_->height();
1980 1981
1981 // Shadow the jump targets for all escapes from the try block, including 1982 // Shadow the jump targets for all escapes from the try block, including
1982 // returns. During shadowing, the original target is hidden as the 1983 // returns. During shadowing, the original target is hidden as the
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
2021 if (has_valid_frame()) { 2022 if (has_valid_frame()) {
2022 // The next handler address is on top of the frame. 2023 // The next handler address is on top of the frame.
2023 ASSERT(StackHandlerConstants::kNextOffset == 0); 2024 ASSERT(StackHandlerConstants::kNextOffset == 0);
2024 __ movq(kScratchRegister, handler_address); 2025 __ movq(kScratchRegister, handler_address);
2025 frame_->EmitPop(Operand(kScratchRegister, 0)); 2026 frame_->EmitPop(Operand(kScratchRegister, 0));
2026 frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1); 2027 frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1);
2027 2028
2028 // Fake a top of stack value (unneeded when FALLING) and set the 2029 // Fake a top of stack value (unneeded when FALLING) and set the
2029 // state in ecx, then jump around the unlink blocks if any. 2030 // state in ecx, then jump around the unlink blocks if any.
2030 frame_->EmitPush(Heap::kUndefinedValueRootIndex); 2031 frame_->EmitPush(Heap::kUndefinedValueRootIndex);
2031 __ movq(rcx, Immediate(Smi::FromInt(FALLING))); 2032 __ Move(rcx, Smi::FromInt(FALLING));
2032 if (nof_unlinks > 0) { 2033 if (nof_unlinks > 0) {
2033 finally_block.Jump(); 2034 finally_block.Jump();
2034 } 2035 }
2035 } 2036 }
2036 2037
2037 // Generate code to unlink and set the state for the (formerly) 2038 // Generate code to unlink and set the state for the (formerly)
2038 // shadowing targets that have been jumped to. 2039 // shadowing targets that have been jumped to.
2039 for (int i = 0; i < shadows.length(); i++) { 2040 for (int i = 0; i < shadows.length(); i++) {
2040 if (shadows[i]->is_linked()) { 2041 if (shadows[i]->is_linked()) {
2041 // If we have come from the shadowed return, the return value is 2042 // If we have come from the shadowed return, the return value is
(...skipping 25 matching lines...) Expand all
2067 frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1); 2068 frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1);
2068 2069
2069 if (i == kReturnShadowIndex) { 2070 if (i == kReturnShadowIndex) {
2070 // If this target shadowed the function return, materialize 2071 // If this target shadowed the function return, materialize
2071 // the return value on the stack. 2072 // the return value on the stack.
2072 frame_->EmitPush(rax); 2073 frame_->EmitPush(rax);
2073 } else { 2074 } else {
2074 // Fake TOS for targets that shadowed breaks and continues. 2075 // Fake TOS for targets that shadowed breaks and continues.
2075 frame_->EmitPush(Heap::kUndefinedValueRootIndex); 2076 frame_->EmitPush(Heap::kUndefinedValueRootIndex);
2076 } 2077 }
2077 __ movq(rcx, Immediate(Smi::FromInt(JUMPING + i))); 2078 __ Move(rcx, Smi::FromInt(JUMPING + i));
2078 if (--nof_unlinks > 0) { 2079 if (--nof_unlinks > 0) {
2079 // If this is not the last unlink block, jump around the next. 2080 // If this is not the last unlink block, jump around the next.
2080 finally_block.Jump(); 2081 finally_block.Jump();
2081 } 2082 }
2082 } 2083 }
2083 } 2084 }
2084 2085
2085 // --- Finally block --- 2086 // --- Finally block ---
2086 finally_block.Bind(); 2087 finally_block.Bind();
2087 2088
(...skipping 10 matching lines...) Expand all
2098 // Restore state and return value or faked TOS. 2099 // Restore state and return value or faked TOS.
2099 frame_->EmitPop(rcx); 2100 frame_->EmitPop(rcx);
2100 frame_->EmitPop(rax); 2101 frame_->EmitPop(rax);
2101 } 2102 }
2102 2103
2103 // Generate code to jump to the right destination for all used 2104 // Generate code to jump to the right destination for all used
2104 // formerly shadowing targets. Deallocate each shadow target. 2105 // formerly shadowing targets. Deallocate each shadow target.
2105 for (int i = 0; i < shadows.length(); i++) { 2106 for (int i = 0; i < shadows.length(); i++) {
2106 if (has_valid_frame() && shadows[i]->is_bound()) { 2107 if (has_valid_frame() && shadows[i]->is_bound()) {
2107 BreakTarget* original = shadows[i]->other_target(); 2108 BreakTarget* original = shadows[i]->other_target();
2108 __ cmpq(rcx, Immediate(Smi::FromInt(JUMPING + i))); 2109 __ SmiCompare(rcx, Smi::FromInt(JUMPING + i));
2109 if (i == kReturnShadowIndex) { 2110 if (i == kReturnShadowIndex) {
2110 // The return value is (already) in rax. 2111 // The return value is (already) in rax.
2111 Result return_value = allocator_->Allocate(rax); 2112 Result return_value = allocator_->Allocate(rax);
2112 ASSERT(return_value.is_valid()); 2113 ASSERT(return_value.is_valid());
2113 if (function_return_is_shadowed_) { 2114 if (function_return_is_shadowed_) {
2114 original->Branch(equal, &return_value); 2115 original->Branch(equal, &return_value);
2115 } else { 2116 } else {
2116 // Branch around the preparation for return which may emit 2117 // Branch around the preparation for return which may emit
2117 // code. 2118 // code.
2118 JumpTarget skip; 2119 JumpTarget skip;
2119 skip.Branch(not_equal); 2120 skip.Branch(not_equal);
2120 frame_->PrepareForReturn(); 2121 frame_->PrepareForReturn();
2121 original->Jump(&return_value); 2122 original->Jump(&return_value);
2122 skip.Bind(); 2123 skip.Bind();
2123 } 2124 }
2124 } else { 2125 } else {
2125 original->Branch(equal); 2126 original->Branch(equal);
2126 } 2127 }
2127 } 2128 }
2128 } 2129 }
2129 2130
2130 if (has_valid_frame()) { 2131 if (has_valid_frame()) {
2131 // Check if we need to rethrow the exception. 2132 // Check if we need to rethrow the exception.
2132 JumpTarget exit; 2133 JumpTarget exit;
2133 __ cmpq(rcx, Immediate(Smi::FromInt(THROWING))); 2134 __ SmiCompare(rcx, Smi::FromInt(THROWING));
2134 exit.Branch(not_equal); 2135 exit.Branch(not_equal);
2135 2136
2136 // Rethrow exception. 2137 // Rethrow exception.
2137 frame_->EmitPush(rax); // undo pop from above 2138 frame_->EmitPush(rax); // undo pop from above
2138 frame_->CallRuntime(Runtime::kReThrow, 1); 2139 frame_->CallRuntime(Runtime::kReThrow, 1);
2139 2140
2140 // Done. 2141 // Done.
2141 exit.Bind(); 2142 exit.Bind();
2142 } 2143 }
2143 } 2144 }
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after
2271 RegExpLiteral* node_; 2272 RegExpLiteral* node_;
2272 }; 2273 };
2273 2274
2274 2275
2275 void DeferredRegExpLiteral::Generate() { 2276 void DeferredRegExpLiteral::Generate() {
2276 // Since the entry is undefined we call the runtime system to 2277 // Since the entry is undefined we call the runtime system to
2277 // compute the literal. 2278 // compute the literal.
2278 // Literal array (0). 2279 // Literal array (0).
2279 __ push(literals_); 2280 __ push(literals_);
2280 // Literal index (1). 2281 // Literal index (1).
2281 __ push(Immediate(Smi::FromInt(node_->literal_index()))); 2282 __ Push(Smi::FromInt(node_->literal_index()));
2282 // RegExp pattern (2). 2283 // RegExp pattern (2).
2283 __ Push(node_->pattern()); 2284 __ Push(node_->pattern());
2284 // RegExp flags (3). 2285 // RegExp flags (3).
2285 __ Push(node_->flags()); 2286 __ Push(node_->flags());
2286 __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4); 2287 __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4);
2287 if (!boilerplate_.is(rax)) __ movq(boilerplate_, rax); 2288 if (!boilerplate_.is(rax)) __ movq(boilerplate_, rax);
2288 } 2289 }
2289 2290
2290 2291
2291 void CodeGenerator::VisitRegExpLiteral(RegExpLiteral* node) { 2292 void CodeGenerator::VisitRegExpLiteral(RegExpLiteral* node) {
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
2344 ObjectLiteral* node_; 2345 ObjectLiteral* node_;
2345 }; 2346 };
2346 2347
2347 2348
2348 void DeferredObjectLiteral::Generate() { 2349 void DeferredObjectLiteral::Generate() {
2349 // Since the entry is undefined we call the runtime system to 2350 // Since the entry is undefined we call the runtime system to
2350 // compute the literal. 2351 // compute the literal.
2351 // Literal array (0). 2352 // Literal array (0).
2352 __ push(literals_); 2353 __ push(literals_);
2353 // Literal index (1). 2354 // Literal index (1).
2354 __ push(Immediate(Smi::FromInt(node_->literal_index()))); 2355 __ Push(Smi::FromInt(node_->literal_index()));
2355 // Constant properties (2). 2356 // Constant properties (2).
2356 __ Push(node_->constant_properties()); 2357 __ Push(node_->constant_properties());
2357 __ CallRuntime(Runtime::kCreateObjectLiteralBoilerplate, 3); 2358 __ CallRuntime(Runtime::kCreateObjectLiteralBoilerplate, 3);
2358 if (!boilerplate_.is(rax)) __ movq(boilerplate_, rax); 2359 if (!boilerplate_.is(rax)) __ movq(boilerplate_, rax);
2359 } 2360 }
2360 2361
2361 2362
2362 void CodeGenerator::VisitObjectLiteral(ObjectLiteral* node) { 2363 void CodeGenerator::VisitObjectLiteral(ObjectLiteral* node) {
2363 Comment cmnt(masm_, "[ ObjectLiteral"); 2364 Comment cmnt(masm_, "[ ObjectLiteral");
2364 2365
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
2477 ArrayLiteral* node_; 2478 ArrayLiteral* node_;
2478 }; 2479 };
2479 2480
2480 2481
2481 void DeferredArrayLiteral::Generate() { 2482 void DeferredArrayLiteral::Generate() {
2482 // Since the entry is undefined we call the runtime system to 2483 // Since the entry is undefined we call the runtime system to
2483 // compute the literal. 2484 // compute the literal.
2484 // Literal array (0). 2485 // Literal array (0).
2485 __ push(literals_); 2486 __ push(literals_);
2486 // Literal index (1). 2487 // Literal index (1).
2487 __ push(Immediate(Smi::FromInt(node_->literal_index()))); 2488 __ Push(Smi::FromInt(node_->literal_index()));
2488 // Constant properties (2). 2489 // Constant properties (2).
2489 __ Push(node_->literals()); 2490 __ Push(node_->literals());
2490 __ CallRuntime(Runtime::kCreateArrayLiteralBoilerplate, 3); 2491 __ CallRuntime(Runtime::kCreateArrayLiteralBoilerplate, 3);
2491 if (!boilerplate_.is(rax)) __ movq(boilerplate_, rax); 2492 if (!boilerplate_.is(rax)) __ movq(boilerplate_, rax);
2492 } 2493 }
2493 2494
2494 2495
2495 void CodeGenerator::VisitArrayLiteral(ArrayLiteral* node) { 2496 void CodeGenerator::VisitArrayLiteral(ArrayLiteral* node) {
2496 Comment cmnt(masm_, "[ ArrayLiteral"); 2497 Comment cmnt(masm_, "[ ArrayLiteral");
2497 2498
(...skipping 646 matching lines...) Expand 10 before | Expand all | Expand 10 after
3144 private: 3145 private:
3145 Register dst_; 3146 Register dst_;
3146 bool is_increment_; 3147 bool is_increment_;
3147 }; 3148 };
3148 3149
3149 3150
3150 void DeferredPrefixCountOperation::Generate() { 3151 void DeferredPrefixCountOperation::Generate() {
3151 __ push(dst_); 3152 __ push(dst_);
3152 __ InvokeBuiltin(Builtins::TO_NUMBER, CALL_FUNCTION); 3153 __ InvokeBuiltin(Builtins::TO_NUMBER, CALL_FUNCTION);
3153 __ push(rax); 3154 __ push(rax);
3154 __ push(Immediate(Smi::FromInt(1))); 3155 __ Push(Smi::FromInt(1));
3155 if (is_increment_) { 3156 if (is_increment_) {
3156 __ CallRuntime(Runtime::kNumberAdd, 2); 3157 __ CallRuntime(Runtime::kNumberAdd, 2);
3157 } else { 3158 } else {
3158 __ CallRuntime(Runtime::kNumberSub, 2); 3159 __ CallRuntime(Runtime::kNumberSub, 2);
3159 } 3160 }
3160 if (!dst_.is(rax)) __ movq(dst_, rax); 3161 if (!dst_.is(rax)) __ movq(dst_, rax);
3161 } 3162 }
3162 3163
3163 3164
3164 // The value in dst was optimistically incremented or decremented. The 3165 // The value in dst was optimistically incremented or decremented. The
(...skipping 19 matching lines...) Expand all
3184 3185
3185 void DeferredPostfixCountOperation::Generate() { 3186 void DeferredPostfixCountOperation::Generate() {
3186 __ push(dst_); 3187 __ push(dst_);
3187 __ InvokeBuiltin(Builtins::TO_NUMBER, CALL_FUNCTION); 3188 __ InvokeBuiltin(Builtins::TO_NUMBER, CALL_FUNCTION);
3188 3189
3189 // Save the result of ToNumber to use as the old value. 3190 // Save the result of ToNumber to use as the old value.
3190 __ push(rax); 3191 __ push(rax);
3191 3192
3192 // Call the runtime for the addition or subtraction. 3193 // Call the runtime for the addition or subtraction.
3193 __ push(rax); 3194 __ push(rax);
3194 __ push(Immediate(Smi::FromInt(1))); 3195 __ Push(Smi::FromInt(1));
3195 if (is_increment_) { 3196 if (is_increment_) {
3196 __ CallRuntime(Runtime::kNumberAdd, 2); 3197 __ CallRuntime(Runtime::kNumberAdd, 2);
3197 } else { 3198 } else {
3198 __ CallRuntime(Runtime::kNumberSub, 2); 3199 __ CallRuntime(Runtime::kNumberSub, 2);
3199 } 3200 }
3200 if (!dst_.is(rax)) __ movq(dst_, rax); 3201 if (!dst_.is(rax)) __ movq(dst_, rax);
3201 __ pop(old_); 3202 __ pop(old_);
3202 } 3203 }
3203 3204
3204 3205
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
3242 DeferredCode* deferred = NULL; 3243 DeferredCode* deferred = NULL;
3243 if (is_postfix) { 3244 if (is_postfix) {
3244 deferred = new DeferredPostfixCountOperation(new_value.reg(), 3245 deferred = new DeferredPostfixCountOperation(new_value.reg(),
3245 old_value.reg(), 3246 old_value.reg(),
3246 is_increment); 3247 is_increment);
3247 } else { 3248 } else {
3248 deferred = new DeferredPrefixCountOperation(new_value.reg(), 3249 deferred = new DeferredPrefixCountOperation(new_value.reg(),
3249 is_increment); 3250 is_increment);
3250 } 3251 }
3251 3252
3252 __ movq(kScratchRegister, new_value.reg()); 3253 __ JumpIfNotSmi(new_value.reg(), deferred->entry_label());
3253 if (is_increment) { 3254 if (is_increment) {
3254 __ addl(kScratchRegister, Immediate(Smi::FromInt(1))); 3255 __ SmiAddConstant(kScratchRegister,
3256 new_value.reg(),
3257 Smi::FromInt(1),
3258 deferred->entry_label());
3255 } else { 3259 } else {
3256 __ subl(kScratchRegister, Immediate(Smi::FromInt(1))); 3260 __ SmiSubConstant(kScratchRegister,
3261 new_value.reg(),
3262 Smi::FromInt(1),
3263 deferred->entry_label());
3257 } 3264 }
3258 // Smi test.
3259 deferred->Branch(overflow);
3260 __ JumpIfNotSmi(kScratchRegister, deferred->entry_label());
3261 __ movq(new_value.reg(), kScratchRegister); 3265 __ movq(new_value.reg(), kScratchRegister);
3262 deferred->BindExit(); 3266 deferred->BindExit();
3263 3267
3264 // Postfix: store the old value in the allocated slot under the 3268 // Postfix: store the old value in the allocated slot under the
3265 // reference. 3269 // reference.
3266 if (is_postfix) frame_->SetElementAt(target.size(), &old_value); 3270 if (is_postfix) frame_->SetElementAt(target.size(), &old_value);
3267 3271
3268 frame_->Push(&new_value); 3272 frame_->Push(&new_value);
3269 // Non-constant: update the reference. 3273 // Non-constant: update the reference.
3270 if (!is_const) target.SetValue(NOT_CONST_INIT); 3274 if (!is_const) target.SetValue(NOT_CONST_INIT);
(...skipping 356 matching lines...) Expand 10 before | Expand all | Expand 10 after
3627 3631
3628 void CodeGenerator::GenerateIsConstructCall(ZoneList<Expression*>* args) { 3632 void CodeGenerator::GenerateIsConstructCall(ZoneList<Expression*>* args) {
3629 ASSERT(args->length() == 0); 3633 ASSERT(args->length() == 0);
3630 3634
3631 // Get the frame pointer for the calling frame. 3635 // Get the frame pointer for the calling frame.
3632 Result fp = allocator()->Allocate(); 3636 Result fp = allocator()->Allocate();
3633 __ movq(fp.reg(), Operand(rbp, StandardFrameConstants::kCallerFPOffset)); 3637 __ movq(fp.reg(), Operand(rbp, StandardFrameConstants::kCallerFPOffset));
3634 3638
3635 // Skip the arguments adaptor frame if it exists. 3639 // Skip the arguments adaptor frame if it exists.
3636 Label check_frame_marker; 3640 Label check_frame_marker;
3637 __ cmpq(Operand(fp.reg(), StandardFrameConstants::kContextOffset), 3641 __ SmiCompare(Operand(fp.reg(), StandardFrameConstants::kContextOffset),
3638 Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); 3642 Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
3639 __ j(not_equal, &check_frame_marker); 3643 __ j(not_equal, &check_frame_marker);
3640 __ movq(fp.reg(), Operand(fp.reg(), StandardFrameConstants::kCallerFPOffset)); 3644 __ movq(fp.reg(), Operand(fp.reg(), StandardFrameConstants::kCallerFPOffset));
3641 3645
3642 // Check the marker in the calling frame. 3646 // Check the marker in the calling frame.
3643 __ bind(&check_frame_marker); 3647 __ bind(&check_frame_marker);
3644 __ cmpq(Operand(fp.reg(), StandardFrameConstants::kMarkerOffset), 3648 __ SmiCompare(Operand(fp.reg(), StandardFrameConstants::kMarkerOffset),
3645 Immediate(Smi::FromInt(StackFrame::CONSTRUCT))); 3649 Smi::FromInt(StackFrame::CONSTRUCT));
3646 fp.Unuse(); 3650 fp.Unuse();
3647 destination()->Split(equal); 3651 destination()->Split(equal);
3648 } 3652 }
3649 3653
3650 3654
3651 void CodeGenerator::GenerateArgumentsLength(ZoneList<Expression*>* args) { 3655 void CodeGenerator::GenerateArgumentsLength(ZoneList<Expression*>* args) {
3652 ASSERT(args->length() == 0); 3656 ASSERT(args->length() == 0);
3653 // ArgumentsAccessStub takes the parameter count as an input argument 3657 // ArgumentsAccessStub takes the parameter count as an input argument
3654 // in register eax. Create a constant result for it. 3658 // in register eax. Create a constant result for it.
3655 Result count(Handle<Smi>(Smi::FromInt(scope_->num_parameters()))); 3659 Result count(Handle<Smi>(Smi::FromInt(scope_->num_parameters())));
(...skipping 215 matching lines...) Expand 10 before | Expand all | Expand 10 after
3871 __ cmpq(right.reg(), left.reg()); 3875 __ cmpq(right.reg(), left.reg());
3872 right.Unuse(); 3876 right.Unuse();
3873 left.Unuse(); 3877 left.Unuse();
3874 destination()->Split(equal); 3878 destination()->Split(equal);
3875 } 3879 }
3876 3880
3877 3881
3878 void CodeGenerator::GenerateGetFramePointer(ZoneList<Expression*>* args) { 3882 void CodeGenerator::GenerateGetFramePointer(ZoneList<Expression*>* args) {
3879 ASSERT(args->length() == 0); 3883 ASSERT(args->length() == 0);
3880 // RBP value is aligned, so it should be tagged as a smi (without necesarily 3884 // RBP value is aligned, so it should be tagged as a smi (without necesarily
3881 // being padded as a smi). 3885 // being padded as a smi, so it should not be treated as a smi.).
3882 ASSERT(kSmiTag == 0 && kSmiTagSize == 1); 3886 ASSERT(kSmiTag == 0 && kSmiTagSize == 1);
3883 Result rbp_as_smi = allocator_->Allocate(); 3887 Result rbp_as_smi = allocator_->Allocate();
3884 ASSERT(rbp_as_smi.is_valid()); 3888 ASSERT(rbp_as_smi.is_valid());
3885 __ movq(rbp_as_smi.reg(), rbp); 3889 __ movq(rbp_as_smi.reg(), rbp);
3886 frame_->Push(&rbp_as_smi); 3890 frame_->Push(&rbp_as_smi);
3887 } 3891 }
3888 3892
3889 3893
3890 void CodeGenerator::GenerateRandomPositiveSmi(ZoneList<Expression*>* args) { 3894 void CodeGenerator::GenerateRandomPositiveSmi(ZoneList<Expression*>* args) {
3891 ASSERT(args->length() == 0); 3895 ASSERT(args->length() == 0);
(...skipping 363 matching lines...) Expand 10 before | Expand all | Expand 10 after
4255 4259
4256 // 'true' => true. 4260 // 'true' => true.
4257 __ CompareRoot(value.reg(), Heap::kTrueValueRootIndex); 4261 __ CompareRoot(value.reg(), Heap::kTrueValueRootIndex);
4258 dest->true_target()->Branch(equal); 4262 dest->true_target()->Branch(equal);
4259 4263
4260 // 'undefined' => false. 4264 // 'undefined' => false.
4261 __ CompareRoot(value.reg(), Heap::kUndefinedValueRootIndex); 4265 __ CompareRoot(value.reg(), Heap::kUndefinedValueRootIndex);
4262 dest->false_target()->Branch(equal); 4266 dest->false_target()->Branch(equal);
4263 4267
4264 // Smi => false iff zero. 4268 // Smi => false iff zero.
4265 Condition equals = masm_->CheckSmiEqualsConstant(value.reg(), 0); 4269 __ SmiCompare(value.reg(), Smi::FromInt(0));
4266 dest->false_target()->Branch(equals); 4270 dest->false_target()->Branch(equal);
4267 Condition is_smi = masm_->CheckSmi(value.reg()); 4271 Condition is_smi = masm_->CheckSmi(value.reg());
4268 dest->true_target()->Branch(is_smi); 4272 dest->true_target()->Branch(is_smi);
4269 4273
4270 // Call the stub for all other cases. 4274 // Call the stub for all other cases.
4271 frame_->Push(&value); // Undo the Pop() from above. 4275 frame_->Push(&value); // Undo the Pop() from above.
4272 ToBooleanStub stub; 4276 ToBooleanStub stub;
4273 Result temp = frame_->CallStub(&stub, 1); 4277 Result temp = frame_->CallStub(&stub, 1);
4274 // Convert the result to a condition code. 4278 // Convert the result to a condition code.
4275 __ testq(temp.reg(), temp.reg()); 4279 __ testq(temp.reg(), temp.reg());
4276 temp.Unuse(); 4280 temp.Unuse();
(...skipping 661 matching lines...) Expand 10 before | Expand all | Expand 10 after
4938 __ testq(result.reg(), result.reg()); 4942 __ testq(result.reg(), result.reg());
4939 result.Unuse(); 4943 result.Unuse();
4940 dest->true_target()->Branch(cc); 4944 dest->true_target()->Branch(cc);
4941 dest->false_target()->Jump(); 4945 dest->false_target()->Jump();
4942 4946
4943 is_smi.Bind(); 4947 is_smi.Bind();
4944 left_side = Result(left_reg); 4948 left_side = Result(left_reg);
4945 right_side = Result(right_val); 4949 right_side = Result(right_val);
4946 // Test smi equality and comparison by signed int comparison. 4950 // Test smi equality and comparison by signed int comparison.
4947 // Both sides are smis, so we can use an Immediate. 4951 // Both sides are smis, so we can use an Immediate.
4948 __ cmpl(left_side.reg(), Immediate(Smi::cast(*right_side.handle()))); 4952 __ SmiCompare(left_side.reg(), Smi::cast(*right_side.handle()));
4949 left_side.Unuse(); 4953 left_side.Unuse();
4950 right_side.Unuse(); 4954 right_side.Unuse();
4951 dest->Split(cc); 4955 dest->Split(cc);
4952 } 4956 }
4953 } else if (cc == equal && 4957 } else if (cc == equal &&
4954 (left_side_constant_null || right_side_constant_null)) { 4958 (left_side_constant_null || right_side_constant_null)) {
4955 // To make null checks efficient, we check if either the left side or 4959 // To make null checks efficient, we check if either the left side or
4956 // the right side is the constant 'null'. 4960 // the right side is the constant 'null'.
4957 // If so, we optimize the code by inlining a null check instead of 4961 // If so, we optimize the code by inlining a null check instead of
4958 // calling the (very) general runtime routine for checking equality. 4962 // calling the (very) general runtime routine for checking equality.
(...skipping 12 matching lines...) Expand all
4971 __ CompareRoot(operand.reg(), Heap::kUndefinedValueRootIndex); 4975 __ CompareRoot(operand.reg(), Heap::kUndefinedValueRootIndex);
4972 dest->true_target()->Branch(equal); 4976 dest->true_target()->Branch(equal);
4973 Condition is_smi = masm_->CheckSmi(operand.reg()); 4977 Condition is_smi = masm_->CheckSmi(operand.reg());
4974 dest->false_target()->Branch(is_smi); 4978 dest->false_target()->Branch(is_smi);
4975 4979
4976 // It can be an undetectable object. 4980 // It can be an undetectable object.
4977 // Use a scratch register in preference to spilling operand.reg(). 4981 // Use a scratch register in preference to spilling operand.reg().
4978 Result temp = allocator()->Allocate(); 4982 Result temp = allocator()->Allocate();
4979 ASSERT(temp.is_valid()); 4983 ASSERT(temp.is_valid());
4980 __ movq(temp.reg(), 4984 __ movq(temp.reg(),
4981 FieldOperand(operand.reg(), HeapObject::kMapOffset)); 4985 FieldOperand(operand.reg(), HeapObject::kMapOffset));
4982 __ testb(FieldOperand(temp.reg(), Map::kBitFieldOffset), 4986 __ testb(FieldOperand(temp.reg(), Map::kBitFieldOffset),
4983 Immediate(1 << Map::kIsUndetectable)); 4987 Immediate(1 << Map::kIsUndetectable));
4984 temp.Unuse(); 4988 temp.Unuse();
4985 operand.Unuse(); 4989 operand.Unuse();
4986 dest->Split(not_zero); 4990 dest->Split(not_zero);
4987 } 4991 }
4988 } else { // Neither side is a constant Smi or null. 4992 } else { // Neither side is a constant Smi or null.
4989 // If either side is a non-smi constant, skip the smi check. 4993 // If either side is a non-smi constant, skip the smi check.
4990 bool known_non_smi = 4994 bool known_non_smi =
4991 (left_side.is_constant() && !left_side.handle()->IsSmi()) || 4995 (left_side.is_constant() && !left_side.handle()->IsSmi()) ||
4992 (right_side.is_constant() && !right_side.handle()->IsSmi()); 4996 (right_side.is_constant() && !right_side.handle()->IsSmi());
4993 left_side.ToRegister(); 4997 left_side.ToRegister();
4994 right_side.ToRegister(); 4998 right_side.ToRegister();
4995 4999
4996 if (known_non_smi) { 5000 if (known_non_smi) {
4997 // When non-smi, call out to the compare stub. 5001 // When non-smi, call out to the compare stub.
4998 CompareStub stub(cc, strict); 5002 CompareStub stub(cc, strict);
4999 Result answer = frame_->CallStub(&stub, &left_side, &right_side); 5003 Result answer = frame_->CallStub(&stub, &left_side, &right_side);
5000 // The result is a Smi, which is negative, zero, or positive. 5004 // The result is a Smi, which is negative, zero, or positive.
5001 __ testl(answer.reg(), answer.reg()); // Both zero and sign flag right. 5005 __ SmiTest(answer.reg()); // Sets both zero and sign flag.
5002 answer.Unuse(); 5006 answer.Unuse();
5003 dest->Split(cc); 5007 dest->Split(cc);
5004 } else { 5008 } else {
5005 // Here we split control flow to the stub call and inlined cases 5009 // Here we split control flow to the stub call and inlined cases
5006 // before finally splitting it to the control destination. We use 5010 // before finally splitting it to the control destination. We use
5007 // a jump target and branching to duplicate the virtual frame at 5011 // a jump target and branching to duplicate the virtual frame at
5008 // the first split. We manually handle the off-frame references 5012 // the first split. We manually handle the off-frame references
5009 // by reconstituting them on the non-fall-through path. 5013 // by reconstituting them on the non-fall-through path.
5010 JumpTarget is_smi; 5014 JumpTarget is_smi;
5011 Register left_reg = left_side.reg(); 5015 Register left_reg = left_side.reg();
5012 Register right_reg = right_side.reg(); 5016 Register right_reg = right_side.reg();
5013 5017
5014 Condition both_smi = masm_->CheckBothSmi(left_reg, right_reg); 5018 Condition both_smi = masm_->CheckBothSmi(left_reg, right_reg);
5015 is_smi.Branch(both_smi); 5019 is_smi.Branch(both_smi);
5016 // When non-smi, call out to the compare stub. 5020 // When non-smi, call out to the compare stub.
5017 CompareStub stub(cc, strict); 5021 CompareStub stub(cc, strict);
5018 Result answer = frame_->CallStub(&stub, &left_side, &right_side); 5022 Result answer = frame_->CallStub(&stub, &left_side, &right_side);
5019 __ testl(answer.reg(), answer.reg()); // Sets both zero and sign flags. 5023 __ SmiTest(answer.reg()); // Sets both zero and sign flags.
5020 answer.Unuse(); 5024 answer.Unuse();
5021 dest->true_target()->Branch(cc); 5025 dest->true_target()->Branch(cc);
5022 dest->false_target()->Jump(); 5026 dest->false_target()->Jump();
5023 5027
5024 is_smi.Bind(); 5028 is_smi.Bind();
5025 left_side = Result(left_reg); 5029 left_side = Result(left_reg);
5026 right_side = Result(right_reg); 5030 right_side = Result(right_reg);
5027 __ cmpl(left_side.reg(), right_side.reg()); 5031 __ SmiCompare(left_side.reg(), right_side.reg());
5028 right_side.Unuse(); 5032 right_side.Unuse();
5029 left_side.Unuse(); 5033 left_side.Unuse();
5030 dest->Split(cc); 5034 dest->Split(cc);
5031 } 5035 }
5032 } 5036 }
5033 } 5037 }
5034 5038
5035 5039
5036 class DeferredInlineBinaryOperation: public DeferredCode { 5040 class DeferredInlineBinaryOperation: public DeferredCode {
5037 public: 5041 public:
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after
5214 masm_->testl(rax, Immediate(-delta_to_patch_site)); 5218 masm_->testl(rax, Immediate(-delta_to_patch_site));
5215 __ IncrementCounter(&Counters::named_load_inline_miss, 1); 5219 __ IncrementCounter(&Counters::named_load_inline_miss, 1);
5216 5220
5217 if (!dst_.is(rax)) __ movq(dst_, rax); 5221 if (!dst_.is(rax)) __ movq(dst_, rax);
5218 __ pop(receiver_); 5222 __ pop(receiver_);
5219 } 5223 }
5220 5224
5221 5225
5222 void DeferredInlineSmiAdd::Generate() { 5226 void DeferredInlineSmiAdd::Generate() {
5223 __ push(dst_); 5227 __ push(dst_);
5224 __ push(Immediate(value_)); 5228 __ Push(value_);
5225 GenericBinaryOpStub igostub(Token::ADD, overwrite_mode_, SMI_CODE_INLINED); 5229 GenericBinaryOpStub igostub(Token::ADD, overwrite_mode_, SMI_CODE_INLINED);
5226 __ CallStub(&igostub); 5230 __ CallStub(&igostub);
5227 if (!dst_.is(rax)) __ movq(dst_, rax); 5231 if (!dst_.is(rax)) __ movq(dst_, rax);
5228 } 5232 }
5229 5233
5230 5234
5231 void DeferredInlineSmiAddReversed::Generate() { 5235 void DeferredInlineSmiAddReversed::Generate() {
5232 __ push(Immediate(value_)); // Note: sign extended. 5236 __ Push(value_);
5233 __ push(dst_); 5237 __ push(dst_);
5234 GenericBinaryOpStub igostub(Token::ADD, overwrite_mode_, SMI_CODE_INLINED); 5238 GenericBinaryOpStub igostub(Token::ADD, overwrite_mode_, SMI_CODE_INLINED);
5235 __ CallStub(&igostub); 5239 __ CallStub(&igostub);
5236 if (!dst_.is(rax)) __ movq(dst_, rax); 5240 if (!dst_.is(rax)) __ movq(dst_, rax);
5237 } 5241 }
5238 5242
5239 5243
5240 void DeferredInlineSmiSub::Generate() { 5244 void DeferredInlineSmiSub::Generate() {
5241 __ push(dst_); 5245 __ push(dst_);
5242 __ push(Immediate(value_)); // Note: sign extended. 5246 __ Push(value_);
5243 GenericBinaryOpStub igostub(Token::SUB, overwrite_mode_, SMI_CODE_INLINED); 5247 GenericBinaryOpStub igostub(Token::SUB, overwrite_mode_, SMI_CODE_INLINED);
5244 __ CallStub(&igostub); 5248 __ CallStub(&igostub);
5245 if (!dst_.is(rax)) __ movq(dst_, rax); 5249 if (!dst_.is(rax)) __ movq(dst_, rax);
5246 } 5250 }
5247 5251
5248 5252
5249 void DeferredInlineSmiOperation::Generate() { 5253 void DeferredInlineSmiOperation::Generate() {
5250 __ push(src_); 5254 __ push(src_);
5251 __ push(Immediate(value_)); // Note: sign extended. 5255 __ Push(value_);
5252 // For mod we don't generate all the Smi code inline. 5256 // For mod we don't generate all the Smi code inline.
5253 GenericBinaryOpStub stub( 5257 GenericBinaryOpStub stub(
5254 op_, 5258 op_,
5255 overwrite_mode_, 5259 overwrite_mode_,
5256 (op_ == Token::MOD) ? SMI_CODE_IN_STUB : SMI_CODE_INLINED); 5260 (op_ == Token::MOD) ? SMI_CODE_IN_STUB : SMI_CODE_INLINED);
5257 __ CallStub(&stub); 5261 __ CallStub(&stub);
5258 if (!dst_.is(rax)) __ movq(dst_, rax); 5262 if (!dst_.is(rax)) __ movq(dst_, rax);
5259 } 5263 }
5260 5264
5261 5265
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
5299 smi_value, 5303 smi_value,
5300 overwrite_mode); 5304 overwrite_mode);
5301 } else { 5305 } else {
5302 deferred = new DeferredInlineSmiAdd(operand->reg(), 5306 deferred = new DeferredInlineSmiAdd(operand->reg(),
5303 smi_value, 5307 smi_value,
5304 overwrite_mode); 5308 overwrite_mode);
5305 } 5309 }
5306 __ JumpIfNotSmi(operand->reg(), deferred->entry_label()); 5310 __ JumpIfNotSmi(operand->reg(), deferred->entry_label());
5307 __ SmiAddConstant(operand->reg(), 5311 __ SmiAddConstant(operand->reg(),
5308 operand->reg(), 5312 operand->reg(),
5309 int_value, 5313 smi_value,
5310 deferred->entry_label()); 5314 deferred->entry_label());
5311 deferred->BindExit(); 5315 deferred->BindExit();
5312 frame_->Push(operand); 5316 frame_->Push(operand);
5313 break; 5317 break;
5314 } 5318 }
5315 5319
5316 case Token::SUB: { 5320 case Token::SUB: {
5317 if (reversed) { 5321 if (reversed) {
5318 Result constant_operand(value); 5322 Result constant_operand(value);
5319 LikelySmiBinaryOperation(op, &constant_operand, operand, 5323 LikelySmiBinaryOperation(op, &constant_operand, operand,
5320 overwrite_mode); 5324 overwrite_mode);
5321 } else { 5325 } else {
5322 operand->ToRegister(); 5326 operand->ToRegister();
5323 frame_->Spill(operand->reg()); 5327 frame_->Spill(operand->reg());
5324 DeferredCode* deferred = new DeferredInlineSmiSub(operand->reg(), 5328 DeferredCode* deferred = new DeferredInlineSmiSub(operand->reg(),
5325 smi_value, 5329 smi_value,
5326 overwrite_mode); 5330 overwrite_mode);
5327 __ JumpIfNotSmi(operand->reg(), deferred->entry_label()); 5331 __ JumpIfNotSmi(operand->reg(), deferred->entry_label());
5328 // A smi currently fits in a 32-bit Immediate. 5332 // A smi currently fits in a 32-bit Immediate.
5329 __ SmiSubConstant(operand->reg(), 5333 __ SmiSubConstant(operand->reg(),
5330 operand->reg(), 5334 operand->reg(),
5331 int_value, 5335 smi_value,
5332 deferred->entry_label()); 5336 deferred->entry_label());
5333 deferred->BindExit(); 5337 deferred->BindExit();
5334 frame_->Push(operand); 5338 frame_->Push(operand);
5335 } 5339 }
5336 break; 5340 break;
5337 } 5341 }
5338 5342
5339 case Token::SAR: 5343 case Token::SAR:
5340 if (reversed) { 5344 if (reversed) {
5341 Result constant_operand(value); 5345 Result constant_operand(value);
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
5375 Result answer = allocator()->Allocate(); 5379 Result answer = allocator()->Allocate();
5376 ASSERT(answer.is_valid()); 5380 ASSERT(answer.is_valid());
5377 DeferredInlineSmiOperation* deferred = 5381 DeferredInlineSmiOperation* deferred =
5378 new DeferredInlineSmiOperation(op, 5382 new DeferredInlineSmiOperation(op,
5379 answer.reg(), 5383 answer.reg(),
5380 operand->reg(), 5384 operand->reg(),
5381 smi_value, 5385 smi_value,
5382 overwrite_mode); 5386 overwrite_mode);
5383 __ JumpIfNotSmi(operand->reg(), deferred->entry_label()); 5387 __ JumpIfNotSmi(operand->reg(), deferred->entry_label());
5384 __ SmiShiftLogicalRightConstant(answer.reg(), 5388 __ SmiShiftLogicalRightConstant(answer.reg(),
5385 operand->reg(), 5389 operand->reg(),
5386 shift_value, 5390 shift_value,
5387 deferred->entry_label()); 5391 deferred->entry_label());
5388 deferred->BindExit(); 5392 deferred->BindExit();
5389 operand->Unuse(); 5393 operand->Unuse();
5390 frame_->Push(&answer); 5394 frame_->Push(&answer);
5391 } 5395 }
5392 break; 5396 break;
5393 5397
5394 case Token::SHL: 5398 case Token::SHL:
5395 if (reversed) { 5399 if (reversed) {
5396 Result constant_operand(value); 5400 Result constant_operand(value);
5397 LikelySmiBinaryOperation(op, &constant_operand, operand, 5401 LikelySmiBinaryOperation(op, &constant_operand, operand,
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
5446 // Swap left and right overwrite modes. 0->0, 1->2, 2->1. 5450 // Swap left and right overwrite modes. 0->0, 1->2, 2->1.
5447 overwrite_mode = static_cast<OverwriteMode>((2 * overwrite_mode) % 3); 5451 overwrite_mode = static_cast<OverwriteMode>((2 * overwrite_mode) % 3);
5448 } 5452 }
5449 DeferredCode* deferred = new DeferredInlineSmiOperation(op, 5453 DeferredCode* deferred = new DeferredInlineSmiOperation(op,
5450 operand->reg(), 5454 operand->reg(),
5451 operand->reg(), 5455 operand->reg(),
5452 smi_value, 5456 smi_value,
5453 overwrite_mode); 5457 overwrite_mode);
5454 __ JumpIfNotSmi(operand->reg(), deferred->entry_label()); 5458 __ JumpIfNotSmi(operand->reg(), deferred->entry_label());
5455 if (op == Token::BIT_AND) { 5459 if (op == Token::BIT_AND) {
5456 __ SmiAndConstant(operand->reg(), operand->reg(), int_value); 5460 __ SmiAndConstant(operand->reg(), operand->reg(), smi_value);
5457 } else if (op == Token::BIT_XOR) { 5461 } else if (op == Token::BIT_XOR) {
5458 if (int_value != 0) { 5462 if (int_value != 0) {
5459 __ SmiXorConstant(operand->reg(), operand->reg(), int_value); 5463 __ SmiXorConstant(operand->reg(), operand->reg(), smi_value);
5460 } 5464 }
5461 } else { 5465 } else {
5462 ASSERT(op == Token::BIT_OR); 5466 ASSERT(op == Token::BIT_OR);
5463 if (int_value != 0) { 5467 if (int_value != 0) {
5464 __ SmiOrConstant(operand->reg(), operand->reg(), int_value); 5468 __ SmiOrConstant(operand->reg(), operand->reg(), smi_value);
5465 } 5469 }
5466 } 5470 }
5467 deferred->BindExit(); 5471 deferred->BindExit();
5468 frame_->Push(operand); 5472 frame_->Push(operand);
5469 break; 5473 break;
5470 } 5474 }
5471 5475
5472 // Generate inline code for mod of powers of 2 and negative powers of 2. 5476 // Generate inline code for mod of powers of 2 and negative powers of 2.
5473 case Token::MOD: 5477 case Token::MOD:
5474 if (!reversed && 5478 if (!reversed &&
5475 int_value != 0 && 5479 int_value != 0 &&
5476 (IsPowerOf2(int_value) || IsPowerOf2(-int_value))) { 5480 (IsPowerOf2(int_value) || IsPowerOf2(-int_value))) {
5477 operand->ToRegister(); 5481 operand->ToRegister();
5478 frame_->Spill(operand->reg()); 5482 frame_->Spill(operand->reg());
5479 DeferredCode* deferred = new DeferredInlineSmiOperation(op, 5483 DeferredCode* deferred =
5480 operand->reg(), 5484 new DeferredInlineSmiOperation(op,
5481 operand->reg(), 5485 operand->reg(),
5482 smi_value, 5486 operand->reg(),
5483 overwrite_mode); 5487 smi_value,
5488 overwrite_mode);
5484 // Check for negative or non-Smi left hand side. 5489 // Check for negative or non-Smi left hand side.
5485 __ JumpIfNotPositiveSmi(operand->reg(), deferred->entry_label()); 5490 __ JumpIfNotPositiveSmi(operand->reg(), deferred->entry_label());
5486 if (int_value < 0) int_value = -int_value; 5491 if (int_value < 0) int_value = -int_value;
5487 if (int_value == 1) { 5492 if (int_value == 1) {
5488 __ movl(operand->reg(), Immediate(Smi::FromInt(0))); 5493 __ Move(operand->reg(), Smi::FromInt(0));
5489 } else { 5494 } else {
5490 __ SmiAndConstant(operand->reg(), operand->reg(), int_value - 1); 5495 __ SmiAndConstant(operand->reg(),
5496 operand->reg(),
5497 Smi::FromInt(int_value - 1));
5491 } 5498 }
5492 deferred->BindExit(); 5499 deferred->BindExit();
5493 frame_->Push(operand); 5500 frame_->Push(operand);
5494 break; // This break only applies if we generated code for MOD. 5501 break; // This break only applies if we generated code for MOD.
5495 } 5502 }
5496 // Fall through if we did not find a power of 2 on the right hand side! 5503 // Fall through if we did not find a power of 2 on the right hand side!
5497 // The next case must be the default. 5504 // The next case must be the default.
5498 5505
5499 default: { 5506 default: {
5500 Result constant_operand(value); 5507 Result constant_operand(value);
(...skipping 577 matching lines...) Expand 10 before | Expand all | Expand 10 after
6078 receiver.reg()); 6085 receiver.reg());
6079 6086
6080 // Check that the value is a smi if it is not a constant. 6087 // Check that the value is a smi if it is not a constant.
6081 // We can skip the write barrier for smis and constants. 6088 // We can skip the write barrier for smis and constants.
6082 if (!value_is_constant) { 6089 if (!value_is_constant) {
6083 __ JumpIfNotSmi(value.reg(), deferred->entry_label()); 6090 __ JumpIfNotSmi(value.reg(), deferred->entry_label());
6084 } 6091 }
6085 6092
6086 // Check that the key is a non-negative smi. 6093 // Check that the key is a non-negative smi.
6087 __ JumpIfNotPositiveSmi(key.reg(), deferred->entry_label()); 6094 __ JumpIfNotPositiveSmi(key.reg(), deferred->entry_label());
6088 // Ensure that the smi is zero-extended. This is not guaranteed.
6089 __ movl(key.reg(), key.reg());
6090 6095
6091 // Check that the receiver is not a smi. 6096 // Check that the receiver is not a smi.
6092 __ JumpIfSmi(receiver.reg(), deferred->entry_label()); 6097 __ JumpIfSmi(receiver.reg(), deferred->entry_label());
6093 6098
6094 // Check that the receiver is a JSArray. 6099 // Check that the receiver is a JSArray.
6095 __ CmpObjectType(receiver.reg(), JS_ARRAY_TYPE, kScratchRegister); 6100 __ CmpObjectType(receiver.reg(), JS_ARRAY_TYPE, kScratchRegister);
6096 deferred->Branch(not_equal); 6101 deferred->Branch(not_equal);
6097 6102
6098 // Check that the key is within bounds. Both the key and the 6103 // Check that the key is within bounds. Both the key and the
6099 // length of the JSArray are smis, so compare only low 32 bits. 6104 // length of the JSArray are smis.
6100 __ cmpl(key.reg(), 6105 __ SmiCompare(FieldOperand(receiver.reg(), JSArray::kLengthOffset),
6101 FieldOperand(receiver.reg(), JSArray::kLengthOffset)); 6106 key.reg());
6102 deferred->Branch(greater_equal); 6107 deferred->Branch(less_equal);
6103 6108
6104 // Get the elements array from the receiver and check that it 6109 // Get the elements array from the receiver and check that it
6105 // is a flat array (not a dictionary). 6110 // is a flat array (not a dictionary).
6106 __ movq(tmp.reg(), 6111 __ movq(tmp.reg(),
6107 FieldOperand(receiver.reg(), JSObject::kElementsOffset)); 6112 FieldOperand(receiver.reg(), JSObject::kElementsOffset));
6108 // Bind the deferred code patch site to be able to locate the 6113 // Bind the deferred code patch site to be able to locate the
6109 // fixed array map comparison. When debugging, we patch this 6114 // fixed array map comparison. When debugging, we patch this
6110 // comparison to always fail so that we will hit the IC call 6115 // comparison to always fail so that we will hit the IC call
6111 // in the deferred code which will allow the debugger to 6116 // in the deferred code which will allow the debugger to
6112 // break for fast case stores. 6117 // break for fast case stores.
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after
6296 return true; 6301 return true;
6297 } 6302 }
6298 6303
6299 6304
6300 // End of CodeGenerator implementation. 6305 // End of CodeGenerator implementation.
6301 6306
6302 void UnarySubStub::Generate(MacroAssembler* masm) { 6307 void UnarySubStub::Generate(MacroAssembler* masm) {
6303 Label slow; 6308 Label slow;
6304 Label done; 6309 Label done;
6305 Label try_float; 6310 Label try_float;
6306 Label special;
6307 // Check whether the value is a smi. 6311 // Check whether the value is a smi.
6308 __ JumpIfNotSmi(rax, &try_float); 6312 __ JumpIfNotSmi(rax, &try_float);
6309 6313
6310 // Enter runtime system if the value of the smi is zero 6314 // Enter runtime system if the value of the smi is zero
6311 // to make sure that we switch between 0 and -0. 6315 // to make sure that we switch between 0 and -0.
6312 // Also enter it if the value of the smi is Smi::kMinValue 6316 // Also enter it if the value of the smi is Smi::kMinValue.
6313 __ testl(rax, Immediate(0x7FFFFFFE)); 6317 __ SmiNeg(rax, rax, &done);
6314 __ j(zero, &special);
6315 __ negl(rax);
6316 __ jmp(&done);
6317 6318
6318 __ bind(&special); 6319 // Either zero or Smi::kMinValue, neither of which become a smi when negated.
6319 // Either zero or -0x4000000, neither of which become a smi when negated. 6320 __ SmiCompare(rax, Smi::FromInt(0));
6320 __ testl(rax, rax); 6321 __ j(not_equal, &slow);
6321 __ j(not_zero, &slow);
6322 __ Move(rax, Factory::minus_zero_value()); 6322 __ Move(rax, Factory::minus_zero_value());
6323 __ jmp(&done); 6323 __ jmp(&done);
6324 6324
6325 // Enter runtime system. 6325 // Enter runtime system.
6326 __ bind(&slow); 6326 __ bind(&slow);
6327 __ pop(rcx); // pop return address 6327 __ pop(rcx); // pop return address
6328 __ push(rax); 6328 __ push(rax);
6329 __ push(rcx); // push return address 6329 __ push(rcx); // push return address
6330 __ InvokeBuiltin(Builtins::UNARY_MINUS, JUMP_FUNCTION); 6330 __ InvokeBuiltin(Builtins::UNARY_MINUS, JUMP_FUNCTION);
6331 __ jmp(&done); 6331 __ jmp(&done);
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after
6463 // Push arguments below the return address to prepare jump to builtin. 6463 // Push arguments below the return address to prepare jump to builtin.
6464 __ pop(rcx); 6464 __ pop(rcx);
6465 __ push(rax); 6465 __ push(rax);
6466 __ push(rdx); 6466 __ push(rdx);
6467 __ push(rcx); 6467 __ push(rcx);
6468 6468
6469 // Inlined floating point compare. 6469 // Inlined floating point compare.
6470 // Call builtin if operands are not floating point or smi. 6470 // Call builtin if operands are not floating point or smi.
6471 Label check_for_symbols; 6471 Label check_for_symbols;
6472 // Push arguments on stack, for helper functions. 6472 // Push arguments on stack, for helper functions.
6473 FloatingPointHelper::CheckFloatOperands(masm, &check_for_symbols); 6473 FloatingPointHelper::CheckNumberOperands(masm, &check_for_symbols);
6474 FloatingPointHelper::LoadFloatOperands(masm, rax, rdx); 6474 FloatingPointHelper::LoadFloatOperands(masm, rax, rdx);
6475 __ FCmp(); 6475 __ FCmp();
6476 6476
6477 // Jump to builtin for NaN. 6477 // Jump to builtin for NaN.
6478 __ j(parity_even, &call_builtin); 6478 __ j(parity_even, &call_builtin);
6479 6479
6480 // TODO(1243847): Use cmov below once CpuFeatures are properly hooked up. 6480 // TODO(1243847): Use cmov below once CpuFeatures are properly hooked up.
6481 Label below_lbl, above_lbl; 6481 Label below_lbl, above_lbl;
6482 // use rdx, rax to convert unsigned to signed comparison 6482 // use rdx, rax to convert unsigned to signed comparison
6483 __ j(below, &below_lbl); 6483 __ j(below, &below_lbl);
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
6520 builtin = strict_ ? Builtins::STRICT_EQUALS : Builtins::EQUALS; 6520 builtin = strict_ ? Builtins::STRICT_EQUALS : Builtins::EQUALS;
6521 } else { 6521 } else {
6522 builtin = Builtins::COMPARE; 6522 builtin = Builtins::COMPARE;
6523 int ncr; // NaN compare result 6523 int ncr; // NaN compare result
6524 if (cc_ == less || cc_ == less_equal) { 6524 if (cc_ == less || cc_ == less_equal) {
6525 ncr = GREATER; 6525 ncr = GREATER;
6526 } else { 6526 } else {
6527 ASSERT(cc_ == greater || cc_ == greater_equal); // remaining cases 6527 ASSERT(cc_ == greater || cc_ == greater_equal); // remaining cases
6528 ncr = LESS; 6528 ncr = LESS;
6529 } 6529 }
6530 __ push(Immediate(Smi::FromInt(ncr))); 6530 __ Push(Smi::FromInt(ncr));
6531 } 6531 }
6532 6532
6533 // Restore return address on the stack. 6533 // Restore return address on the stack.
6534 __ push(rcx); 6534 __ push(rcx);
6535 6535
6536 // Call the native; it returns -1 (less), 0 (equal), or 1 (greater) 6536 // Call the native; it returns -1 (less), 0 (equal), or 1 (greater)
6537 // tagged as a small integer. 6537 // tagged as a small integer.
6538 __ InvokeBuiltin(builtin, JUMP_FUNCTION); 6538 __ InvokeBuiltin(builtin, JUMP_FUNCTION);
6539 } 6539 }
6540 6540
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
6619 __ j(equal, &is_not_instance); 6619 __ j(equal, &is_not_instance);
6620 __ movq(rcx, FieldOperand(rcx, HeapObject::kMapOffset)); 6620 __ movq(rcx, FieldOperand(rcx, HeapObject::kMapOffset));
6621 __ movq(rcx, FieldOperand(rcx, Map::kPrototypeOffset)); 6621 __ movq(rcx, FieldOperand(rcx, Map::kPrototypeOffset));
6622 __ jmp(&loop); 6622 __ jmp(&loop);
6623 6623
6624 __ bind(&is_instance); 6624 __ bind(&is_instance);
6625 __ xor_(rax, rax); 6625 __ xor_(rax, rax);
6626 __ ret(2 * kPointerSize); 6626 __ ret(2 * kPointerSize);
6627 6627
6628 __ bind(&is_not_instance); 6628 __ bind(&is_not_instance);
6629 __ movq(rax, Immediate(Smi::FromInt(1))); 6629 __ Move(rax, Smi::FromInt(1));
6630 __ ret(2 * kPointerSize); 6630 __ ret(2 * kPointerSize);
6631 6631
6632 // Slow-case: Go through the JavaScript implementation. 6632 // Slow-case: Go through the JavaScript implementation.
6633 __ bind(&slow); 6633 __ bind(&slow);
6634 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); 6634 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION);
6635 } 6635 }
6636 6636
6637 6637
6638 void ArgumentsAccessStub::GenerateNewObject(MacroAssembler* masm) { 6638 void ArgumentsAccessStub::GenerateNewObject(MacroAssembler* masm) {
6639 // The displacement is used for skipping the return address and the 6639 // The displacement is used for skipping the return address and the
6640 // frame pointer on the stack. It is the offset of the last 6640 // frame pointer on the stack. It is the offset of the last
6641 // parameter (if any) relative to the frame pointer. 6641 // parameter (if any) relative to the frame pointer.
6642 static const int kDisplacement = 2 * kPointerSize; 6642 static const int kDisplacement = 2 * kPointerSize;
6643 6643
6644 // Check if the calling frame is an arguments adaptor frame. 6644 // Check if the calling frame is an arguments adaptor frame.
6645 Label runtime; 6645 Label runtime;
6646 __ movq(rdx, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); 6646 __ movq(rdx, Operand(rbp, StandardFrameConstants::kCallerFPOffset));
6647 __ movq(rcx, Operand(rdx, StandardFrameConstants::kContextOffset)); 6647 __ SmiCompare(Operand(rdx, StandardFrameConstants::kContextOffset),
6648 __ cmpq(rcx, Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); 6648 Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
6649 __ j(not_equal, &runtime); 6649 __ j(not_equal, &runtime);
6650 // Value in rcx is Smi encoded. 6650 // Value in rcx is Smi encoded.
6651 6651
6652 // Patch the arguments.length and the parameters pointer. 6652 // Patch the arguments.length and the parameters pointer.
6653 __ movq(rcx, Operand(rdx, ArgumentsAdaptorFrameConstants::kLengthOffset)); 6653 __ movq(rcx, Operand(rdx, ArgumentsAdaptorFrameConstants::kLengthOffset));
6654 __ movq(Operand(rsp, 1 * kPointerSize), rcx); 6654 __ movq(Operand(rsp, 1 * kPointerSize), rcx);
6655 SmiIndex index = masm->SmiToIndex(rcx, rcx, kPointerSizeLog2); 6655 SmiIndex index = masm->SmiToIndex(rcx, rcx, kPointerSizeLog2);
6656 __ lea(rdx, Operand(rdx, index.reg, index.scale, kDisplacement)); 6656 __ lea(rdx, Operand(rdx, index.reg, index.scale, kDisplacement));
6657 __ movq(Operand(rsp, 2 * kPointerSize), rdx); 6657 __ movq(Operand(rsp, 2 * kPointerSize), rdx);
6658 6658
(...skipping 12 matching lines...) Expand all
6671 // to the frame pointer. 6671 // to the frame pointer.
6672 static const int kDisplacement = 1 * kPointerSize; 6672 static const int kDisplacement = 1 * kPointerSize;
6673 6673
6674 // Check that the key is a smi. 6674 // Check that the key is a smi.
6675 Label slow; 6675 Label slow;
6676 __ JumpIfNotSmi(rdx, &slow); 6676 __ JumpIfNotSmi(rdx, &slow);
6677 6677
6678 // Check if the calling frame is an arguments adaptor frame. 6678 // Check if the calling frame is an arguments adaptor frame.
6679 Label adaptor; 6679 Label adaptor;
6680 __ movq(rbx, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); 6680 __ movq(rbx, Operand(rbp, StandardFrameConstants::kCallerFPOffset));
6681 __ movq(rcx, Operand(rbx, StandardFrameConstants::kContextOffset)); 6681 __ SmiCompare(Operand(rbx, StandardFrameConstants::kContextOffset),
6682 __ cmpq(rcx, Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); 6682 Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
6683 __ j(equal, &adaptor); 6683 __ j(equal, &adaptor);
6684 6684
6685 // Check index against formal parameters count limit passed in 6685 // Check index against formal parameters count limit passed in
6686 // through register rax. Use unsigned comparison to get negative 6686 // through register rax. Use unsigned comparison to get negative
6687 // check for free. 6687 // check for free.
6688 __ cmpq(rdx, rax); 6688 __ cmpq(rdx, rax);
6689 __ j(above_equal, &slow); 6689 __ j(above_equal, &slow);
6690 6690
6691 // Read the argument from the stack and return it. 6691 // Read the argument from the stack and return it.
6692 SmiIndex index = masm->SmiToIndex(rax, rax, kPointerSizeLog2); 6692 SmiIndex index = masm->SmiToIndex(rax, rax, kPointerSizeLog2);
(...skipping 26 matching lines...) Expand all
6719 Runtime::Function* f = 6719 Runtime::Function* f =
6720 Runtime::FunctionForId(Runtime::kGetArgumentsProperty); 6720 Runtime::FunctionForId(Runtime::kGetArgumentsProperty);
6721 __ TailCallRuntime(ExternalReference(f), 1, f->result_size); 6721 __ TailCallRuntime(ExternalReference(f), 1, f->result_size);
6722 } 6722 }
6723 6723
6724 6724
6725 void ArgumentsAccessStub::GenerateReadLength(MacroAssembler* masm) { 6725 void ArgumentsAccessStub::GenerateReadLength(MacroAssembler* masm) {
6726 // Check if the calling frame is an arguments adaptor frame. 6726 // Check if the calling frame is an arguments adaptor frame.
6727 Label adaptor; 6727 Label adaptor;
6728 __ movq(rdx, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); 6728 __ movq(rdx, Operand(rbp, StandardFrameConstants::kCallerFPOffset));
6729 __ movq(rcx, Operand(rdx, StandardFrameConstants::kContextOffset)); 6729 __ SmiCompare(Operand(rdx, StandardFrameConstants::kContextOffset),
6730 __ cmpq(rcx, Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); 6730 Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
6731 __ j(equal, &adaptor); 6731 __ j(equal, &adaptor);
6732 6732
6733 // Nothing to do: The formal number of parameters has already been 6733 // Nothing to do: The formal number of parameters has already been
6734 // passed in register rax by calling function. Just return it. 6734 // passed in register rax by calling function. Just return it.
6735 __ ret(0); 6735 __ ret(0);
6736 6736
6737 // Arguments adaptor case: Read the arguments length from the 6737 // Arguments adaptor case: Read the arguments length from the
6738 // adaptor frame and return it. 6738 // adaptor frame and return it.
6739 __ bind(&adaptor); 6739 __ bind(&adaptor);
6740 __ movq(rax, Operand(rdx, ArgumentsAdaptorFrameConstants::kLengthOffset)); 6740 __ movq(rax, Operand(rdx, ArgumentsAdaptorFrameConstants::kLengthOffset));
(...skipping 321 matching lines...) Expand 10 before | Expand all | Expand 10 after
7062 #ifdef ENABLE_LOGGING_AND_PROFILING 7062 #ifdef ENABLE_LOGGING_AND_PROFILING
7063 Label not_outermost_js, not_outermost_js_2; 7063 Label not_outermost_js, not_outermost_js_2;
7064 #endif 7064 #endif
7065 7065
7066 // Setup frame. 7066 // Setup frame.
7067 __ push(rbp); 7067 __ push(rbp);
7068 __ movq(rbp, rsp); 7068 __ movq(rbp, rsp);
7069 7069
7070 // Push the stack frame type marker twice. 7070 // Push the stack frame type marker twice.
7071 int marker = is_construct ? StackFrame::ENTRY_CONSTRUCT : StackFrame::ENTRY; 7071 int marker = is_construct ? StackFrame::ENTRY_CONSTRUCT : StackFrame::ENTRY;
7072 __ push(Immediate(Smi::FromInt(marker))); // context slot 7072 __ Push(Smi::FromInt(marker)); // context slot
7073 __ push(Immediate(Smi::FromInt(marker))); // function slot 7073 __ Push(Smi::FromInt(marker)); // function slot
7074 // Save callee-saved registers (X64 calling conventions). 7074 // Save callee-saved registers (X64 calling conventions).
7075 __ push(r12); 7075 __ push(r12);
7076 __ push(r13); 7076 __ push(r13);
7077 __ push(r14); 7077 __ push(r14);
7078 __ push(r15); 7078 __ push(r15);
7079 __ push(rdi); 7079 __ push(rdi);
7080 __ push(rsi); 7080 __ push(rsi);
7081 __ push(rbx); 7081 __ push(rbx);
7082 // TODO(X64): Push XMM6-XMM15 (low 64 bits) as well, or make them 7082 // TODO(X64): Push XMM6-XMM15 (low 64 bits) as well, or make them
7083 // callee-save in JS code as well. 7083 // callee-save in JS code as well.
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
7175 // Implementation of stubs. 7175 // Implementation of stubs.
7176 7176
7177 // Stub classes have public member named masm, not masm_. 7177 // Stub classes have public member named masm, not masm_.
7178 7178
7179 void StackCheckStub::Generate(MacroAssembler* masm) { 7179 void StackCheckStub::Generate(MacroAssembler* masm) {
7180 // Because builtins always remove the receiver from the stack, we 7180 // Because builtins always remove the receiver from the stack, we
7181 // have to fake one to avoid underflowing the stack. The receiver 7181 // have to fake one to avoid underflowing the stack. The receiver
7182 // must be inserted below the return address on the stack so we 7182 // must be inserted below the return address on the stack so we
7183 // temporarily store that in a register. 7183 // temporarily store that in a register.
7184 __ pop(rax); 7184 __ pop(rax);
7185 __ push(Immediate(Smi::FromInt(0))); 7185 __ Push(Smi::FromInt(0));
7186 __ push(rax); 7186 __ push(rax);
7187 7187
7188 // Do tail-call to runtime routine. 7188 // Do tail-call to runtime routine.
7189 Runtime::Function* f = Runtime::FunctionForId(Runtime::kStackGuard); 7189 Runtime::Function* f = Runtime::FunctionForId(Runtime::kStackGuard);
7190 __ TailCallRuntime(ExternalReference(f), 1, f->result_size); 7190 __ TailCallRuntime(ExternalReference(f), 1, f->result_size);
7191 } 7191 }
7192 7192
7193 7193
7194 void FloatingPointHelper::AllocateHeapNumber(MacroAssembler* masm, 7194 void FloatingPointHelper::AllocateHeapNumber(MacroAssembler* masm,
7195 Label* need_gc, 7195 Label* need_gc,
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after
7314 __ bind(&load_smi_rhs); 7314 __ bind(&load_smi_rhs);
7315 __ SmiToInteger64(kScratchRegister, rhs); 7315 __ SmiToInteger64(kScratchRegister, rhs);
7316 __ push(kScratchRegister); 7316 __ push(kScratchRegister);
7317 __ fild_d(Operand(rsp, 0)); 7317 __ fild_d(Operand(rsp, 0));
7318 __ pop(kScratchRegister); 7318 __ pop(kScratchRegister);
7319 7319
7320 __ bind(&done); 7320 __ bind(&done);
7321 } 7321 }
7322 7322
7323 7323
7324 void FloatingPointHelper::CheckFloatOperands(MacroAssembler* masm, 7324 void FloatingPointHelper::CheckNumberOperands(MacroAssembler* masm,
7325 Label* non_float) { 7325 Label* non_float) {
7326 Label test_other, done; 7326 Label test_other, done;
7327 // Test if both operands are numbers (heap_numbers or smis). 7327 // Test if both operands are numbers (heap_numbers or smis).
7328 // If not, jump to label non_float. 7328 // If not, jump to label non_float.
7329 __ JumpIfSmi(rdx, &test_other); // argument in rdx is OK 7329 __ JumpIfSmi(rdx, &test_other); // argument in rdx is OK
7330 __ Cmp(FieldOperand(rdx, HeapObject::kMapOffset), Factory::heap_number_map()); 7330 __ Cmp(FieldOperand(rdx, HeapObject::kMapOffset), Factory::heap_number_map());
7331 __ j(not_equal, non_float); // The argument in rdx is not a number. 7331 __ j(not_equal, non_float); // The argument in rdx is not a number.
7332 7332
7333 __ bind(&test_other); 7333 __ bind(&test_other);
7334 __ JumpIfSmi(rax, &done); // argument in rax is OK 7334 __ JumpIfSmi(rax, &done); // argument in rax is OK
7335 __ Cmp(FieldOperand(rax, HeapObject::kMapOffset), Factory::heap_number_map()); 7335 __ Cmp(FieldOperand(rax, HeapObject::kMapOffset), Factory::heap_number_map());
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
7396 break; 7396 break;
7397 7397
7398 case Token::BIT_XOR: 7398 case Token::BIT_XOR:
7399 __ SmiXor(rax, rax, rbx); 7399 __ SmiXor(rax, rax, rbx);
7400 break; 7400 break;
7401 7401
7402 case Token::SHL: 7402 case Token::SHL:
7403 case Token::SHR: 7403 case Token::SHR:
7404 case Token::SAR: 7404 case Token::SAR:
7405 // Move the second operand into register ecx. 7405 // Move the second operand into register ecx.
7406 __ movl(rcx, rbx); 7406 __ movq(rcx, rbx);
7407 // Perform the operation. 7407 // Perform the operation.
7408 switch (op_) { 7408 switch (op_) {
7409 case Token::SAR: 7409 case Token::SAR:
7410 __ SmiShiftArithmeticRight(rax, rax, rbx); 7410 __ SmiShiftArithmeticRight(rax, rax, rcx);
7411 break; 7411 break;
7412 case Token::SHR: 7412 case Token::SHR:
7413 __ SmiShiftLogicalRight(rax, rax, rbx, slow); 7413 __ SmiShiftLogicalRight(rax, rax, rcx, slow);
7414 break; 7414 break;
7415 case Token::SHL: 7415 case Token::SHL:
7416 __ SmiShiftLeft(rax, rax, rbx, slow); 7416 __ SmiShiftLeft(rax, rax, rcx, slow);
7417 break; 7417 break;
7418 default: 7418 default:
7419 UNREACHABLE(); 7419 UNREACHABLE();
7420 } 7420 }
7421 break; 7421 break;
7422 7422
7423 default: 7423 default:
7424 UNREACHABLE(); 7424 UNREACHABLE();
7425 break; 7425 break;
7426 } 7426 }
(...skipping 20 matching lines...) Expand all
7447 __ movq(rdx, Operand(rsp, 2 * kPointerSize)); // get x 7447 __ movq(rdx, Operand(rsp, 2 * kPointerSize)); // get x
7448 7448
7449 // Floating point case. 7449 // Floating point case.
7450 switch (op_) { 7450 switch (op_) {
7451 case Token::ADD: 7451 case Token::ADD:
7452 case Token::SUB: 7452 case Token::SUB:
7453 case Token::MUL: 7453 case Token::MUL:
7454 case Token::DIV: { 7454 case Token::DIV: {
7455 // rax: y 7455 // rax: y
7456 // rdx: x 7456 // rdx: x
7457 FloatingPointHelper::CheckFloatOperands(masm, &call_runtime); 7457 FloatingPointHelper::CheckNumberOperands(masm, &call_runtime);
7458 // Fast-case: Both operands are numbers. 7458 // Fast-case: Both operands are numbers.
7459 // Allocate a heap number, if needed. 7459 // Allocate a heap number, if needed.
7460 Label skip_allocation; 7460 Label skip_allocation;
7461 switch (mode_) { 7461 switch (mode_) {
7462 case OVERWRITE_LEFT: 7462 case OVERWRITE_LEFT:
7463 __ movq(rax, rdx); 7463 __ movq(rax, rdx);
7464 // Fall through! 7464 // Fall through!
7465 case OVERWRITE_RIGHT: 7465 case OVERWRITE_RIGHT:
7466 // If the argument in rax is already an object, we skip the 7466 // If the argument in rax is already an object, we skip the
7467 // allocation of a heap number. 7467 // allocation of a heap number.
(...skipping 24 matching lines...) Expand all
7492 case Token::MOD: { 7492 case Token::MOD: {
7493 // For MOD we go directly to runtime in the non-smi case. 7493 // For MOD we go directly to runtime in the non-smi case.
7494 break; 7494 break;
7495 } 7495 }
7496 case Token::BIT_OR: 7496 case Token::BIT_OR:
7497 case Token::BIT_AND: 7497 case Token::BIT_AND:
7498 case Token::BIT_XOR: 7498 case Token::BIT_XOR:
7499 case Token::SAR: 7499 case Token::SAR:
7500 case Token::SHL: 7500 case Token::SHL:
7501 case Token::SHR: { 7501 case Token::SHR: {
7502 FloatingPointHelper::CheckFloatOperands(masm, &call_runtime); 7502 FloatingPointHelper::CheckNumberOperands(masm, &call_runtime);
7503 // TODO(X64): Don't convert a Smi to float and then back to int32 7503 // TODO(X64): Don't convert a Smi to float and then back to int32
7504 // afterwards. 7504 // afterwards.
7505 FloatingPointHelper::LoadFloatOperands(masm); 7505 FloatingPointHelper::LoadFloatOperands(masm);
7506 7506
7507 Label skip_allocation, non_smi_result, operand_conversion_failure; 7507 Label skip_allocation, non_smi_result, operand_conversion_failure;
7508 7508
7509 // Reserve space for converted numbers. 7509 // Reserve space for converted numbers.
7510 __ subq(rsp, Immediate(2 * kPointerSize)); 7510 __ subq(rsp, Immediate(2 * kPointerSize));
7511 7511
7512 if (use_sse3_) { 7512 if (use_sse3_) {
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
7546 __ and_(rax, Immediate(0x4400)); 7546 __ and_(rax, Immediate(0x4400));
7547 __ cmpl(rax, Immediate(0x4000)); 7547 __ cmpl(rax, Immediate(0x4000));
7548 __ j(not_zero, &operand_conversion_failure); 7548 __ j(not_zero, &operand_conversion_failure);
7549 } 7549 }
7550 } 7550 }
7551 7551
7552 // Get int32 operands and perform bitop. 7552 // Get int32 operands and perform bitop.
7553 __ pop(rcx); 7553 __ pop(rcx);
7554 __ pop(rax); 7554 __ pop(rax);
7555 switch (op_) { 7555 switch (op_) {
7556 case Token::BIT_OR: __ or_(rax, rcx); break; 7556 case Token::BIT_OR: __ orl(rax, rcx); break;
7557 case Token::BIT_AND: __ and_(rax, rcx); break; 7557 case Token::BIT_AND: __ andl(rax, rcx); break;
7558 case Token::BIT_XOR: __ xor_(rax, rcx); break; 7558 case Token::BIT_XOR: __ xorl(rax, rcx); break;
7559 case Token::SAR: __ sarl(rax); break; 7559 case Token::SAR: __ sarl(rax); break;
7560 case Token::SHL: __ shll(rax); break; 7560 case Token::SHL: __ shll(rax); break;
7561 case Token::SHR: __ shrl(rax); break; 7561 case Token::SHR: __ shrl(rax); break;
7562 default: UNREACHABLE(); 7562 default: UNREACHABLE();
7563 } 7563 }
7564 if (op_ == Token::SHR) { 7564 if (op_ == Token::SHR) {
7565 // Check if result is non-negative and fits in a smi. 7565 // Check if result is non-negative. This can only happen for a shift
7566 __ testl(rax, Immediate(0xc0000000)); 7566 // by zero, which also doesn't update the sign flag.
7567 __ j(not_zero, &non_smi_result); 7567 __ testl(rax, rax);
7568 } else {
7569 // Check if result fits in a smi.
7570 __ cmpl(rax, Immediate(0xc0000000));
7571 __ j(negative, &non_smi_result); 7568 __ j(negative, &non_smi_result);
7572 } 7569 }
7573 // Tag smi result and return. 7570 __ JumpIfNotValidSmiValue(rax, &non_smi_result);
7571 // Tag smi result, if possible, and return.
7574 __ Integer32ToSmi(rax, rax); 7572 __ Integer32ToSmi(rax, rax);
7575 __ ret(2 * kPointerSize); 7573 __ ret(2 * kPointerSize);
7576 7574
7577 // All ops except SHR return a signed int32 that we load in a HeapNumber. 7575 // All ops except SHR return a signed int32 that we load in a HeapNumber.
7578 if (op_ != Token::SHR) { 7576 if (op_ != Token::SHR && non_smi_result.is_linked()) {
7579 __ bind(&non_smi_result); 7577 __ bind(&non_smi_result);
7580 // Allocate a heap number if needed. 7578 // Allocate a heap number if needed.
7581 __ movsxlq(rbx, rax); // rbx: sign extended 32-bit result 7579 __ movsxlq(rbx, rax); // rbx: sign extended 32-bit result
7582 switch (mode_) { 7580 switch (mode_) {
7583 case OVERWRITE_LEFT: 7581 case OVERWRITE_LEFT:
7584 case OVERWRITE_RIGHT: 7582 case OVERWRITE_RIGHT:
7585 // If the operand was an object, we skip the 7583 // If the operand was an object, we skip the
7586 // allocation of a heap number. 7584 // allocation of a heap number.
7587 __ movq(rax, Operand(rsp, mode_ == OVERWRITE_RIGHT ? 7585 __ movq(rax, Operand(rsp, mode_ == OVERWRITE_RIGHT ?
7588 1 * kPointerSize : 2 * kPointerSize)); 7586 1 * kPointerSize : 2 * kPointerSize));
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
7675 int CompareStub::MinorKey() { 7673 int CompareStub::MinorKey() {
7676 // Encode the two parameters in a unique 16 bit value. 7674 // Encode the two parameters in a unique 16 bit value.
7677 ASSERT(static_cast<unsigned>(cc_) < (1 << 15)); 7675 ASSERT(static_cast<unsigned>(cc_) < (1 << 15));
7678 return (static_cast<unsigned>(cc_) << 1) | (strict_ ? 1 : 0); 7676 return (static_cast<unsigned>(cc_) << 1) | (strict_ ? 1 : 0);
7679 } 7677 }
7680 7678
7681 7679
7682 #undef __ 7680 #undef __
7683 7681
7684 } } // namespace v8::internal 7682 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/x64/builtins-x64.cc ('k') | src/x64/ic-x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698