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

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

Issue 143633007: A64: Synchronize with r18764. (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/a64
Patch Set: Created 6 years, 10 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/x64/deoptimizer-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 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 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 121 matching lines...) Expand 10 before | Expand all | Expand 10 after
132 } 132 }
133 #endif 133 #endif
134 134
135 // Classic mode functions and builtins need to replace the receiver with the 135 // Classic mode functions and builtins need to replace the receiver with the
136 // global proxy when called as functions (without an explicit receiver 136 // global proxy when called as functions (without an explicit receiver
137 // object). 137 // object).
138 if (info->is_classic_mode() && !info->is_native()) { 138 if (info->is_classic_mode() && !info->is_native()) {
139 Label ok; 139 Label ok;
140 // +1 for return address. 140 // +1 for return address.
141 StackArgumentsAccessor args(rsp, info->scope()->num_parameters()); 141 StackArgumentsAccessor args(rsp, info->scope()->num_parameters());
142 __ movq(rcx, args.GetReceiverOperand()); 142 __ movp(rcx, args.GetReceiverOperand());
143 143
144 __ CompareRoot(rcx, Heap::kUndefinedValueRootIndex); 144 __ CompareRoot(rcx, Heap::kUndefinedValueRootIndex);
145 __ j(not_equal, &ok, Label::kNear); 145 __ j(not_equal, &ok, Label::kNear);
146 146
147 __ movq(rcx, GlobalObjectOperand()); 147 __ movp(rcx, GlobalObjectOperand());
148 __ movq(rcx, FieldOperand(rcx, GlobalObject::kGlobalReceiverOffset)); 148 __ movp(rcx, FieldOperand(rcx, GlobalObject::kGlobalReceiverOffset));
149 149
150 __ movq(args.GetReceiverOperand(), rcx); 150 __ movp(args.GetReceiverOperand(), rcx);
151 151
152 __ bind(&ok); 152 __ bind(&ok);
153 } 153 }
154 154
155 // Open a frame scope to indicate that there is a frame on the stack. The 155 // Open a frame scope to indicate that there is a frame on the stack. The
156 // MANUAL indicates that the scope shouldn't actually generate code to set up 156 // MANUAL indicates that the scope shouldn't actually generate code to set up
157 // the frame (that is done below). 157 // the frame (that is done below).
158 FrameScope frame_scope(masm_, StackFrame::MANUAL); 158 FrameScope frame_scope(masm_, StackFrame::MANUAL);
159 159
160 info->set_prologue_offset(masm_->pc_offset()); 160 info->set_prologue_offset(masm_->pc_offset());
(...skipping 14 matching lines...) Expand all
175 } 175 }
176 } 176 }
177 177
178 bool function_in_register = true; 178 bool function_in_register = true;
179 179
180 // Possibly allocate a local context. 180 // Possibly allocate a local context.
181 int heap_slots = info->scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; 181 int heap_slots = info->scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
182 if (heap_slots > 0) { 182 if (heap_slots > 0) {
183 Comment cmnt(masm_, "[ Allocate context"); 183 Comment cmnt(masm_, "[ Allocate context");
184 // Argument to NewContext is the function, which is still in rdi. 184 // Argument to NewContext is the function, which is still in rdi.
185 __ push(rdi);
186 if (FLAG_harmony_scoping && info->scope()->is_global_scope()) { 185 if (FLAG_harmony_scoping && info->scope()->is_global_scope()) {
186 __ push(rdi);
187 __ Push(info->scope()->GetScopeInfo()); 187 __ Push(info->scope()->GetScopeInfo());
188 __ CallRuntime(Runtime::kNewGlobalContext, 2); 188 __ CallRuntime(Runtime::kNewGlobalContext, 2);
189 } else if (heap_slots <= FastNewContextStub::kMaximumSlots) { 189 } else if (heap_slots <= FastNewContextStub::kMaximumSlots) {
190 FastNewContextStub stub(heap_slots); 190 FastNewContextStub stub(heap_slots);
191 __ CallStub(&stub); 191 __ CallStub(&stub);
192 } else { 192 } else {
193 __ push(rdi);
193 __ CallRuntime(Runtime::kNewFunctionContext, 1); 194 __ CallRuntime(Runtime::kNewFunctionContext, 1);
194 } 195 }
195 function_in_register = false; 196 function_in_register = false;
196 // Context is returned in both rax and rsi. It replaces the context 197 // Context is returned in rax. It replaces the context passed to us.
197 // passed to us. It's saved in the stack and kept live in rsi. 198 // It's saved in the stack and kept live in rsi.
198 __ movq(Operand(rbp, StandardFrameConstants::kContextOffset), rsi); 199 __ movp(rsi, rax);
200 __ movp(Operand(rbp, StandardFrameConstants::kContextOffset), rax);
199 201
200 // Copy any necessary parameters into the context. 202 // Copy any necessary parameters into the context.
201 int num_parameters = info->scope()->num_parameters(); 203 int num_parameters = info->scope()->num_parameters();
202 for (int i = 0; i < num_parameters; i++) { 204 for (int i = 0; i < num_parameters; i++) {
203 Variable* var = scope()->parameter(i); 205 Variable* var = scope()->parameter(i);
204 if (var->IsContextSlot()) { 206 if (var->IsContextSlot()) {
205 int parameter_offset = StandardFrameConstants::kCallerSPOffset + 207 int parameter_offset = StandardFrameConstants::kCallerSPOffset +
206 (num_parameters - 1 - i) * kPointerSize; 208 (num_parameters - 1 - i) * kPointerSize;
207 // Load parameter from stack. 209 // Load parameter from stack.
208 __ movq(rax, Operand(rbp, parameter_offset)); 210 __ movp(rax, Operand(rbp, parameter_offset));
209 // Store it in the context. 211 // Store it in the context.
210 int context_offset = Context::SlotOffset(var->index()); 212 int context_offset = Context::SlotOffset(var->index());
211 __ movq(Operand(rsi, context_offset), rax); 213 __ movp(Operand(rsi, context_offset), rax);
212 // Update the write barrier. This clobbers rax and rbx. 214 // Update the write barrier. This clobbers rax and rbx.
213 __ RecordWriteContextSlot( 215 __ RecordWriteContextSlot(
214 rsi, context_offset, rax, rbx, kDontSaveFPRegs); 216 rsi, context_offset, rax, rbx, kDontSaveFPRegs);
215 } 217 }
216 } 218 }
217 } 219 }
218 220
219 // Possibly allocate an arguments object. 221 // Possibly allocate an arguments object.
220 Variable* arguments = scope()->arguments(); 222 Variable* arguments = scope()->arguments();
221 if (arguments != NULL) { 223 if (arguments != NULL) {
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
311 __ Move(rbx, profiling_counter_, RelocInfo::EMBEDDED_OBJECT); 313 __ Move(rbx, profiling_counter_, RelocInfo::EMBEDDED_OBJECT);
312 __ SmiAddConstant(FieldOperand(rbx, Cell::kValueOffset), 314 __ SmiAddConstant(FieldOperand(rbx, Cell::kValueOffset),
313 Smi::FromInt(-delta)); 315 Smi::FromInt(-delta));
314 } 316 }
315 317
316 318
317 void FullCodeGenerator::EmitProfilingCounterReset() { 319 void FullCodeGenerator::EmitProfilingCounterReset() {
318 int reset_value = FLAG_interrupt_budget; 320 int reset_value = FLAG_interrupt_budget;
319 __ Move(rbx, profiling_counter_, RelocInfo::EMBEDDED_OBJECT); 321 __ Move(rbx, profiling_counter_, RelocInfo::EMBEDDED_OBJECT);
320 __ Move(kScratchRegister, Smi::FromInt(reset_value)); 322 __ Move(kScratchRegister, Smi::FromInt(reset_value));
321 __ movq(FieldOperand(rbx, Cell::kValueOffset), kScratchRegister); 323 __ movp(FieldOperand(rbx, Cell::kValueOffset), kScratchRegister);
322 } 324 }
323 325
324 326
325 void FullCodeGenerator::EmitBackEdgeBookkeeping(IterationStatement* stmt, 327 void FullCodeGenerator::EmitBackEdgeBookkeeping(IterationStatement* stmt,
326 Label* back_edge_target) { 328 Label* back_edge_target) {
327 Comment cmnt(masm_, "[ Back edge bookkeeping"); 329 Comment cmnt(masm_, "[ Back edge bookkeeping");
328 Label ok; 330 Label ok;
329 331
330 ASSERT(back_edge_target->is_bound()); 332 ASSERT(back_edge_target->is_bound());
331 int distance = masm_->SizeOfCodeGeneratedSince(back_edge_target); 333 int distance = masm_->SizeOfCodeGeneratedSince(back_edge_target);
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
381 __ bind(&ok); 383 __ bind(&ok);
382 #ifdef DEBUG 384 #ifdef DEBUG
383 // Add a label for checking the size of the code used for returning. 385 // Add a label for checking the size of the code used for returning.
384 Label check_exit_codesize; 386 Label check_exit_codesize;
385 masm_->bind(&check_exit_codesize); 387 masm_->bind(&check_exit_codesize);
386 #endif 388 #endif
387 CodeGenerator::RecordPositions(masm_, function()->end_position() - 1); 389 CodeGenerator::RecordPositions(masm_, function()->end_position() - 1);
388 __ RecordJSReturn(); 390 __ RecordJSReturn();
389 // Do not use the leave instruction here because it is too short to 391 // Do not use the leave instruction here because it is too short to
390 // patch with the code required by the debugger. 392 // patch with the code required by the debugger.
391 __ movq(rsp, rbp); 393 __ movp(rsp, rbp);
392 __ pop(rbp); 394 __ pop(rbp);
393 int no_frame_start = masm_->pc_offset(); 395 int no_frame_start = masm_->pc_offset();
394 396
395 int arguments_bytes = (info_->scope()->num_parameters() + 1) * kPointerSize; 397 int arguments_bytes = (info_->scope()->num_parameters() + 1) * kPointerSize;
396 __ Ret(arguments_bytes, rcx); 398 __ Ret(arguments_bytes, rcx);
397 399
398 #ifdef ENABLE_DEBUGGER_SUPPORT 400 #ifdef ENABLE_DEBUGGER_SUPPORT
399 // Add padding that will be overwritten by a debugger breakpoint. We 401 // Add padding that will be overwritten by a debugger breakpoint. We
400 // have just generated at least 7 bytes: "movq rsp, rbp; pop rbp; ret k" 402 // have just generated at least 7 bytes: "movq rsp, rbp; pop rbp; ret k"
401 // (3 + 1 + 3). 403 // (3 + 1 + 3).
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after
538 ASSERT(count > 0); 540 ASSERT(count > 0);
539 __ Drop(count); 541 __ Drop(count);
540 __ Move(result_register(), reg); 542 __ Move(result_register(), reg);
541 } 543 }
542 544
543 545
544 void FullCodeGenerator::StackValueContext::DropAndPlug(int count, 546 void FullCodeGenerator::StackValueContext::DropAndPlug(int count,
545 Register reg) const { 547 Register reg) const {
546 ASSERT(count > 0); 548 ASSERT(count > 0);
547 if (count > 1) __ Drop(count - 1); 549 if (count > 1) __ Drop(count - 1);
548 __ movq(Operand(rsp, 0), reg); 550 __ movp(Operand(rsp, 0), reg);
549 } 551 }
550 552
551 553
552 void FullCodeGenerator::TestContext::DropAndPlug(int count, 554 void FullCodeGenerator::TestContext::DropAndPlug(int count,
553 Register reg) const { 555 Register reg) const {
554 ASSERT(count > 0); 556 ASSERT(count > 0);
555 // For simplicity we always test the accumulator register. 557 // For simplicity we always test the accumulator register.
556 __ Drop(count); 558 __ Drop(count);
557 __ Move(result_register(), reg); 559 __ Move(result_register(), reg);
558 codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL); 560 codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL);
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
681 return ContextOperand(scratch, var->index()); 683 return ContextOperand(scratch, var->index());
682 } else { 684 } else {
683 return StackOperand(var); 685 return StackOperand(var);
684 } 686 }
685 } 687 }
686 688
687 689
688 void FullCodeGenerator::GetVar(Register dest, Variable* var) { 690 void FullCodeGenerator::GetVar(Register dest, Variable* var) {
689 ASSERT(var->IsContextSlot() || var->IsStackAllocated()); 691 ASSERT(var->IsContextSlot() || var->IsStackAllocated());
690 MemOperand location = VarOperand(var, dest); 692 MemOperand location = VarOperand(var, dest);
691 __ movq(dest, location); 693 __ movp(dest, location);
692 } 694 }
693 695
694 696
695 void FullCodeGenerator::SetVar(Variable* var, 697 void FullCodeGenerator::SetVar(Variable* var,
696 Register src, 698 Register src,
697 Register scratch0, 699 Register scratch0,
698 Register scratch1) { 700 Register scratch1) {
699 ASSERT(var->IsContextSlot() || var->IsStackAllocated()); 701 ASSERT(var->IsContextSlot() || var->IsStackAllocated());
700 ASSERT(!scratch0.is(src)); 702 ASSERT(!scratch0.is(src));
701 ASSERT(!scratch0.is(scratch1)); 703 ASSERT(!scratch0.is(scratch1));
702 ASSERT(!scratch1.is(src)); 704 ASSERT(!scratch1.is(src));
703 MemOperand location = VarOperand(var, scratch0); 705 MemOperand location = VarOperand(var, scratch0);
704 __ movq(location, src); 706 __ movp(location, src);
705 707
706 // Emit the write barrier code if the location is in the heap. 708 // Emit the write barrier code if the location is in the heap.
707 if (var->IsContextSlot()) { 709 if (var->IsContextSlot()) {
708 int offset = Context::SlotOffset(var->index()); 710 int offset = Context::SlotOffset(var->index());
709 __ RecordWriteContextSlot(scratch0, offset, src, scratch1, kDontSaveFPRegs); 711 __ RecordWriteContextSlot(scratch0, offset, src, scratch1, kDontSaveFPRegs);
710 } 712 }
711 } 713 }
712 714
713 715
714 void FullCodeGenerator::PrepareForBailoutBeforeSplit(Expression* expr, 716 void FullCodeGenerator::PrepareForBailoutBeforeSplit(Expression* expr,
(...skipping 14 matching lines...) Expand all
729 __ bind(&skip); 731 __ bind(&skip);
730 } 732 }
731 } 733 }
732 734
733 735
734 void FullCodeGenerator::EmitDebugCheckDeclarationContext(Variable* variable) { 736 void FullCodeGenerator::EmitDebugCheckDeclarationContext(Variable* variable) {
735 // The variable in the declaration always resides in the current context. 737 // The variable in the declaration always resides in the current context.
736 ASSERT_EQ(0, scope()->ContextChainLength(variable->scope())); 738 ASSERT_EQ(0, scope()->ContextChainLength(variable->scope()));
737 if (generate_debug_code_) { 739 if (generate_debug_code_) {
738 // Check that we're not inside a with or catch context. 740 // Check that we're not inside a with or catch context.
739 __ movq(rbx, FieldOperand(rsi, HeapObject::kMapOffset)); 741 __ movp(rbx, FieldOperand(rsi, HeapObject::kMapOffset));
740 __ CompareRoot(rbx, Heap::kWithContextMapRootIndex); 742 __ CompareRoot(rbx, Heap::kWithContextMapRootIndex);
741 __ Check(not_equal, kDeclarationInWithContext); 743 __ Check(not_equal, kDeclarationInWithContext);
742 __ CompareRoot(rbx, Heap::kCatchContextMapRootIndex); 744 __ CompareRoot(rbx, Heap::kCatchContextMapRootIndex);
743 __ Check(not_equal, kDeclarationInCatchContext); 745 __ Check(not_equal, kDeclarationInCatchContext);
744 } 746 }
745 } 747 }
746 748
747 749
748 void FullCodeGenerator::VisitVariableDeclaration( 750 void FullCodeGenerator::VisitVariableDeclaration(
749 VariableDeclaration* declaration) { 751 VariableDeclaration* declaration) {
(...skipping 11 matching lines...) Expand all
761 ? isolate()->factory()->the_hole_value() 763 ? isolate()->factory()->the_hole_value()
762 : isolate()->factory()->undefined_value(), 764 : isolate()->factory()->undefined_value(),
763 zone()); 765 zone());
764 break; 766 break;
765 767
766 case Variable::PARAMETER: 768 case Variable::PARAMETER:
767 case Variable::LOCAL: 769 case Variable::LOCAL:
768 if (hole_init) { 770 if (hole_init) {
769 Comment cmnt(masm_, "[ VariableDeclaration"); 771 Comment cmnt(masm_, "[ VariableDeclaration");
770 __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex); 772 __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex);
771 __ movq(StackOperand(variable), kScratchRegister); 773 __ movp(StackOperand(variable), kScratchRegister);
772 } 774 }
773 break; 775 break;
774 776
775 case Variable::CONTEXT: 777 case Variable::CONTEXT:
776 if (hole_init) { 778 if (hole_init) {
777 Comment cmnt(masm_, "[ VariableDeclaration"); 779 Comment cmnt(masm_, "[ VariableDeclaration");
778 EmitDebugCheckDeclarationContext(variable); 780 EmitDebugCheckDeclarationContext(variable);
779 __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex); 781 __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex);
780 __ movq(ContextOperand(rsi, variable->index()), kScratchRegister); 782 __ movp(ContextOperand(rsi, variable->index()), kScratchRegister);
781 // No write barrier since the hole value is in old space. 783 // No write barrier since the hole value is in old space.
782 PrepareForBailoutForId(proxy->id(), NO_REGISTERS); 784 PrepareForBailoutForId(proxy->id(), NO_REGISTERS);
783 } 785 }
784 break; 786 break;
785 787
786 case Variable::LOOKUP: { 788 case Variable::LOOKUP: {
787 Comment cmnt(masm_, "[ VariableDeclaration"); 789 Comment cmnt(masm_, "[ VariableDeclaration");
788 __ push(rsi); 790 __ push(rsi);
789 __ Push(variable->name()); 791 __ Push(variable->name());
790 // Declaration nodes are always introduced in one of four modes. 792 // Declaration nodes are always introduced in one of four modes.
(...skipping 29 matching lines...) Expand all
820 // Check for stack-overflow exception. 822 // Check for stack-overflow exception.
821 if (function.is_null()) return SetStackOverflow(); 823 if (function.is_null()) return SetStackOverflow();
822 globals_->Add(function, zone()); 824 globals_->Add(function, zone());
823 break; 825 break;
824 } 826 }
825 827
826 case Variable::PARAMETER: 828 case Variable::PARAMETER:
827 case Variable::LOCAL: { 829 case Variable::LOCAL: {
828 Comment cmnt(masm_, "[ FunctionDeclaration"); 830 Comment cmnt(masm_, "[ FunctionDeclaration");
829 VisitForAccumulatorValue(declaration->fun()); 831 VisitForAccumulatorValue(declaration->fun());
830 __ movq(StackOperand(variable), result_register()); 832 __ movp(StackOperand(variable), result_register());
831 break; 833 break;
832 } 834 }
833 835
834 case Variable::CONTEXT: { 836 case Variable::CONTEXT: {
835 Comment cmnt(masm_, "[ FunctionDeclaration"); 837 Comment cmnt(masm_, "[ FunctionDeclaration");
836 EmitDebugCheckDeclarationContext(variable); 838 EmitDebugCheckDeclarationContext(variable);
837 VisitForAccumulatorValue(declaration->fun()); 839 VisitForAccumulatorValue(declaration->fun());
838 __ movq(ContextOperand(rsi, variable->index()), result_register()); 840 __ movp(ContextOperand(rsi, variable->index()), result_register());
839 int offset = Context::SlotOffset(variable->index()); 841 int offset = Context::SlotOffset(variable->index());
840 // We know that we have written a function, which is not a smi. 842 // We know that we have written a function, which is not a smi.
841 __ RecordWriteContextSlot(rsi, 843 __ RecordWriteContextSlot(rsi,
842 offset, 844 offset,
843 result_register(), 845 result_register(),
844 rcx, 846 rcx,
845 kDontSaveFPRegs, 847 kDontSaveFPRegs,
846 EMIT_REMEMBERED_SET, 848 EMIT_REMEMBERED_SET,
847 OMIT_SMI_CHECK); 849 OMIT_SMI_CHECK);
848 PrepareForBailoutForId(proxy->id(), NO_REGISTERS); 850 PrepareForBailoutForId(proxy->id(), NO_REGISTERS);
(...skipping 16 matching lines...) Expand all
865 void FullCodeGenerator::VisitModuleDeclaration(ModuleDeclaration* declaration) { 867 void FullCodeGenerator::VisitModuleDeclaration(ModuleDeclaration* declaration) {
866 Variable* variable = declaration->proxy()->var(); 868 Variable* variable = declaration->proxy()->var();
867 ASSERT(variable->location() == Variable::CONTEXT); 869 ASSERT(variable->location() == Variable::CONTEXT);
868 ASSERT(variable->interface()->IsFrozen()); 870 ASSERT(variable->interface()->IsFrozen());
869 871
870 Comment cmnt(masm_, "[ ModuleDeclaration"); 872 Comment cmnt(masm_, "[ ModuleDeclaration");
871 EmitDebugCheckDeclarationContext(variable); 873 EmitDebugCheckDeclarationContext(variable);
872 874
873 // Load instance object. 875 // Load instance object.
874 __ LoadContext(rax, scope_->ContextChainLength(scope_->GlobalScope())); 876 __ LoadContext(rax, scope_->ContextChainLength(scope_->GlobalScope()));
875 __ movq(rax, ContextOperand(rax, variable->interface()->Index())); 877 __ movp(rax, ContextOperand(rax, variable->interface()->Index()));
876 __ movq(rax, ContextOperand(rax, Context::EXTENSION_INDEX)); 878 __ movp(rax, ContextOperand(rax, Context::EXTENSION_INDEX));
877 879
878 // Assign it. 880 // Assign it.
879 __ movq(ContextOperand(rsi, variable->index()), rax); 881 __ movp(ContextOperand(rsi, variable->index()), rax);
880 // We know that we have written a module, which is not a smi. 882 // We know that we have written a module, which is not a smi.
881 __ RecordWriteContextSlot(rsi, 883 __ RecordWriteContextSlot(rsi,
882 Context::SlotOffset(variable->index()), 884 Context::SlotOffset(variable->index()),
883 rax, 885 rax,
884 rcx, 886 rcx,
885 kDontSaveFPRegs, 887 kDontSaveFPRegs,
886 EMIT_REMEMBERED_SET, 888 EMIT_REMEMBERED_SET,
887 OMIT_SMI_CHECK); 889 OMIT_SMI_CHECK);
888 PrepareForBailoutForId(declaration->proxy()->id(), NO_REGISTERS); 890 PrepareForBailoutForId(declaration->proxy()->id(), NO_REGISTERS);
889 891
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
963 } 965 }
964 966
965 Comment cmnt(masm_, "[ Case comparison"); 967 Comment cmnt(masm_, "[ Case comparison");
966 __ bind(&next_test); 968 __ bind(&next_test);
967 next_test.Unuse(); 969 next_test.Unuse();
968 970
969 // Compile the label expression. 971 // Compile the label expression.
970 VisitForAccumulatorValue(clause->label()); 972 VisitForAccumulatorValue(clause->label());
971 973
972 // Perform the comparison as if via '==='. 974 // Perform the comparison as if via '==='.
973 __ movq(rdx, Operand(rsp, 0)); // Switch value. 975 __ movp(rdx, Operand(rsp, 0)); // Switch value.
974 bool inline_smi_code = ShouldInlineSmiCase(Token::EQ_STRICT); 976 bool inline_smi_code = ShouldInlineSmiCase(Token::EQ_STRICT);
975 JumpPatchSite patch_site(masm_); 977 JumpPatchSite patch_site(masm_);
976 if (inline_smi_code) { 978 if (inline_smi_code) {
977 Label slow_case; 979 Label slow_case;
978 __ movq(rcx, rdx); 980 __ movp(rcx, rdx);
979 __ or_(rcx, rax); 981 __ or_(rcx, rax);
980 patch_site.EmitJumpIfNotSmi(rcx, &slow_case, Label::kNear); 982 patch_site.EmitJumpIfNotSmi(rcx, &slow_case, Label::kNear);
981 983
982 __ cmpq(rdx, rax); 984 __ cmpq(rdx, rax);
983 __ j(not_equal, &next_test); 985 __ j(not_equal, &next_test);
984 __ Drop(1); // Switch value is no longer needed. 986 __ Drop(1); // Switch value is no longer needed.
985 __ jmp(clause->body_target()); 987 __ jmp(clause->body_target());
986 __ bind(&slow_case); 988 __ bind(&slow_case);
987 } 989 }
988 990
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
1070 1072
1071 // Check cache validity in generated code. This is a fast case for 1073 // Check cache validity in generated code. This is a fast case for
1072 // the JSObject::IsSimpleEnum cache validity checks. If we cannot 1074 // the JSObject::IsSimpleEnum cache validity checks. If we cannot
1073 // guarantee cache validity, call the runtime system to check cache 1075 // guarantee cache validity, call the runtime system to check cache
1074 // validity or get the property names in a fixed array. 1076 // validity or get the property names in a fixed array.
1075 __ CheckEnumCache(null_value, &call_runtime); 1077 __ CheckEnumCache(null_value, &call_runtime);
1076 1078
1077 // The enum cache is valid. Load the map of the object being 1079 // The enum cache is valid. Load the map of the object being
1078 // iterated over and use the cache for the iteration. 1080 // iterated over and use the cache for the iteration.
1079 Label use_cache; 1081 Label use_cache;
1080 __ movq(rax, FieldOperand(rax, HeapObject::kMapOffset)); 1082 __ movp(rax, FieldOperand(rax, HeapObject::kMapOffset));
1081 __ jmp(&use_cache, Label::kNear); 1083 __ jmp(&use_cache, Label::kNear);
1082 1084
1083 // Get the set of properties to enumerate. 1085 // Get the set of properties to enumerate.
1084 __ bind(&call_runtime); 1086 __ bind(&call_runtime);
1085 __ push(rax); // Duplicate the enumerable object on the stack. 1087 __ push(rax); // Duplicate the enumerable object on the stack.
1086 __ CallRuntime(Runtime::kGetPropertyNamesFast, 1); 1088 __ CallRuntime(Runtime::kGetPropertyNamesFast, 1);
1087 1089
1088 // If we got a map from the runtime call, we can do a fast 1090 // If we got a map from the runtime call, we can do a fast
1089 // modification check. Otherwise, we got a fixed array, and we have 1091 // modification check. Otherwise, we got a fixed array, and we have
1090 // to do a slow check. 1092 // to do a slow check.
1091 Label fixed_array; 1093 Label fixed_array;
1092 __ CompareRoot(FieldOperand(rax, HeapObject::kMapOffset), 1094 __ CompareRoot(FieldOperand(rax, HeapObject::kMapOffset),
1093 Heap::kMetaMapRootIndex); 1095 Heap::kMetaMapRootIndex);
1094 __ j(not_equal, &fixed_array); 1096 __ j(not_equal, &fixed_array);
1095 1097
1096 // We got a map in register rax. Get the enumeration cache from it. 1098 // We got a map in register rax. Get the enumeration cache from it.
1097 __ bind(&use_cache); 1099 __ bind(&use_cache);
1098 1100
1099 Label no_descriptors; 1101 Label no_descriptors;
1100 1102
1101 __ EnumLength(rdx, rax); 1103 __ EnumLength(rdx, rax);
1102 __ Cmp(rdx, Smi::FromInt(0)); 1104 __ Cmp(rdx, Smi::FromInt(0));
1103 __ j(equal, &no_descriptors); 1105 __ j(equal, &no_descriptors);
1104 1106
1105 __ LoadInstanceDescriptors(rax, rcx); 1107 __ LoadInstanceDescriptors(rax, rcx);
1106 __ movq(rcx, FieldOperand(rcx, DescriptorArray::kEnumCacheOffset)); 1108 __ movp(rcx, FieldOperand(rcx, DescriptorArray::kEnumCacheOffset));
1107 __ movq(rcx, FieldOperand(rcx, DescriptorArray::kEnumCacheBridgeCacheOffset)); 1109 __ movp(rcx, FieldOperand(rcx, DescriptorArray::kEnumCacheBridgeCacheOffset));
1108 1110
1109 // Set up the four remaining stack slots. 1111 // Set up the four remaining stack slots.
1110 __ push(rax); // Map. 1112 __ push(rax); // Map.
1111 __ push(rcx); // Enumeration cache. 1113 __ push(rcx); // Enumeration cache.
1112 __ push(rdx); // Number of valid entries for the map in the enum cache. 1114 __ push(rdx); // Number of valid entries for the map in the enum cache.
1113 __ Push(Smi::FromInt(0)); // Initial index. 1115 __ Push(Smi::FromInt(0)); // Initial index.
1114 __ jmp(&loop); 1116 __ jmp(&loop);
1115 1117
1116 __ bind(&no_descriptors); 1118 __ bind(&no_descriptors);
1117 __ addq(rsp, Immediate(kPointerSize)); 1119 __ addq(rsp, Immediate(kPointerSize));
1118 __ jmp(&exit); 1120 __ jmp(&exit);
1119 1121
1120 // We got a fixed array in register rax. Iterate through that. 1122 // We got a fixed array in register rax. Iterate through that.
1121 Label non_proxy; 1123 Label non_proxy;
1122 __ bind(&fixed_array); 1124 __ bind(&fixed_array);
1123 1125
1124 Handle<Cell> cell = isolate()->factory()->NewCell( 1126 Handle<Cell> cell = isolate()->factory()->NewCell(
1125 Handle<Object>(Smi::FromInt(TypeFeedbackCells::kForInFastCaseMarker), 1127 Handle<Object>(Smi::FromInt(TypeFeedbackCells::kForInFastCaseMarker),
1126 isolate())); 1128 isolate()));
1127 RecordTypeFeedbackCell(stmt->ForInFeedbackId(), cell); 1129 RecordTypeFeedbackCell(stmt->ForInFeedbackId(), cell);
1128 __ Move(rbx, cell); 1130 __ Move(rbx, cell);
1129 __ Move(FieldOperand(rbx, Cell::kValueOffset), 1131 __ Move(FieldOperand(rbx, Cell::kValueOffset),
1130 Smi::FromInt(TypeFeedbackCells::kForInSlowCaseMarker)); 1132 Smi::FromInt(TypeFeedbackCells::kForInSlowCaseMarker));
1131 1133
1132 __ Move(rbx, Smi::FromInt(1)); // Smi indicates slow check 1134 __ Move(rbx, Smi::FromInt(1)); // Smi indicates slow check
1133 __ movq(rcx, Operand(rsp, 0 * kPointerSize)); // Get enumerated object 1135 __ movp(rcx, Operand(rsp, 0 * kPointerSize)); // Get enumerated object
1134 STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE); 1136 STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE);
1135 __ CmpObjectType(rcx, LAST_JS_PROXY_TYPE, rcx); 1137 __ CmpObjectType(rcx, LAST_JS_PROXY_TYPE, rcx);
1136 __ j(above, &non_proxy); 1138 __ j(above, &non_proxy);
1137 __ Move(rbx, Smi::FromInt(0)); // Zero indicates proxy 1139 __ Move(rbx, Smi::FromInt(0)); // Zero indicates proxy
1138 __ bind(&non_proxy); 1140 __ bind(&non_proxy);
1139 __ push(rbx); // Smi 1141 __ push(rbx); // Smi
1140 __ push(rax); // Array 1142 __ push(rax); // Array
1141 __ movq(rax, FieldOperand(rax, FixedArray::kLengthOffset)); 1143 __ movp(rax, FieldOperand(rax, FixedArray::kLengthOffset));
1142 __ push(rax); // Fixed array length (as smi). 1144 __ push(rax); // Fixed array length (as smi).
1143 __ Push(Smi::FromInt(0)); // Initial index. 1145 __ Push(Smi::FromInt(0)); // Initial index.
1144 1146
1145 // Generate code for doing the condition check. 1147 // Generate code for doing the condition check.
1146 PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS); 1148 PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS);
1147 __ bind(&loop); 1149 __ bind(&loop);
1148 __ movq(rax, Operand(rsp, 0 * kPointerSize)); // Get the current index. 1150 __ movp(rax, Operand(rsp, 0 * kPointerSize)); // Get the current index.
1149 __ cmpq(rax, Operand(rsp, 1 * kPointerSize)); // Compare to the array length. 1151 __ cmpq(rax, Operand(rsp, 1 * kPointerSize)); // Compare to the array length.
1150 __ j(above_equal, loop_statement.break_label()); 1152 __ j(above_equal, loop_statement.break_label());
1151 1153
1152 // Get the current entry of the array into register rbx. 1154 // Get the current entry of the array into register rbx.
1153 __ movq(rbx, Operand(rsp, 2 * kPointerSize)); 1155 __ movp(rbx, Operand(rsp, 2 * kPointerSize));
1154 SmiIndex index = masm()->SmiToIndex(rax, rax, kPointerSizeLog2); 1156 SmiIndex index = masm()->SmiToIndex(rax, rax, kPointerSizeLog2);
1155 __ movq(rbx, FieldOperand(rbx, 1157 __ movp(rbx, FieldOperand(rbx,
1156 index.reg, 1158 index.reg,
1157 index.scale, 1159 index.scale,
1158 FixedArray::kHeaderSize)); 1160 FixedArray::kHeaderSize));
1159 1161
1160 // Get the expected map from the stack or a smi in the 1162 // Get the expected map from the stack or a smi in the
1161 // permanent slow case into register rdx. 1163 // permanent slow case into register rdx.
1162 __ movq(rdx, Operand(rsp, 3 * kPointerSize)); 1164 __ movp(rdx, Operand(rsp, 3 * kPointerSize));
1163 1165
1164 // Check if the expected map still matches that of the enumerable. 1166 // Check if the expected map still matches that of the enumerable.
1165 // If not, we may have to filter the key. 1167 // If not, we may have to filter the key.
1166 Label update_each; 1168 Label update_each;
1167 __ movq(rcx, Operand(rsp, 4 * kPointerSize)); 1169 __ movp(rcx, Operand(rsp, 4 * kPointerSize));
1168 __ cmpq(rdx, FieldOperand(rcx, HeapObject::kMapOffset)); 1170 __ cmpq(rdx, FieldOperand(rcx, HeapObject::kMapOffset));
1169 __ j(equal, &update_each, Label::kNear); 1171 __ j(equal, &update_each, Label::kNear);
1170 1172
1171 // For proxies, no filtering is done. 1173 // For proxies, no filtering is done.
1172 // TODO(rossberg): What if only a prototype is a proxy? Not specified yet. 1174 // TODO(rossberg): What if only a prototype is a proxy? Not specified yet.
1173 __ Cmp(rdx, Smi::FromInt(0)); 1175 __ Cmp(rdx, Smi::FromInt(0));
1174 __ j(equal, &update_each, Label::kNear); 1176 __ j(equal, &update_each, Label::kNear);
1175 1177
1176 // Convert the entry to a string or null if it isn't a property 1178 // Convert the entry to a string or null if it isn't a property
1177 // anymore. If the property has been removed while iterating, we 1179 // anymore. If the property has been removed while iterating, we
1178 // just skip it. 1180 // just skip it.
1179 __ push(rcx); // Enumerable. 1181 __ push(rcx); // Enumerable.
1180 __ push(rbx); // Current entry. 1182 __ push(rbx); // Current entry.
1181 __ InvokeBuiltin(Builtins::FILTER_KEY, CALL_FUNCTION); 1183 __ InvokeBuiltin(Builtins::FILTER_KEY, CALL_FUNCTION);
1182 __ Cmp(rax, Smi::FromInt(0)); 1184 __ Cmp(rax, Smi::FromInt(0));
1183 __ j(equal, loop_statement.continue_label()); 1185 __ j(equal, loop_statement.continue_label());
1184 __ movq(rbx, rax); 1186 __ movp(rbx, rax);
1185 1187
1186 // Update the 'each' property or variable from the possibly filtered 1188 // Update the 'each' property or variable from the possibly filtered
1187 // entry in register rbx. 1189 // entry in register rbx.
1188 __ bind(&update_each); 1190 __ bind(&update_each);
1189 __ movq(result_register(), rbx); 1191 __ movp(result_register(), rbx);
1190 // Perform the assignment as if via '='. 1192 // Perform the assignment as if via '='.
1191 { EffectContext context(this); 1193 { EffectContext context(this);
1192 EmitAssignment(stmt->each()); 1194 EmitAssignment(stmt->each());
1193 } 1195 }
1194 1196
1195 // Generate code for the body of the loop. 1197 // Generate code for the body of the loop.
1196 Visit(stmt->body()); 1198 Visit(stmt->body());
1197 1199
1198 // Generate code for going to the next element by incrementing the 1200 // Generate code for going to the next element by incrementing the
1199 // index (smi) stored on top of the stack. 1201 // index (smi) stored on top of the stack.
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after
1315 Scope* s = scope(); 1317 Scope* s = scope();
1316 while (s != NULL) { 1318 while (s != NULL) {
1317 if (s->num_heap_slots() > 0) { 1319 if (s->num_heap_slots() > 0) {
1318 if (s->calls_non_strict_eval()) { 1320 if (s->calls_non_strict_eval()) {
1319 // Check that extension is NULL. 1321 // Check that extension is NULL.
1320 __ cmpq(ContextOperand(context, Context::EXTENSION_INDEX), 1322 __ cmpq(ContextOperand(context, Context::EXTENSION_INDEX),
1321 Immediate(0)); 1323 Immediate(0));
1322 __ j(not_equal, slow); 1324 __ j(not_equal, slow);
1323 } 1325 }
1324 // Load next context in chain. 1326 // Load next context in chain.
1325 __ movq(temp, ContextOperand(context, Context::PREVIOUS_INDEX)); 1327 __ movp(temp, ContextOperand(context, Context::PREVIOUS_INDEX));
1326 // Walk the rest of the chain without clobbering rsi. 1328 // Walk the rest of the chain without clobbering rsi.
1327 context = temp; 1329 context = temp;
1328 } 1330 }
1329 // If no outer scope calls eval, we do not need to check more 1331 // If no outer scope calls eval, we do not need to check more
1330 // context extensions. If we have reached an eval scope, we check 1332 // context extensions. If we have reached an eval scope, we check
1331 // all extensions from this point. 1333 // all extensions from this point.
1332 if (!s->outer_scope_calls_non_strict_eval() || s->is_eval_scope()) break; 1334 if (!s->outer_scope_calls_non_strict_eval() || s->is_eval_scope()) break;
1333 s = s->outer_scope(); 1335 s = s->outer_scope();
1334 } 1336 }
1335 1337
1336 if (s != NULL && s->is_eval_scope()) { 1338 if (s != NULL && s->is_eval_scope()) {
1337 // Loop up the context chain. There is no frame effect so it is 1339 // Loop up the context chain. There is no frame effect so it is
1338 // safe to use raw labels here. 1340 // safe to use raw labels here.
1339 Label next, fast; 1341 Label next, fast;
1340 if (!context.is(temp)) { 1342 if (!context.is(temp)) {
1341 __ movq(temp, context); 1343 __ movp(temp, context);
1342 } 1344 }
1343 // Load map for comparison into register, outside loop. 1345 // Load map for comparison into register, outside loop.
1344 __ LoadRoot(kScratchRegister, Heap::kNativeContextMapRootIndex); 1346 __ LoadRoot(kScratchRegister, Heap::kNativeContextMapRootIndex);
1345 __ bind(&next); 1347 __ bind(&next);
1346 // Terminate at native context. 1348 // Terminate at native context.
1347 __ cmpq(kScratchRegister, FieldOperand(temp, HeapObject::kMapOffset)); 1349 __ cmpq(kScratchRegister, FieldOperand(temp, HeapObject::kMapOffset));
1348 __ j(equal, &fast, Label::kNear); 1350 __ j(equal, &fast, Label::kNear);
1349 // Check that extension is NULL. 1351 // Check that extension is NULL.
1350 __ cmpq(ContextOperand(temp, Context::EXTENSION_INDEX), Immediate(0)); 1352 __ cmpq(ContextOperand(temp, Context::EXTENSION_INDEX), Immediate(0));
1351 __ j(not_equal, slow); 1353 __ j(not_equal, slow);
1352 // Load next context in chain. 1354 // Load next context in chain.
1353 __ movq(temp, ContextOperand(temp, Context::PREVIOUS_INDEX)); 1355 __ movp(temp, ContextOperand(temp, Context::PREVIOUS_INDEX));
1354 __ jmp(&next); 1356 __ jmp(&next);
1355 __ bind(&fast); 1357 __ bind(&fast);
1356 } 1358 }
1357 1359
1358 // All extension objects were empty and it is safe to use a global 1360 // All extension objects were empty and it is safe to use a global
1359 // load IC call. 1361 // load IC call.
1360 __ movq(rax, GlobalObjectOperand()); 1362 __ movp(rax, GlobalObjectOperand());
1361 __ Move(rcx, var->name()); 1363 __ Move(rcx, var->name());
1362 ContextualMode mode = (typeof_state == INSIDE_TYPEOF) 1364 ContextualMode mode = (typeof_state == INSIDE_TYPEOF)
1363 ? NOT_CONTEXTUAL 1365 ? NOT_CONTEXTUAL
1364 : CONTEXTUAL; 1366 : CONTEXTUAL;
1365 CallLoadIC(mode); 1367 CallLoadIC(mode);
1366 } 1368 }
1367 1369
1368 1370
1369 MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(Variable* var, 1371 MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(Variable* var,
1370 Label* slow) { 1372 Label* slow) {
1371 ASSERT(var->IsContextSlot()); 1373 ASSERT(var->IsContextSlot());
1372 Register context = rsi; 1374 Register context = rsi;
1373 Register temp = rbx; 1375 Register temp = rbx;
1374 1376
1375 for (Scope* s = scope(); s != var->scope(); s = s->outer_scope()) { 1377 for (Scope* s = scope(); s != var->scope(); s = s->outer_scope()) {
1376 if (s->num_heap_slots() > 0) { 1378 if (s->num_heap_slots() > 0) {
1377 if (s->calls_non_strict_eval()) { 1379 if (s->calls_non_strict_eval()) {
1378 // Check that extension is NULL. 1380 // Check that extension is NULL.
1379 __ cmpq(ContextOperand(context, Context::EXTENSION_INDEX), 1381 __ cmpq(ContextOperand(context, Context::EXTENSION_INDEX),
1380 Immediate(0)); 1382 Immediate(0));
1381 __ j(not_equal, slow); 1383 __ j(not_equal, slow);
1382 } 1384 }
1383 __ movq(temp, ContextOperand(context, Context::PREVIOUS_INDEX)); 1385 __ movp(temp, ContextOperand(context, Context::PREVIOUS_INDEX));
1384 // Walk the rest of the chain without clobbering rsi. 1386 // Walk the rest of the chain without clobbering rsi.
1385 context = temp; 1387 context = temp;
1386 } 1388 }
1387 } 1389 }
1388 // Check that last extension is NULL. 1390 // Check that last extension is NULL.
1389 __ cmpq(ContextOperand(context, Context::EXTENSION_INDEX), Immediate(0)); 1391 __ cmpq(ContextOperand(context, Context::EXTENSION_INDEX), Immediate(0));
1390 __ j(not_equal, slow); 1392 __ j(not_equal, slow);
1391 1393
1392 // This function is used only for loads, not stores, so it's safe to 1394 // This function is used only for loads, not stores, so it's safe to
1393 // return an rsi-based operand (the write barrier cannot be allowed to 1395 // return an rsi-based operand (the write barrier cannot be allowed to
1394 // destroy the rsi register). 1396 // destroy the rsi register).
1395 return ContextOperand(context, var->index()); 1397 return ContextOperand(context, var->index());
1396 } 1398 }
1397 1399
1398 1400
1399 void FullCodeGenerator::EmitDynamicLookupFastCase(Variable* var, 1401 void FullCodeGenerator::EmitDynamicLookupFastCase(Variable* var,
1400 TypeofState typeof_state, 1402 TypeofState typeof_state,
1401 Label* slow, 1403 Label* slow,
1402 Label* done) { 1404 Label* done) {
1403 // Generate fast-case code for variables that might be shadowed by 1405 // Generate fast-case code for variables that might be shadowed by
1404 // eval-introduced variables. Eval is used a lot without 1406 // eval-introduced variables. Eval is used a lot without
1405 // introducing variables. In those cases, we do not want to 1407 // introducing variables. In those cases, we do not want to
1406 // perform a runtime call for all variables in the scope 1408 // perform a runtime call for all variables in the scope
1407 // containing the eval. 1409 // containing the eval.
1408 if (var->mode() == DYNAMIC_GLOBAL) { 1410 if (var->mode() == DYNAMIC_GLOBAL) {
1409 EmitLoadGlobalCheckExtensions(var, typeof_state, slow); 1411 EmitLoadGlobalCheckExtensions(var, typeof_state, slow);
1410 __ jmp(done); 1412 __ jmp(done);
1411 } else if (var->mode() == DYNAMIC_LOCAL) { 1413 } else if (var->mode() == DYNAMIC_LOCAL) {
1412 Variable* local = var->local_if_not_shadowed(); 1414 Variable* local = var->local_if_not_shadowed();
1413 __ movq(rax, ContextSlotOperandCheckExtensions(local, slow)); 1415 __ movp(rax, ContextSlotOperandCheckExtensions(local, slow));
1414 if (local->mode() == LET || 1416 if (local->mode() == LET ||
1415 local->mode() == CONST || 1417 local->mode() == CONST ||
1416 local->mode() == CONST_HARMONY) { 1418 local->mode() == CONST_HARMONY) {
1417 __ CompareRoot(rax, Heap::kTheHoleValueRootIndex); 1419 __ CompareRoot(rax, Heap::kTheHoleValueRootIndex);
1418 __ j(not_equal, done); 1420 __ j(not_equal, done);
1419 if (local->mode() == CONST) { 1421 if (local->mode() == CONST) {
1420 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); 1422 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
1421 } else { // LET || CONST_HARMONY 1423 } else { // LET || CONST_HARMONY
1422 __ Push(var->name()); 1424 __ Push(var->name());
1423 __ CallRuntime(Runtime::kThrowReferenceError, 1); 1425 __ CallRuntime(Runtime::kThrowReferenceError, 1);
(...skipping 10 matching lines...) Expand all
1434 Variable* var = proxy->var(); 1436 Variable* var = proxy->var();
1435 1437
1436 // Three cases: global variables, lookup variables, and all other types of 1438 // Three cases: global variables, lookup variables, and all other types of
1437 // variables. 1439 // variables.
1438 switch (var->location()) { 1440 switch (var->location()) {
1439 case Variable::UNALLOCATED: { 1441 case Variable::UNALLOCATED: {
1440 Comment cmnt(masm_, "Global variable"); 1442 Comment cmnt(masm_, "Global variable");
1441 // Use inline caching. Variable name is passed in rcx and the global 1443 // Use inline caching. Variable name is passed in rcx and the global
1442 // object on the stack. 1444 // object on the stack.
1443 __ Move(rcx, var->name()); 1445 __ Move(rcx, var->name());
1444 __ movq(rax, GlobalObjectOperand()); 1446 __ movp(rax, GlobalObjectOperand());
1445 CallLoadIC(CONTEXTUAL); 1447 CallLoadIC(CONTEXTUAL);
1446 context()->Plug(rax); 1448 context()->Plug(rax);
1447 break; 1449 break;
1448 } 1450 }
1449 1451
1450 case Variable::PARAMETER: 1452 case Variable::PARAMETER:
1451 case Variable::LOCAL: 1453 case Variable::LOCAL:
1452 case Variable::CONTEXT: { 1454 case Variable::CONTEXT: {
1453 Comment cmnt(masm_, var->IsContextSlot() ? "Context slot" : "Stack slot"); 1455 Comment cmnt(masm_, var->IsContextSlot() ? "Context slot" : "Stack slot");
1454 if (var->binding_needs_init()) { 1456 if (var->binding_needs_init()) {
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
1530 1532
1531 1533
1532 void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { 1534 void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
1533 Comment cmnt(masm_, "[ RegExpLiteral"); 1535 Comment cmnt(masm_, "[ RegExpLiteral");
1534 Label materialized; 1536 Label materialized;
1535 // Registers will be used as follows: 1537 // Registers will be used as follows:
1536 // rdi = JS function. 1538 // rdi = JS function.
1537 // rcx = literals array. 1539 // rcx = literals array.
1538 // rbx = regexp literal. 1540 // rbx = regexp literal.
1539 // rax = regexp literal clone. 1541 // rax = regexp literal clone.
1540 __ movq(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); 1542 __ movp(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
1541 __ movq(rcx, FieldOperand(rdi, JSFunction::kLiteralsOffset)); 1543 __ movp(rcx, FieldOperand(rdi, JSFunction::kLiteralsOffset));
1542 int literal_offset = 1544 int literal_offset =
1543 FixedArray::kHeaderSize + expr->literal_index() * kPointerSize; 1545 FixedArray::kHeaderSize + expr->literal_index() * kPointerSize;
1544 __ movq(rbx, FieldOperand(rcx, literal_offset)); 1546 __ movp(rbx, FieldOperand(rcx, literal_offset));
1545 __ CompareRoot(rbx, Heap::kUndefinedValueRootIndex); 1547 __ CompareRoot(rbx, Heap::kUndefinedValueRootIndex);
1546 __ j(not_equal, &materialized, Label::kNear); 1548 __ j(not_equal, &materialized, Label::kNear);
1547 1549
1548 // Create regexp literal using runtime function 1550 // Create regexp literal using runtime function
1549 // Result will be in rax. 1551 // Result will be in rax.
1550 __ push(rcx); 1552 __ push(rcx);
1551 __ Push(Smi::FromInt(expr->literal_index())); 1553 __ Push(Smi::FromInt(expr->literal_index()));
1552 __ Push(expr->pattern()); 1554 __ Push(expr->pattern());
1553 __ Push(expr->flags()); 1555 __ Push(expr->flags());
1554 __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4); 1556 __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4);
1555 __ movq(rbx, rax); 1557 __ movp(rbx, rax);
1556 1558
1557 __ bind(&materialized); 1559 __ bind(&materialized);
1558 int size = JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kPointerSize; 1560 int size = JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kPointerSize;
1559 Label allocated, runtime_allocate; 1561 Label allocated, runtime_allocate;
1560 __ Allocate(size, rax, rcx, rdx, &runtime_allocate, TAG_OBJECT); 1562 __ Allocate(size, rax, rcx, rdx, &runtime_allocate, TAG_OBJECT);
1561 __ jmp(&allocated); 1563 __ jmp(&allocated);
1562 1564
1563 __ bind(&runtime_allocate); 1565 __ bind(&runtime_allocate);
1564 __ push(rbx); 1566 __ push(rbx);
1565 __ Push(Smi::FromInt(size)); 1567 __ Push(Smi::FromInt(size));
1566 __ CallRuntime(Runtime::kAllocateInNewSpace, 1); 1568 __ CallRuntime(Runtime::kAllocateInNewSpace, 1);
1567 __ pop(rbx); 1569 __ pop(rbx);
1568 1570
1569 __ bind(&allocated); 1571 __ bind(&allocated);
1570 // Copy the content into the newly allocated memory. 1572 // Copy the content into the newly allocated memory.
1571 // (Unroll copy loop once for better throughput). 1573 // (Unroll copy loop once for better throughput).
1572 for (int i = 0; i < size - kPointerSize; i += 2 * kPointerSize) { 1574 for (int i = 0; i < size - kPointerSize; i += 2 * kPointerSize) {
1573 __ movq(rdx, FieldOperand(rbx, i)); 1575 __ movp(rdx, FieldOperand(rbx, i));
1574 __ movq(rcx, FieldOperand(rbx, i + kPointerSize)); 1576 __ movp(rcx, FieldOperand(rbx, i + kPointerSize));
1575 __ movq(FieldOperand(rax, i), rdx); 1577 __ movp(FieldOperand(rax, i), rdx);
1576 __ movq(FieldOperand(rax, i + kPointerSize), rcx); 1578 __ movp(FieldOperand(rax, i + kPointerSize), rcx);
1577 } 1579 }
1578 if ((size % (2 * kPointerSize)) != 0) { 1580 if ((size % (2 * kPointerSize)) != 0) {
1579 __ movq(rdx, FieldOperand(rbx, size - kPointerSize)); 1581 __ movp(rdx, FieldOperand(rbx, size - kPointerSize));
1580 __ movq(FieldOperand(rax, size - kPointerSize), rdx); 1582 __ movp(FieldOperand(rax, size - kPointerSize), rdx);
1581 } 1583 }
1582 context()->Plug(rax); 1584 context()->Plug(rax);
1583 } 1585 }
1584 1586
1585 1587
1586 void FullCodeGenerator::EmitAccessor(Expression* expression) { 1588 void FullCodeGenerator::EmitAccessor(Expression* expression) {
1587 if (expression == NULL) { 1589 if (expression == NULL) {
1588 __ PushRoot(Heap::kNullValueRootIndex); 1590 __ PushRoot(Heap::kNullValueRootIndex);
1589 } else { 1591 } else {
1590 VisitForStackValue(expression); 1592 VisitForStackValue(expression);
(...skipping 10 matching lines...) Expand all
1601 ? ObjectLiteral::kFastElements 1603 ? ObjectLiteral::kFastElements
1602 : ObjectLiteral::kNoFlags; 1604 : ObjectLiteral::kNoFlags;
1603 flags |= expr->has_function() 1605 flags |= expr->has_function()
1604 ? ObjectLiteral::kHasFunction 1606 ? ObjectLiteral::kHasFunction
1605 : ObjectLiteral::kNoFlags; 1607 : ObjectLiteral::kNoFlags;
1606 int properties_count = constant_properties->length() / 2; 1608 int properties_count = constant_properties->length() / 2;
1607 if ((FLAG_track_double_fields && expr->may_store_doubles()) || 1609 if ((FLAG_track_double_fields && expr->may_store_doubles()) ||
1608 expr->depth() > 1 || Serializer::enabled() || 1610 expr->depth() > 1 || Serializer::enabled() ||
1609 flags != ObjectLiteral::kFastElements || 1611 flags != ObjectLiteral::kFastElements ||
1610 properties_count > FastCloneShallowObjectStub::kMaximumClonedProperties) { 1612 properties_count > FastCloneShallowObjectStub::kMaximumClonedProperties) {
1611 __ movq(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); 1613 __ movp(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
1612 __ push(FieldOperand(rdi, JSFunction::kLiteralsOffset)); 1614 __ push(FieldOperand(rdi, JSFunction::kLiteralsOffset));
1613 __ Push(Smi::FromInt(expr->literal_index())); 1615 __ Push(Smi::FromInt(expr->literal_index()));
1614 __ Push(constant_properties); 1616 __ Push(constant_properties);
1615 __ Push(Smi::FromInt(flags)); 1617 __ Push(Smi::FromInt(flags));
1616 __ CallRuntime(Runtime::kCreateObjectLiteral, 4); 1618 __ CallRuntime(Runtime::kCreateObjectLiteral, 4);
1617 } else { 1619 } else {
1618 __ movq(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); 1620 __ movp(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
1619 __ movq(rax, FieldOperand(rdi, JSFunction::kLiteralsOffset)); 1621 __ movp(rax, FieldOperand(rdi, JSFunction::kLiteralsOffset));
1620 __ Move(rbx, Smi::FromInt(expr->literal_index())); 1622 __ Move(rbx, Smi::FromInt(expr->literal_index()));
1621 __ Move(rcx, constant_properties); 1623 __ Move(rcx, constant_properties);
1622 __ Move(rdx, Smi::FromInt(flags)); 1624 __ Move(rdx, Smi::FromInt(flags));
1623 FastCloneShallowObjectStub stub(properties_count); 1625 FastCloneShallowObjectStub stub(properties_count);
1624 __ CallStub(&stub); 1626 __ CallStub(&stub);
1625 } 1627 }
1626 1628
1627 // If result_saved is true the result is on top of the stack. If 1629 // If result_saved is true the result is on top of the stack. If
1628 // result_saved is false the result is in rax. 1630 // result_saved is false the result is in rax.
1629 bool result_saved = false; 1631 bool result_saved = false;
(...skipping 18 matching lines...) Expand all
1648 case ObjectLiteral::Property::CONSTANT: 1650 case ObjectLiteral::Property::CONSTANT:
1649 UNREACHABLE(); 1651 UNREACHABLE();
1650 case ObjectLiteral::Property::MATERIALIZED_LITERAL: 1652 case ObjectLiteral::Property::MATERIALIZED_LITERAL:
1651 ASSERT(!CompileTimeValue::IsCompileTimeValue(value)); 1653 ASSERT(!CompileTimeValue::IsCompileTimeValue(value));
1652 // Fall through. 1654 // Fall through.
1653 case ObjectLiteral::Property::COMPUTED: 1655 case ObjectLiteral::Property::COMPUTED:
1654 if (key->value()->IsInternalizedString()) { 1656 if (key->value()->IsInternalizedString()) {
1655 if (property->emit_store()) { 1657 if (property->emit_store()) {
1656 VisitForAccumulatorValue(value); 1658 VisitForAccumulatorValue(value);
1657 __ Move(rcx, key->value()); 1659 __ Move(rcx, key->value());
1658 __ movq(rdx, Operand(rsp, 0)); 1660 __ movp(rdx, Operand(rsp, 0));
1659 CallStoreIC(NOT_CONTEXTUAL, key->LiteralFeedbackId()); 1661 CallStoreIC(NOT_CONTEXTUAL, key->LiteralFeedbackId());
1660 PrepareForBailoutForId(key->id(), NO_REGISTERS); 1662 PrepareForBailoutForId(key->id(), NO_REGISTERS);
1661 } else { 1663 } else {
1662 VisitForEffect(value); 1664 VisitForEffect(value);
1663 } 1665 }
1664 break; 1666 break;
1665 } 1667 }
1666 __ push(Operand(rsp, 0)); // Duplicate receiver. 1668 __ push(Operand(rsp, 0)); // Duplicate receiver.
1667 VisitForStackValue(key); 1669 VisitForStackValue(key);
1668 VisitForStackValue(value); 1670 VisitForStackValue(value);
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
1743 // we can turn it off if we don't have anywhere else to transition to. 1745 // we can turn it off if we don't have anywhere else to transition to.
1744 allocation_site_mode = DONT_TRACK_ALLOCATION_SITE; 1746 allocation_site_mode = DONT_TRACK_ALLOCATION_SITE;
1745 } 1747 }
1746 1748
1747 Heap* heap = isolate()->heap(); 1749 Heap* heap = isolate()->heap();
1748 if (has_constant_fast_elements && 1750 if (has_constant_fast_elements &&
1749 constant_elements_values->map() == heap->fixed_cow_array_map()) { 1751 constant_elements_values->map() == heap->fixed_cow_array_map()) {
1750 // If the elements are already FAST_*_ELEMENTS, the boilerplate cannot 1752 // If the elements are already FAST_*_ELEMENTS, the boilerplate cannot
1751 // change, so it's possible to specialize the stub in advance. 1753 // change, so it's possible to specialize the stub in advance.
1752 __ IncrementCounter(isolate()->counters()->cow_arrays_created_stub(), 1); 1754 __ IncrementCounter(isolate()->counters()->cow_arrays_created_stub(), 1);
1753 __ movq(rbx, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); 1755 __ movp(rbx, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
1754 __ movq(rax, FieldOperand(rbx, JSFunction::kLiteralsOffset)); 1756 __ movp(rax, FieldOperand(rbx, JSFunction::kLiteralsOffset));
1755 __ Move(rbx, Smi::FromInt(expr->literal_index())); 1757 __ Move(rbx, Smi::FromInt(expr->literal_index()));
1756 __ Move(rcx, constant_elements); 1758 __ Move(rcx, constant_elements);
1757 FastCloneShallowArrayStub stub( 1759 FastCloneShallowArrayStub stub(
1758 FastCloneShallowArrayStub::COPY_ON_WRITE_ELEMENTS, 1760 FastCloneShallowArrayStub::COPY_ON_WRITE_ELEMENTS,
1759 allocation_site_mode, 1761 allocation_site_mode,
1760 length); 1762 length);
1761 __ CallStub(&stub); 1763 __ CallStub(&stub);
1762 } else if (expr->depth() > 1 || Serializer::enabled() || 1764 } else if (expr->depth() > 1 || Serializer::enabled() ||
1763 length > FastCloneShallowArrayStub::kMaximumClonedLength) { 1765 length > FastCloneShallowArrayStub::kMaximumClonedLength) {
1764 __ movq(rbx, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); 1766 __ movp(rbx, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
1765 __ push(FieldOperand(rbx, JSFunction::kLiteralsOffset)); 1767 __ push(FieldOperand(rbx, JSFunction::kLiteralsOffset));
1766 __ Push(Smi::FromInt(expr->literal_index())); 1768 __ Push(Smi::FromInt(expr->literal_index()));
1767 __ Push(constant_elements); 1769 __ Push(constant_elements);
1768 __ Push(Smi::FromInt(flags)); 1770 __ Push(Smi::FromInt(flags));
1769 __ CallRuntime(Runtime::kCreateArrayLiteral, 4); 1771 __ CallRuntime(Runtime::kCreateArrayLiteral, 4);
1770 } else { 1772 } else {
1771 ASSERT(IsFastSmiOrObjectElementsKind(constant_elements_kind) || 1773 ASSERT(IsFastSmiOrObjectElementsKind(constant_elements_kind) ||
1772 FLAG_smi_only_arrays); 1774 FLAG_smi_only_arrays);
1773 FastCloneShallowArrayStub::Mode mode = 1775 FastCloneShallowArrayStub::Mode mode =
1774 FastCloneShallowArrayStub::CLONE_ANY_ELEMENTS; 1776 FastCloneShallowArrayStub::CLONE_ANY_ELEMENTS;
1775 1777
1776 // If the elements are already FAST_*_ELEMENTS, the boilerplate cannot 1778 // If the elements are already FAST_*_ELEMENTS, the boilerplate cannot
1777 // change, so it's possible to specialize the stub in advance. 1779 // change, so it's possible to specialize the stub in advance.
1778 if (has_constant_fast_elements) { 1780 if (has_constant_fast_elements) {
1779 mode = FastCloneShallowArrayStub::CLONE_ELEMENTS; 1781 mode = FastCloneShallowArrayStub::CLONE_ELEMENTS;
1780 } 1782 }
1781 1783
1782 __ movq(rbx, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); 1784 __ movp(rbx, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
1783 __ movq(rax, FieldOperand(rbx, JSFunction::kLiteralsOffset)); 1785 __ movp(rax, FieldOperand(rbx, JSFunction::kLiteralsOffset));
1784 __ Move(rbx, Smi::FromInt(expr->literal_index())); 1786 __ Move(rbx, Smi::FromInt(expr->literal_index()));
1785 __ Move(rcx, constant_elements); 1787 __ Move(rcx, constant_elements);
1786 FastCloneShallowArrayStub stub(mode, allocation_site_mode, length); 1788 FastCloneShallowArrayStub stub(mode, allocation_site_mode, length);
1787 __ CallStub(&stub); 1789 __ CallStub(&stub);
1788 } 1790 }
1789 1791
1790 bool result_saved = false; // Is the result saved to the stack? 1792 bool result_saved = false; // Is the result saved to the stack?
1791 1793
1792 // Emit code to evaluate all the non-constant subexpressions and to store 1794 // Emit code to evaluate all the non-constant subexpressions and to store
1793 // them into the newly cloned array. 1795 // them into the newly cloned array.
1794 for (int i = 0; i < length; i++) { 1796 for (int i = 0; i < length; i++) {
1795 Expression* subexpr = subexprs->at(i); 1797 Expression* subexpr = subexprs->at(i);
1796 // If the subexpression is a literal or a simple materialized literal it 1798 // If the subexpression is a literal or a simple materialized literal it
1797 // is already set in the cloned array. 1799 // is already set in the cloned array.
1798 if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue; 1800 if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue;
1799 1801
1800 if (!result_saved) { 1802 if (!result_saved) {
1801 __ push(rax); // array literal 1803 __ push(rax); // array literal
1802 __ Push(Smi::FromInt(expr->literal_index())); 1804 __ Push(Smi::FromInt(expr->literal_index()));
1803 result_saved = true; 1805 result_saved = true;
1804 } 1806 }
1805 VisitForAccumulatorValue(subexpr); 1807 VisitForAccumulatorValue(subexpr);
1806 1808
1807 if (IsFastObjectElementsKind(constant_elements_kind)) { 1809 if (IsFastObjectElementsKind(constant_elements_kind)) {
1808 // Fast-case array literal with ElementsKind of FAST_*_ELEMENTS, they 1810 // Fast-case array literal with ElementsKind of FAST_*_ELEMENTS, they
1809 // cannot transition and don't need to call the runtime stub. 1811 // cannot transition and don't need to call the runtime stub.
1810 int offset = FixedArray::kHeaderSize + (i * kPointerSize); 1812 int offset = FixedArray::kHeaderSize + (i * kPointerSize);
1811 __ movq(rbx, Operand(rsp, kPointerSize)); // Copy of array literal. 1813 __ movp(rbx, Operand(rsp, kPointerSize)); // Copy of array literal.
1812 __ movq(rbx, FieldOperand(rbx, JSObject::kElementsOffset)); 1814 __ movp(rbx, FieldOperand(rbx, JSObject::kElementsOffset));
1813 // Store the subexpression value in the array's elements. 1815 // Store the subexpression value in the array's elements.
1814 __ movq(FieldOperand(rbx, offset), result_register()); 1816 __ movp(FieldOperand(rbx, offset), result_register());
1815 // Update the write barrier for the array store. 1817 // Update the write barrier for the array store.
1816 __ RecordWriteField(rbx, offset, result_register(), rcx, 1818 __ RecordWriteField(rbx, offset, result_register(), rcx,
1817 kDontSaveFPRegs, 1819 kDontSaveFPRegs,
1818 EMIT_REMEMBERED_SET, 1820 EMIT_REMEMBERED_SET,
1819 INLINE_SMI_CHECK); 1821 INLINE_SMI_CHECK);
1820 } else { 1822 } else {
1821 // Store the subexpression value in the array's elements. 1823 // Store the subexpression value in the array's elements.
1822 __ Move(rcx, Smi::FromInt(i)); 1824 __ Move(rcx, Smi::FromInt(i));
1823 StoreArrayLiteralElementStub stub; 1825 StoreArrayLiteralElementStub stub;
1824 __ CallStub(&stub); 1826 __ CallStub(&stub);
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
1867 VisitForAccumulatorValue(property->obj()); 1869 VisitForAccumulatorValue(property->obj());
1868 __ push(result_register()); 1870 __ push(result_register());
1869 } else { 1871 } else {
1870 VisitForStackValue(property->obj()); 1872 VisitForStackValue(property->obj());
1871 } 1873 }
1872 break; 1874 break;
1873 case KEYED_PROPERTY: { 1875 case KEYED_PROPERTY: {
1874 if (expr->is_compound()) { 1876 if (expr->is_compound()) {
1875 VisitForStackValue(property->obj()); 1877 VisitForStackValue(property->obj());
1876 VisitForAccumulatorValue(property->key()); 1878 VisitForAccumulatorValue(property->key());
1877 __ movq(rdx, Operand(rsp, 0)); 1879 __ movp(rdx, Operand(rsp, 0));
1878 __ push(rax); 1880 __ push(rax);
1879 } else { 1881 } else {
1880 VisitForStackValue(property->obj()); 1882 VisitForStackValue(property->obj());
1881 VisitForStackValue(property->key()); 1883 VisitForStackValue(property->key());
1882 } 1884 }
1883 break; 1885 break;
1884 } 1886 }
1885 } 1887 }
1886 1888
1887 // For compound assignments we need another deoptimization point after the 1889 // For compound assignments we need another deoptimization point after the
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
1967 __ jmp(&suspend); 1969 __ jmp(&suspend);
1968 1970
1969 __ bind(&continuation); 1971 __ bind(&continuation);
1970 __ jmp(&resume); 1972 __ jmp(&resume);
1971 1973
1972 __ bind(&suspend); 1974 __ bind(&suspend);
1973 VisitForAccumulatorValue(expr->generator_object()); 1975 VisitForAccumulatorValue(expr->generator_object());
1974 ASSERT(continuation.pos() > 0 && Smi::IsValid(continuation.pos())); 1976 ASSERT(continuation.pos() > 0 && Smi::IsValid(continuation.pos()));
1975 __ Move(FieldOperand(rax, JSGeneratorObject::kContinuationOffset), 1977 __ Move(FieldOperand(rax, JSGeneratorObject::kContinuationOffset),
1976 Smi::FromInt(continuation.pos())); 1978 Smi::FromInt(continuation.pos()));
1977 __ movq(FieldOperand(rax, JSGeneratorObject::kContextOffset), rsi); 1979 __ movp(FieldOperand(rax, JSGeneratorObject::kContextOffset), rsi);
1978 __ movq(rcx, rsi); 1980 __ movp(rcx, rsi);
1979 __ RecordWriteField(rax, JSGeneratorObject::kContextOffset, rcx, rdx, 1981 __ RecordWriteField(rax, JSGeneratorObject::kContextOffset, rcx, rdx,
1980 kDontSaveFPRegs); 1982 kDontSaveFPRegs);
1981 __ lea(rbx, Operand(rbp, StandardFrameConstants::kExpressionsOffset)); 1983 __ lea(rbx, Operand(rbp, StandardFrameConstants::kExpressionsOffset));
1982 __ cmpq(rsp, rbx); 1984 __ cmpq(rsp, rbx);
1983 __ j(equal, &post_runtime); 1985 __ j(equal, &post_runtime);
1984 __ push(rax); // generator object 1986 __ push(rax); // generator object
1985 __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1); 1987 __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1);
1986 __ movq(context_register(), 1988 __ movp(context_register(),
1987 Operand(rbp, StandardFrameConstants::kContextOffset)); 1989 Operand(rbp, StandardFrameConstants::kContextOffset));
1988 __ bind(&post_runtime); 1990 __ bind(&post_runtime);
1989 1991
1990 __ pop(result_register()); 1992 __ pop(result_register());
1991 EmitReturnSequence(); 1993 EmitReturnSequence();
1992 1994
1993 __ bind(&resume); 1995 __ bind(&resume);
1994 context()->Plug(result_register()); 1996 context()->Plug(result_register());
1995 break; 1997 break;
1996 } 1998 }
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
2035 __ bind(&l_try); 2037 __ bind(&l_try);
2036 __ pop(rax); // result 2038 __ pop(rax); // result
2037 __ PushTryHandler(StackHandler::CATCH, expr->index()); 2039 __ PushTryHandler(StackHandler::CATCH, expr->index());
2038 const int handler_size = StackHandlerConstants::kSize; 2040 const int handler_size = StackHandlerConstants::kSize;
2039 __ push(rax); // result 2041 __ push(rax); // result
2040 __ jmp(&l_suspend); 2042 __ jmp(&l_suspend);
2041 __ bind(&l_continuation); 2043 __ bind(&l_continuation);
2042 __ jmp(&l_resume); 2044 __ jmp(&l_resume);
2043 __ bind(&l_suspend); 2045 __ bind(&l_suspend);
2044 const int generator_object_depth = kPointerSize + handler_size; 2046 const int generator_object_depth = kPointerSize + handler_size;
2045 __ movq(rax, Operand(rsp, generator_object_depth)); 2047 __ movp(rax, Operand(rsp, generator_object_depth));
2046 __ push(rax); // g 2048 __ push(rax); // g
2047 ASSERT(l_continuation.pos() > 0 && Smi::IsValid(l_continuation.pos())); 2049 ASSERT(l_continuation.pos() > 0 && Smi::IsValid(l_continuation.pos()));
2048 __ Move(FieldOperand(rax, JSGeneratorObject::kContinuationOffset), 2050 __ Move(FieldOperand(rax, JSGeneratorObject::kContinuationOffset),
2049 Smi::FromInt(l_continuation.pos())); 2051 Smi::FromInt(l_continuation.pos()));
2050 __ movq(FieldOperand(rax, JSGeneratorObject::kContextOffset), rsi); 2052 __ movp(FieldOperand(rax, JSGeneratorObject::kContextOffset), rsi);
2051 __ movq(rcx, rsi); 2053 __ movp(rcx, rsi);
2052 __ RecordWriteField(rax, JSGeneratorObject::kContextOffset, rcx, rdx, 2054 __ RecordWriteField(rax, JSGeneratorObject::kContextOffset, rcx, rdx,
2053 kDontSaveFPRegs); 2055 kDontSaveFPRegs);
2054 __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1); 2056 __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1);
2055 __ movq(context_register(), 2057 __ movp(context_register(),
2056 Operand(rbp, StandardFrameConstants::kContextOffset)); 2058 Operand(rbp, StandardFrameConstants::kContextOffset));
2057 __ pop(rax); // result 2059 __ pop(rax); // result
2058 EmitReturnSequence(); 2060 EmitReturnSequence();
2059 __ bind(&l_resume); // received in rax 2061 __ bind(&l_resume); // received in rax
2060 __ PopTryHandler(); 2062 __ PopTryHandler();
2061 2063
2062 // receiver = iter; f = 'next'; arg = received; 2064 // receiver = iter; f = 'next'; arg = received;
2063 __ bind(&l_next); 2065 __ bind(&l_next);
2064 __ LoadRoot(rcx, Heap::knext_stringRootIndex); // "next" 2066 __ LoadRoot(rcx, Heap::knext_stringRootIndex); // "next"
2065 __ push(rcx); 2067 __ push(rcx);
2066 __ push(Operand(rsp, 2 * kPointerSize)); // iter 2068 __ push(Operand(rsp, 2 * kPointerSize)); // iter
2067 __ push(rax); // received 2069 __ push(rax); // received
2068 2070
2069 // result = receiver[f](arg); 2071 // result = receiver[f](arg);
2070 __ bind(&l_call); 2072 __ bind(&l_call);
2071 Handle<Code> ic = isolate()->stub_cache()->ComputeKeyedCallInitialize(1); 2073 Handle<Code> ic = isolate()->stub_cache()->ComputeKeyedCallInitialize(1);
2072 CallIC(ic); 2074 CallIC(ic);
2073 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 2075 __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
2074 __ Drop(1); // The key is still on the stack; drop it. 2076 __ Drop(1); // The key is still on the stack; drop it.
2075 2077
2076 // if (!result.done) goto l_try; 2078 // if (!result.done) goto l_try;
2077 __ bind(&l_loop); 2079 __ bind(&l_loop);
2078 __ push(rax); // save result 2080 __ push(rax); // save result
2079 __ LoadRoot(rcx, Heap::kdone_stringRootIndex); // "done" 2081 __ LoadRoot(rcx, Heap::kdone_stringRootIndex); // "done"
2080 CallLoadIC(NOT_CONTEXTUAL); // result.done in rax 2082 CallLoadIC(NOT_CONTEXTUAL); // result.done in rax
2081 Handle<Code> bool_ic = ToBooleanStub::GetUninitialized(isolate()); 2083 Handle<Code> bool_ic = ToBooleanStub::GetUninitialized(isolate());
2082 CallIC(bool_ic); 2084 CallIC(bool_ic);
2083 __ testq(result_register(), result_register()); 2085 __ testq(result_register(), result_register());
(...skipping 24 matching lines...) Expand all
2108 // Check generator state. 2110 // Check generator state.
2109 Label wrong_state, closed_state, done; 2111 Label wrong_state, closed_state, done;
2110 STATIC_ASSERT(JSGeneratorObject::kGeneratorExecuting < 0); 2112 STATIC_ASSERT(JSGeneratorObject::kGeneratorExecuting < 0);
2111 STATIC_ASSERT(JSGeneratorObject::kGeneratorClosed == 0); 2113 STATIC_ASSERT(JSGeneratorObject::kGeneratorClosed == 0);
2112 __ SmiCompare(FieldOperand(rbx, JSGeneratorObject::kContinuationOffset), 2114 __ SmiCompare(FieldOperand(rbx, JSGeneratorObject::kContinuationOffset),
2113 Smi::FromInt(0)); 2115 Smi::FromInt(0));
2114 __ j(equal, &closed_state); 2116 __ j(equal, &closed_state);
2115 __ j(less, &wrong_state); 2117 __ j(less, &wrong_state);
2116 2118
2117 // Load suspended function and context. 2119 // Load suspended function and context.
2118 __ movq(rsi, FieldOperand(rbx, JSGeneratorObject::kContextOffset)); 2120 __ movp(rsi, FieldOperand(rbx, JSGeneratorObject::kContextOffset));
2119 __ movq(rdi, FieldOperand(rbx, JSGeneratorObject::kFunctionOffset)); 2121 __ movp(rdi, FieldOperand(rbx, JSGeneratorObject::kFunctionOffset));
2120 2122
2121 // Push receiver. 2123 // Push receiver.
2122 __ push(FieldOperand(rbx, JSGeneratorObject::kReceiverOffset)); 2124 __ push(FieldOperand(rbx, JSGeneratorObject::kReceiverOffset));
2123 2125
2124 // Push holes for arguments to generator function. 2126 // Push holes for arguments to generator function.
2125 __ movq(rdx, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset)); 2127 __ movp(rdx, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset));
2126 __ movsxlq(rdx, 2128 __ movsxlq(rdx,
2127 FieldOperand(rdx, 2129 FieldOperand(rdx,
2128 SharedFunctionInfo::kFormalParameterCountOffset)); 2130 SharedFunctionInfo::kFormalParameterCountOffset));
2129 __ LoadRoot(rcx, Heap::kTheHoleValueRootIndex); 2131 __ LoadRoot(rcx, Heap::kTheHoleValueRootIndex);
2130 Label push_argument_holes, push_frame; 2132 Label push_argument_holes, push_frame;
2131 __ bind(&push_argument_holes); 2133 __ bind(&push_argument_holes);
2132 __ subq(rdx, Immediate(1)); 2134 __ subq(rdx, Immediate(1));
2133 __ j(carry, &push_frame); 2135 __ j(carry, &push_frame);
2134 __ push(rcx); 2136 __ push(rcx);
2135 __ jmp(&push_argument_holes); 2137 __ jmp(&push_argument_holes);
2136 2138
2137 // Enter a new JavaScript frame, and initialize its slots as they were when 2139 // Enter a new JavaScript frame, and initialize its slots as they were when
2138 // the generator was suspended. 2140 // the generator was suspended.
2139 Label resume_frame; 2141 Label resume_frame;
2140 __ bind(&push_frame); 2142 __ bind(&push_frame);
2141 __ call(&resume_frame); 2143 __ call(&resume_frame);
2142 __ jmp(&done); 2144 __ jmp(&done);
2143 __ bind(&resume_frame); 2145 __ bind(&resume_frame);
2144 __ push(rbp); // Caller's frame pointer. 2146 __ push(rbp); // Caller's frame pointer.
2145 __ movq(rbp, rsp); 2147 __ movp(rbp, rsp);
2146 __ push(rsi); // Callee's context. 2148 __ push(rsi); // Callee's context.
2147 __ push(rdi); // Callee's JS Function. 2149 __ push(rdi); // Callee's JS Function.
2148 2150
2149 // Load the operand stack size. 2151 // Load the operand stack size.
2150 __ movq(rdx, FieldOperand(rbx, JSGeneratorObject::kOperandStackOffset)); 2152 __ movp(rdx, FieldOperand(rbx, JSGeneratorObject::kOperandStackOffset));
2151 __ movq(rdx, FieldOperand(rdx, FixedArray::kLengthOffset)); 2153 __ movp(rdx, FieldOperand(rdx, FixedArray::kLengthOffset));
2152 __ SmiToInteger32(rdx, rdx); 2154 __ SmiToInteger32(rdx, rdx);
2153 2155
2154 // If we are sending a value and there is no operand stack, we can jump back 2156 // If we are sending a value and there is no operand stack, we can jump back
2155 // in directly. 2157 // in directly.
2156 if (resume_mode == JSGeneratorObject::NEXT) { 2158 if (resume_mode == JSGeneratorObject::NEXT) {
2157 Label slow_resume; 2159 Label slow_resume;
2158 __ cmpq(rdx, Immediate(0)); 2160 __ cmpq(rdx, Immediate(0));
2159 __ j(not_zero, &slow_resume); 2161 __ j(not_zero, &slow_resume);
2160 __ movq(rdx, FieldOperand(rdi, JSFunction::kCodeEntryOffset)); 2162 __ movp(rdx, FieldOperand(rdi, JSFunction::kCodeEntryOffset));
2161 __ SmiToInteger64(rcx, 2163 __ SmiToInteger64(rcx,
2162 FieldOperand(rbx, JSGeneratorObject::kContinuationOffset)); 2164 FieldOperand(rbx, JSGeneratorObject::kContinuationOffset));
2163 __ addq(rdx, rcx); 2165 __ addq(rdx, rcx);
2164 __ Move(FieldOperand(rbx, JSGeneratorObject::kContinuationOffset), 2166 __ Move(FieldOperand(rbx, JSGeneratorObject::kContinuationOffset),
2165 Smi::FromInt(JSGeneratorObject::kGeneratorExecuting)); 2167 Smi::FromInt(JSGeneratorObject::kGeneratorExecuting));
2166 __ jmp(rdx); 2168 __ jmp(rdx);
2167 __ bind(&slow_resume); 2169 __ bind(&slow_resume);
2168 } 2170 }
2169 2171
2170 // Otherwise, we push holes for the operand stack and call the runtime to fix 2172 // Otherwise, we push holes for the operand stack and call the runtime to fix
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
2212 Label allocated; 2214 Label allocated;
2213 2215
2214 Handle<Map> map(isolate()->native_context()->generator_result_map()); 2216 Handle<Map> map(isolate()->native_context()->generator_result_map());
2215 2217
2216 __ Allocate(map->instance_size(), rax, rcx, rdx, &gc_required, TAG_OBJECT); 2218 __ Allocate(map->instance_size(), rax, rcx, rdx, &gc_required, TAG_OBJECT);
2217 __ jmp(&allocated); 2219 __ jmp(&allocated);
2218 2220
2219 __ bind(&gc_required); 2221 __ bind(&gc_required);
2220 __ Push(Smi::FromInt(map->instance_size())); 2222 __ Push(Smi::FromInt(map->instance_size()));
2221 __ CallRuntime(Runtime::kAllocateInNewSpace, 1); 2223 __ CallRuntime(Runtime::kAllocateInNewSpace, 1);
2222 __ movq(context_register(), 2224 __ movp(context_register(),
2223 Operand(rbp, StandardFrameConstants::kContextOffset)); 2225 Operand(rbp, StandardFrameConstants::kContextOffset));
2224 2226
2225 __ bind(&allocated); 2227 __ bind(&allocated);
2226 __ Move(rbx, map); 2228 __ Move(rbx, map);
2227 __ pop(rcx); 2229 __ pop(rcx);
2228 __ Move(rdx, isolate()->factory()->ToBoolean(done)); 2230 __ Move(rdx, isolate()->factory()->ToBoolean(done));
2229 ASSERT_EQ(map->instance_size(), 5 * kPointerSize); 2231 ASSERT_EQ(map->instance_size(), 5 * kPointerSize);
2230 __ movq(FieldOperand(rax, HeapObject::kMapOffset), rbx); 2232 __ movp(FieldOperand(rax, HeapObject::kMapOffset), rbx);
2231 __ Move(FieldOperand(rax, JSObject::kPropertiesOffset), 2233 __ Move(FieldOperand(rax, JSObject::kPropertiesOffset),
2232 isolate()->factory()->empty_fixed_array()); 2234 isolate()->factory()->empty_fixed_array());
2233 __ Move(FieldOperand(rax, JSObject::kElementsOffset), 2235 __ Move(FieldOperand(rax, JSObject::kElementsOffset),
2234 isolate()->factory()->empty_fixed_array()); 2236 isolate()->factory()->empty_fixed_array());
2235 __ movq(FieldOperand(rax, JSGeneratorObject::kResultValuePropertyOffset), 2237 __ movp(FieldOperand(rax, JSGeneratorObject::kResultValuePropertyOffset),
2236 rcx); 2238 rcx);
2237 __ movq(FieldOperand(rax, JSGeneratorObject::kResultDonePropertyOffset), 2239 __ movp(FieldOperand(rax, JSGeneratorObject::kResultDonePropertyOffset),
2238 rdx); 2240 rdx);
2239 2241
2240 // Only the value field needs a write barrier, as the other values are in the 2242 // Only the value field needs a write barrier, as the other values are in the
2241 // root set. 2243 // root set.
2242 __ RecordWriteField(rax, JSGeneratorObject::kResultValuePropertyOffset, 2244 __ RecordWriteField(rax, JSGeneratorObject::kResultValuePropertyOffset,
2243 rcx, rdx, kDontSaveFPRegs); 2245 rcx, rdx, kDontSaveFPRegs);
2244 } 2246 }
2245 2247
2246 2248
2247 void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) { 2249 void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) {
(...skipping 14 matching lines...) Expand all
2262 void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr, 2264 void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr,
2263 Token::Value op, 2265 Token::Value op,
2264 OverwriteMode mode, 2266 OverwriteMode mode,
2265 Expression* left, 2267 Expression* left,
2266 Expression* right) { 2268 Expression* right) {
2267 // Do combined smi check of the operands. Left operand is on the 2269 // Do combined smi check of the operands. Left operand is on the
2268 // stack (popped into rdx). Right operand is in rax but moved into 2270 // stack (popped into rdx). Right operand is in rax but moved into
2269 // rcx to make the shifts easier. 2271 // rcx to make the shifts easier.
2270 Label done, stub_call, smi_case; 2272 Label done, stub_call, smi_case;
2271 __ pop(rdx); 2273 __ pop(rdx);
2272 __ movq(rcx, rax); 2274 __ movp(rcx, rax);
2273 __ or_(rax, rdx); 2275 __ or_(rax, rdx);
2274 JumpPatchSite patch_site(masm_); 2276 JumpPatchSite patch_site(masm_);
2275 patch_site.EmitJumpIfSmi(rax, &smi_case, Label::kNear); 2277 patch_site.EmitJumpIfSmi(rax, &smi_case, Label::kNear);
2276 2278
2277 __ bind(&stub_call); 2279 __ bind(&stub_call);
2278 __ movq(rax, rcx); 2280 __ movp(rax, rcx);
2279 BinaryOpICStub stub(op, mode); 2281 BinaryOpICStub stub(op, mode);
2280 CallIC(stub.GetCode(isolate()), NOT_CONTEXTUAL, 2282 CallIC(stub.GetCode(isolate()), NOT_CONTEXTUAL,
2281 expr->BinaryOperationFeedbackId()); 2283 expr->BinaryOperationFeedbackId());
2282 patch_site.EmitPatchInfo(); 2284 patch_site.EmitPatchInfo();
2283 __ jmp(&done, Label::kNear); 2285 __ jmp(&done, Label::kNear);
2284 2286
2285 __ bind(&smi_case); 2287 __ bind(&smi_case);
2286 switch (op) { 2288 switch (op) {
2287 case Token::SAR: 2289 case Token::SAR:
2288 __ SmiShiftArithmeticRight(rax, rdx, rcx); 2290 __ SmiShiftArithmeticRight(rax, rdx, rcx);
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
2356 switch (assign_type) { 2358 switch (assign_type) {
2357 case VARIABLE: { 2359 case VARIABLE: {
2358 Variable* var = expr->AsVariableProxy()->var(); 2360 Variable* var = expr->AsVariableProxy()->var();
2359 EffectContext context(this); 2361 EffectContext context(this);
2360 EmitVariableAssignment(var, Token::ASSIGN); 2362 EmitVariableAssignment(var, Token::ASSIGN);
2361 break; 2363 break;
2362 } 2364 }
2363 case NAMED_PROPERTY: { 2365 case NAMED_PROPERTY: {
2364 __ push(rax); // Preserve value. 2366 __ push(rax); // Preserve value.
2365 VisitForAccumulatorValue(prop->obj()); 2367 VisitForAccumulatorValue(prop->obj());
2366 __ movq(rdx, rax); 2368 __ movp(rdx, rax);
2367 __ pop(rax); // Restore value. 2369 __ pop(rax); // Restore value.
2368 __ Move(rcx, prop->key()->AsLiteral()->value()); 2370 __ Move(rcx, prop->key()->AsLiteral()->value());
2369 CallStoreIC(NOT_CONTEXTUAL); 2371 CallStoreIC(NOT_CONTEXTUAL);
2370 break; 2372 break;
2371 } 2373 }
2372 case KEYED_PROPERTY: { 2374 case KEYED_PROPERTY: {
2373 __ push(rax); // Preserve value. 2375 __ push(rax); // Preserve value.
2374 VisitForStackValue(prop->obj()); 2376 VisitForStackValue(prop->obj());
2375 VisitForAccumulatorValue(prop->key()); 2377 VisitForAccumulatorValue(prop->key());
2376 __ movq(rcx, rax); 2378 __ movp(rcx, rax);
2377 __ pop(rdx); 2379 __ pop(rdx);
2378 __ pop(rax); // Restore value. 2380 __ pop(rax); // Restore value.
2379 Handle<Code> ic = is_classic_mode() 2381 Handle<Code> ic = is_classic_mode()
2380 ? isolate()->builtins()->KeyedStoreIC_Initialize() 2382 ? isolate()->builtins()->KeyedStoreIC_Initialize()
2381 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); 2383 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict();
2382 CallIC(ic); 2384 CallIC(ic);
2383 break; 2385 break;
2384 } 2386 }
2385 } 2387 }
2386 context()->Plug(rax); 2388 context()->Plug(rax);
2387 } 2389 }
2388 2390
2389 2391
2390 void FullCodeGenerator::EmitVariableAssignment(Variable* var, 2392 void FullCodeGenerator::EmitVariableAssignment(Variable* var,
2391 Token::Value op) { 2393 Token::Value op) {
2392 if (var->IsUnallocated()) { 2394 if (var->IsUnallocated()) {
2393 // Global var, const, or let. 2395 // Global var, const, or let.
2394 __ Move(rcx, var->name()); 2396 __ Move(rcx, var->name());
2395 __ movq(rdx, GlobalObjectOperand()); 2397 __ movp(rdx, GlobalObjectOperand());
2396 CallStoreIC(CONTEXTUAL); 2398 CallStoreIC(CONTEXTUAL);
2397 } else if (op == Token::INIT_CONST) { 2399 } else if (op == Token::INIT_CONST) {
2398 // Const initializers need a write barrier. 2400 // Const initializers need a write barrier.
2399 ASSERT(!var->IsParameter()); // No const parameters. 2401 ASSERT(!var->IsParameter()); // No const parameters.
2400 if (var->IsStackLocal()) { 2402 if (var->IsStackLocal()) {
2401 Label skip; 2403 Label skip;
2402 __ movq(rdx, StackOperand(var)); 2404 __ movp(rdx, StackOperand(var));
2403 __ CompareRoot(rdx, Heap::kTheHoleValueRootIndex); 2405 __ CompareRoot(rdx, Heap::kTheHoleValueRootIndex);
2404 __ j(not_equal, &skip); 2406 __ j(not_equal, &skip);
2405 __ movq(StackOperand(var), rax); 2407 __ movp(StackOperand(var), rax);
2406 __ bind(&skip); 2408 __ bind(&skip);
2407 } else { 2409 } else {
2408 ASSERT(var->IsContextSlot() || var->IsLookupSlot()); 2410 ASSERT(var->IsContextSlot() || var->IsLookupSlot());
2409 // Like var declarations, const declarations are hoisted to function 2411 // Like var declarations, const declarations are hoisted to function
2410 // scope. However, unlike var initializers, const initializers are 2412 // scope. However, unlike var initializers, const initializers are
2411 // able to drill a hole to that function context, even from inside a 2413 // able to drill a hole to that function context, even from inside a
2412 // 'with' context. We thus bypass the normal static scope lookup for 2414 // 'with' context. We thus bypass the normal static scope lookup for
2413 // var->IsContextSlot(). 2415 // var->IsContextSlot().
2414 __ push(rax); 2416 __ push(rax);
2415 __ push(rsi); 2417 __ push(rsi);
2416 __ Push(var->name()); 2418 __ Push(var->name());
2417 __ CallRuntime(Runtime::kInitializeConstContextSlot, 3); 2419 __ CallRuntime(Runtime::kInitializeConstContextSlot, 3);
2418 } 2420 }
2419 2421
2420 } else if (var->mode() == LET && op != Token::INIT_LET) { 2422 } else if (var->mode() == LET && op != Token::INIT_LET) {
2421 // Non-initializing assignment to let variable needs a write barrier. 2423 // Non-initializing assignment to let variable needs a write barrier.
2422 if (var->IsLookupSlot()) { 2424 if (var->IsLookupSlot()) {
2423 __ push(rax); // Value. 2425 __ push(rax); // Value.
2424 __ push(rsi); // Context. 2426 __ push(rsi); // Context.
2425 __ Push(var->name()); 2427 __ Push(var->name());
2426 __ Push(Smi::FromInt(language_mode())); 2428 __ Push(Smi::FromInt(language_mode()));
2427 __ CallRuntime(Runtime::kStoreContextSlot, 4); 2429 __ CallRuntime(Runtime::kStoreContextSlot, 4);
2428 } else { 2430 } else {
2429 ASSERT(var->IsStackAllocated() || var->IsContextSlot()); 2431 ASSERT(var->IsStackAllocated() || var->IsContextSlot());
2430 Label assign; 2432 Label assign;
2431 MemOperand location = VarOperand(var, rcx); 2433 MemOperand location = VarOperand(var, rcx);
2432 __ movq(rdx, location); 2434 __ movp(rdx, location);
2433 __ CompareRoot(rdx, Heap::kTheHoleValueRootIndex); 2435 __ CompareRoot(rdx, Heap::kTheHoleValueRootIndex);
2434 __ j(not_equal, &assign, Label::kNear); 2436 __ j(not_equal, &assign, Label::kNear);
2435 __ Push(var->name()); 2437 __ Push(var->name());
2436 __ CallRuntime(Runtime::kThrowReferenceError, 1); 2438 __ CallRuntime(Runtime::kThrowReferenceError, 1);
2437 __ bind(&assign); 2439 __ bind(&assign);
2438 __ movq(location, rax); 2440 __ movp(location, rax);
2439 if (var->IsContextSlot()) { 2441 if (var->IsContextSlot()) {
2440 __ movq(rdx, rax); 2442 __ movp(rdx, rax);
2441 __ RecordWriteContextSlot( 2443 __ RecordWriteContextSlot(
2442 rcx, Context::SlotOffset(var->index()), rdx, rbx, kDontSaveFPRegs); 2444 rcx, Context::SlotOffset(var->index()), rdx, rbx, kDontSaveFPRegs);
2443 } 2445 }
2444 } 2446 }
2445 2447
2446 } else if (!var->is_const_mode() || op == Token::INIT_CONST_HARMONY) { 2448 } else if (!var->is_const_mode() || op == Token::INIT_CONST_HARMONY) {
2447 // Assignment to var or initializing assignment to let/const 2449 // Assignment to var or initializing assignment to let/const
2448 // in harmony mode. 2450 // in harmony mode.
2449 if (var->IsStackAllocated() || var->IsContextSlot()) { 2451 if (var->IsStackAllocated() || var->IsContextSlot()) {
2450 MemOperand location = VarOperand(var, rcx); 2452 MemOperand location = VarOperand(var, rcx);
2451 if (generate_debug_code_ && op == Token::INIT_LET) { 2453 if (generate_debug_code_ && op == Token::INIT_LET) {
2452 // Check for an uninitialized let binding. 2454 // Check for an uninitialized let binding.
2453 __ movq(rdx, location); 2455 __ movp(rdx, location);
2454 __ CompareRoot(rdx, Heap::kTheHoleValueRootIndex); 2456 __ CompareRoot(rdx, Heap::kTheHoleValueRootIndex);
2455 __ Check(equal, kLetBindingReInitialization); 2457 __ Check(equal, kLetBindingReInitialization);
2456 } 2458 }
2457 // Perform the assignment. 2459 // Perform the assignment.
2458 __ movq(location, rax); 2460 __ movp(location, rax);
2459 if (var->IsContextSlot()) { 2461 if (var->IsContextSlot()) {
2460 __ movq(rdx, rax); 2462 __ movp(rdx, rax);
2461 __ RecordWriteContextSlot( 2463 __ RecordWriteContextSlot(
2462 rcx, Context::SlotOffset(var->index()), rdx, rbx, kDontSaveFPRegs); 2464 rcx, Context::SlotOffset(var->index()), rdx, rbx, kDontSaveFPRegs);
2463 } 2465 }
2464 } else { 2466 } else {
2465 ASSERT(var->IsLookupSlot()); 2467 ASSERT(var->IsLookupSlot());
2466 __ push(rax); // Value. 2468 __ push(rax); // Value.
2467 __ push(rsi); // Context. 2469 __ push(rsi); // Context.
2468 __ Push(var->name()); 2470 __ Push(var->name());
2469 __ Push(Smi::FromInt(language_mode())); 2471 __ Push(Smi::FromInt(language_mode()));
2470 __ CallRuntime(Runtime::kStoreContextSlot, 4); 2472 __ CallRuntime(Runtime::kStoreContextSlot, 4);
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
2551 // Record source position for debugger. 2553 // Record source position for debugger.
2552 SetSourcePosition(expr->position()); 2554 SetSourcePosition(expr->position());
2553 // Call the IC initialization code. 2555 // Call the IC initialization code.
2554 Handle<Code> ic = isolate()->stub_cache()->ComputeCallInitialize(arg_count); 2556 Handle<Code> ic = isolate()->stub_cache()->ComputeCallInitialize(arg_count);
2555 TypeFeedbackId ast_id = mode == CONTEXTUAL 2557 TypeFeedbackId ast_id = mode == CONTEXTUAL
2556 ? TypeFeedbackId::None() 2558 ? TypeFeedbackId::None()
2557 : expr->CallFeedbackId(); 2559 : expr->CallFeedbackId();
2558 CallIC(ic, mode, ast_id); 2560 CallIC(ic, mode, ast_id);
2559 RecordJSReturnSite(expr); 2561 RecordJSReturnSite(expr);
2560 // Restore context register. 2562 // Restore context register.
2561 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 2563 __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
2562 context()->Plug(rax); 2564 context()->Plug(rax);
2563 } 2565 }
2564 2566
2565 2567
2566 void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr, 2568 void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr,
2567 Expression* key) { 2569 Expression* key) {
2568 // Load the key. 2570 // Load the key.
2569 VisitForAccumulatorValue(key); 2571 VisitForAccumulatorValue(key);
2570 2572
2571 // Swap the name of the function and the receiver on the stack to follow 2573 // Swap the name of the function and the receiver on the stack to follow
2572 // the calling convention for call ICs. 2574 // the calling convention for call ICs.
2573 __ pop(rcx); 2575 __ pop(rcx);
2574 __ push(rax); 2576 __ push(rax);
2575 __ push(rcx); 2577 __ push(rcx);
2576 2578
2577 // Load the arguments. 2579 // Load the arguments.
2578 ZoneList<Expression*>* args = expr->arguments(); 2580 ZoneList<Expression*>* args = expr->arguments();
2579 int arg_count = args->length(); 2581 int arg_count = args->length();
2580 { PreservePositionScope scope(masm()->positions_recorder()); 2582 { PreservePositionScope scope(masm()->positions_recorder());
2581 for (int i = 0; i < arg_count; i++) { 2583 for (int i = 0; i < arg_count; i++) {
2582 VisitForStackValue(args->at(i)); 2584 VisitForStackValue(args->at(i));
2583 } 2585 }
2584 } 2586 }
2585 // Record source position for debugger. 2587 // Record source position for debugger.
2586 SetSourcePosition(expr->position()); 2588 SetSourcePosition(expr->position());
2587 // Call the IC initialization code. 2589 // Call the IC initialization code.
2588 Handle<Code> ic = 2590 Handle<Code> ic =
2589 isolate()->stub_cache()->ComputeKeyedCallInitialize(arg_count); 2591 isolate()->stub_cache()->ComputeKeyedCallInitialize(arg_count);
2590 __ movq(rcx, Operand(rsp, (arg_count + 1) * kPointerSize)); // Key. 2592 __ movp(rcx, Operand(rsp, (arg_count + 1) * kPointerSize)); // Key.
2591 CallIC(ic, NOT_CONTEXTUAL, expr->CallFeedbackId()); 2593 CallIC(ic, NOT_CONTEXTUAL, expr->CallFeedbackId());
2592 RecordJSReturnSite(expr); 2594 RecordJSReturnSite(expr);
2593 // Restore context register. 2595 // Restore context register.
2594 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 2596 __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
2595 context()->DropAndPlug(1, rax); // Drop the key still on the stack. 2597 context()->DropAndPlug(1, rax); // Drop the key still on the stack.
2596 } 2598 }
2597 2599
2598 2600
2599 void FullCodeGenerator::EmitCallWithStub(Call* expr) { 2601 void FullCodeGenerator::EmitCallWithStub(Call* expr) {
2600 // Code common for calls using the call stub. 2602 // Code common for calls using the call stub.
2601 ZoneList<Expression*>* args = expr->arguments(); 2603 ZoneList<Expression*>* args = expr->arguments();
2602 int arg_count = args->length(); 2604 int arg_count = args->length();
2603 { PreservePositionScope scope(masm()->positions_recorder()); 2605 { PreservePositionScope scope(masm()->positions_recorder());
2604 for (int i = 0; i < arg_count; i++) { 2606 for (int i = 0; i < arg_count; i++) {
2605 VisitForStackValue(args->at(i)); 2607 VisitForStackValue(args->at(i));
2606 } 2608 }
2607 } 2609 }
2608 // Record source position for debugger. 2610 // Record source position for debugger.
2609 SetSourcePosition(expr->position()); 2611 SetSourcePosition(expr->position());
2610 2612
2611 Handle<Object> uninitialized = 2613 Handle<Object> uninitialized =
2612 TypeFeedbackCells::UninitializedSentinel(isolate()); 2614 TypeFeedbackCells::UninitializedSentinel(isolate());
2613 Handle<Cell> cell = isolate()->factory()->NewCell(uninitialized); 2615 Handle<Cell> cell = isolate()->factory()->NewCell(uninitialized);
2614 RecordTypeFeedbackCell(expr->CallFeedbackId(), cell); 2616 RecordTypeFeedbackCell(expr->CallFeedbackId(), cell);
2615 __ Move(rbx, cell); 2617 __ Move(rbx, cell);
2616 2618
2617 // Record call targets in unoptimized code. 2619 // Record call targets in unoptimized code.
2618 CallFunctionStub stub(arg_count, RECORD_CALL_TARGET); 2620 CallFunctionStub stub(arg_count, RECORD_CALL_TARGET);
2619 __ movq(rdi, Operand(rsp, (arg_count + 1) * kPointerSize)); 2621 __ movp(rdi, Operand(rsp, (arg_count + 1) * kPointerSize));
2620 __ CallStub(&stub, expr->CallFeedbackId()); 2622 __ CallStub(&stub, expr->CallFeedbackId());
2621 RecordJSReturnSite(expr); 2623 RecordJSReturnSite(expr);
2622 // Restore context register. 2624 // Restore context register.
2623 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 2625 __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
2624 // Discard the function left on TOS. 2626 // Discard the function left on TOS.
2625 context()->DropAndPlug(1, rax); 2627 context()->DropAndPlug(1, rax);
2626 } 2628 }
2627 2629
2628 2630
2629 void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) { 2631 void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) {
2630 // Push copy of the first argument or undefined if it doesn't exist. 2632 // Push copy of the first argument or undefined if it doesn't exist.
2631 if (arg_count > 0) { 2633 if (arg_count > 0) {
2632 __ push(Operand(rsp, arg_count * kPointerSize)); 2634 __ push(Operand(rsp, arg_count * kPointerSize));
2633 } else { 2635 } else {
(...skipping 17 matching lines...) Expand all
2651 2653
2652 void FullCodeGenerator::VisitCall(Call* expr) { 2654 void FullCodeGenerator::VisitCall(Call* expr) {
2653 #ifdef DEBUG 2655 #ifdef DEBUG
2654 // We want to verify that RecordJSReturnSite gets called on all paths 2656 // We want to verify that RecordJSReturnSite gets called on all paths
2655 // through this function. Avoid early returns. 2657 // through this function. Avoid early returns.
2656 expr->return_is_recorded_ = false; 2658 expr->return_is_recorded_ = false;
2657 #endif 2659 #endif
2658 2660
2659 Comment cmnt(masm_, "[ Call"); 2661 Comment cmnt(masm_, "[ Call");
2660 Expression* callee = expr->expression(); 2662 Expression* callee = expr->expression();
2661 VariableProxy* proxy = callee->AsVariableProxy(); 2663 Call::CallType call_type = expr->GetCallType(isolate());
2662 Property* property = callee->AsProperty();
2663 2664
2664 if (proxy != NULL && proxy->var()->is_possibly_eval(isolate())) { 2665 if (call_type == Call::POSSIBLY_EVAL_CALL) {
2665 // In a call to eval, we first call %ResolvePossiblyDirectEval to 2666 // In a call to eval, we first call %ResolvePossiblyDirectEval to
2666 // resolve the function we need to call and the receiver of the call. 2667 // resolve the function we need to call and the receiver of the call.
2667 // Then we call the resolved function using the given arguments. 2668 // Then we call the resolved function using the given arguments.
2668 ZoneList<Expression*>* args = expr->arguments(); 2669 ZoneList<Expression*>* args = expr->arguments();
2669 int arg_count = args->length(); 2670 int arg_count = args->length();
2670 { PreservePositionScope pos_scope(masm()->positions_recorder()); 2671 { PreservePositionScope pos_scope(masm()->positions_recorder());
2671 VisitForStackValue(callee); 2672 VisitForStackValue(callee);
2672 __ PushRoot(Heap::kUndefinedValueRootIndex); // Reserved receiver slot. 2673 __ PushRoot(Heap::kUndefinedValueRootIndex); // Reserved receiver slot.
2673 2674
2674 // Push the arguments. 2675 // Push the arguments.
2675 for (int i = 0; i < arg_count; i++) { 2676 for (int i = 0; i < arg_count; i++) {
2676 VisitForStackValue(args->at(i)); 2677 VisitForStackValue(args->at(i));
2677 } 2678 }
2678 2679
2679 // Push a copy of the function (found below the arguments) and resolve 2680 // Push a copy of the function (found below the arguments) and resolve
2680 // eval. 2681 // eval.
2681 __ push(Operand(rsp, (arg_count + 1) * kPointerSize)); 2682 __ push(Operand(rsp, (arg_count + 1) * kPointerSize));
2682 EmitResolvePossiblyDirectEval(arg_count); 2683 EmitResolvePossiblyDirectEval(arg_count);
2683 2684
2684 // The runtime call returns a pair of values in rax (function) and 2685 // The runtime call returns a pair of values in rax (function) and
2685 // rdx (receiver). Touch up the stack with the right values. 2686 // rdx (receiver). Touch up the stack with the right values.
2686 __ movq(Operand(rsp, (arg_count + 0) * kPointerSize), rdx); 2687 __ movp(Operand(rsp, (arg_count + 0) * kPointerSize), rdx);
2687 __ movq(Operand(rsp, (arg_count + 1) * kPointerSize), rax); 2688 __ movp(Operand(rsp, (arg_count + 1) * kPointerSize), rax);
2688 } 2689 }
2689 // Record source position for debugger. 2690 // Record source position for debugger.
2690 SetSourcePosition(expr->position()); 2691 SetSourcePosition(expr->position());
2691 CallFunctionStub stub(arg_count, NO_CALL_FUNCTION_FLAGS); 2692 CallFunctionStub stub(arg_count, NO_CALL_FUNCTION_FLAGS);
2692 __ movq(rdi, Operand(rsp, (arg_count + 1) * kPointerSize)); 2693 __ movp(rdi, Operand(rsp, (arg_count + 1) * kPointerSize));
2693 __ CallStub(&stub); 2694 __ CallStub(&stub);
2694 RecordJSReturnSite(expr); 2695 RecordJSReturnSite(expr);
2695 // Restore context register. 2696 // Restore context register.
2696 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 2697 __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
2697 context()->DropAndPlug(1, rax); 2698 context()->DropAndPlug(1, rax);
2698 } else if (proxy != NULL && proxy->var()->IsUnallocated()) { 2699 } else if (call_type == Call::GLOBAL_CALL) {
2699 // Call to a global variable. Push global object as receiver for the 2700 // Call to a global variable. Push global object as receiver for the
2700 // call IC lookup. 2701 // call IC lookup.
2701 __ push(GlobalObjectOperand()); 2702 __ push(GlobalObjectOperand());
2703 VariableProxy* proxy = callee->AsVariableProxy();
2702 EmitCallWithIC(expr, proxy->name(), CONTEXTUAL); 2704 EmitCallWithIC(expr, proxy->name(), CONTEXTUAL);
2703 } else if (proxy != NULL && proxy->var()->IsLookupSlot()) { 2705 } else if (call_type == Call::LOOKUP_SLOT_CALL) {
2704 // Call to a lookup slot (dynamically introduced variable). 2706 // Call to a lookup slot (dynamically introduced variable).
2707 VariableProxy* proxy = callee->AsVariableProxy();
2705 Label slow, done; 2708 Label slow, done;
2706 2709
2707 { PreservePositionScope scope(masm()->positions_recorder()); 2710 { PreservePositionScope scope(masm()->positions_recorder());
2708 // Generate code for loading from variables potentially shadowed by 2711 // Generate code for loading from variables potentially shadowed by
2709 // eval-introduced variables. 2712 // eval-introduced variables.
2710 EmitDynamicLookupFastCase(proxy->var(), NOT_INSIDE_TYPEOF, &slow, &done); 2713 EmitDynamicLookupFastCase(proxy->var(), NOT_INSIDE_TYPEOF, &slow, &done);
2711 } 2714 }
2712 __ bind(&slow); 2715 __ bind(&slow);
2713 // Call the runtime to find the function to call (returned in rax) and 2716 // Call the runtime to find the function to call (returned in rax) and
2714 // the object holding it (returned in rdx). 2717 // the object holding it (returned in rdx).
(...skipping 13 matching lines...) Expand all
2728 __ push(rax); 2731 __ push(rax);
2729 // The receiver is implicitly the global receiver. Indicate this by 2732 // The receiver is implicitly the global receiver. Indicate this by
2730 // passing the hole to the call function stub. 2733 // passing the hole to the call function stub.
2731 __ PushRoot(Heap::kUndefinedValueRootIndex); 2734 __ PushRoot(Heap::kUndefinedValueRootIndex);
2732 __ bind(&call); 2735 __ bind(&call);
2733 } 2736 }
2734 2737
2735 // The receiver is either the global receiver or an object found by 2738 // The receiver is either the global receiver or an object found by
2736 // LoadContextSlot. 2739 // LoadContextSlot.
2737 EmitCallWithStub(expr); 2740 EmitCallWithStub(expr);
2738 } else if (property != NULL) { 2741 } else if (call_type == Call::PROPERTY_CALL) {
2742 Property* property = callee->AsProperty();
2739 { PreservePositionScope scope(masm()->positions_recorder()); 2743 { PreservePositionScope scope(masm()->positions_recorder());
2740 VisitForStackValue(property->obj()); 2744 VisitForStackValue(property->obj());
2741 } 2745 }
2742 if (property->key()->IsPropertyName()) { 2746 if (property->key()->IsPropertyName()) {
2743 EmitCallWithIC(expr, 2747 EmitCallWithIC(expr,
2744 property->key()->AsLiteral()->value(), 2748 property->key()->AsLiteral()->value(),
2745 NOT_CONTEXTUAL); 2749 NOT_CONTEXTUAL);
2746 } else { 2750 } else {
2747 EmitKeyedCallWithIC(expr, property->key()); 2751 EmitKeyedCallWithIC(expr, property->key());
2748 } 2752 }
2749 } else { 2753 } else {
2754 ASSERT(call_type == Call::OTHER_CALL);
2750 // Call to an arbitrary expression not handled specially above. 2755 // Call to an arbitrary expression not handled specially above.
2751 { PreservePositionScope scope(masm()->positions_recorder()); 2756 { PreservePositionScope scope(masm()->positions_recorder());
2752 VisitForStackValue(callee); 2757 VisitForStackValue(callee);
2753 } 2758 }
2754 __ PushRoot(Heap::kUndefinedValueRootIndex); 2759 __ PushRoot(Heap::kUndefinedValueRootIndex);
2755 // Emit function call. 2760 // Emit function call.
2756 EmitCallWithStub(expr); 2761 EmitCallWithStub(expr);
2757 } 2762 }
2758 2763
2759 #ifdef DEBUG 2764 #ifdef DEBUG
(...skipping 20 matching lines...) Expand all
2780 for (int i = 0; i < arg_count; i++) { 2785 for (int i = 0; i < arg_count; i++) {
2781 VisitForStackValue(args->at(i)); 2786 VisitForStackValue(args->at(i));
2782 } 2787 }
2783 2788
2784 // Call the construct call builtin that handles allocation and 2789 // Call the construct call builtin that handles allocation and
2785 // constructor invocation. 2790 // constructor invocation.
2786 SetSourcePosition(expr->position()); 2791 SetSourcePosition(expr->position());
2787 2792
2788 // Load function and argument count into rdi and rax. 2793 // Load function and argument count into rdi and rax.
2789 __ Set(rax, arg_count); 2794 __ Set(rax, arg_count);
2790 __ movq(rdi, Operand(rsp, arg_count * kPointerSize)); 2795 __ movp(rdi, Operand(rsp, arg_count * kPointerSize));
2791 2796
2792 // Record call targets in unoptimized code, but not in the snapshot. 2797 // Record call targets in unoptimized code, but not in the snapshot.
2793 Handle<Object> uninitialized = 2798 Handle<Object> uninitialized =
2794 TypeFeedbackCells::UninitializedSentinel(isolate()); 2799 TypeFeedbackCells::UninitializedSentinel(isolate());
2795 Handle<Cell> cell = isolate()->factory()->NewCell(uninitialized); 2800 Handle<Cell> cell = isolate()->factory()->NewCell(uninitialized);
2796 RecordTypeFeedbackCell(expr->CallNewFeedbackId(), cell); 2801 RecordTypeFeedbackCell(expr->CallNewFeedbackId(), cell);
2797 __ Move(rbx, cell); 2802 __ Move(rbx, cell);
2798 2803
2799 CallConstructStub stub(RECORD_CALL_TARGET); 2804 CallConstructStub stub(RECORD_CALL_TARGET);
2800 __ Call(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL); 2805 __ Call(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL);
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
2854 Label materialize_true, materialize_false; 2859 Label materialize_true, materialize_false;
2855 Label* if_true = NULL; 2860 Label* if_true = NULL;
2856 Label* if_false = NULL; 2861 Label* if_false = NULL;
2857 Label* fall_through = NULL; 2862 Label* fall_through = NULL;
2858 context()->PrepareTest(&materialize_true, &materialize_false, 2863 context()->PrepareTest(&materialize_true, &materialize_false,
2859 &if_true, &if_false, &fall_through); 2864 &if_true, &if_false, &fall_through);
2860 2865
2861 __ JumpIfSmi(rax, if_false); 2866 __ JumpIfSmi(rax, if_false);
2862 __ CompareRoot(rax, Heap::kNullValueRootIndex); 2867 __ CompareRoot(rax, Heap::kNullValueRootIndex);
2863 __ j(equal, if_true); 2868 __ j(equal, if_true);
2864 __ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset)); 2869 __ movp(rbx, FieldOperand(rax, HeapObject::kMapOffset));
2865 // Undetectable objects behave like undefined when tested with typeof. 2870 // Undetectable objects behave like undefined when tested with typeof.
2866 __ testb(FieldOperand(rbx, Map::kBitFieldOffset), 2871 __ testb(FieldOperand(rbx, Map::kBitFieldOffset),
2867 Immediate(1 << Map::kIsUndetectable)); 2872 Immediate(1 << Map::kIsUndetectable));
2868 __ j(not_zero, if_false); 2873 __ j(not_zero, if_false);
2869 __ movzxbq(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset)); 2874 __ movzxbq(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset));
2870 __ cmpq(rbx, Immediate(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE)); 2875 __ cmpq(rbx, Immediate(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE));
2871 __ j(below, if_false); 2876 __ j(below, if_false);
2872 __ cmpq(rbx, Immediate(LAST_NONCALLABLE_SPEC_OBJECT_TYPE)); 2877 __ cmpq(rbx, Immediate(LAST_NONCALLABLE_SPEC_OBJECT_TYPE));
2873 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 2878 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2874 Split(below_equal, if_true, if_false, fall_through); 2879 Split(below_equal, if_true, if_false, fall_through);
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
2906 VisitForAccumulatorValue(args->at(0)); 2911 VisitForAccumulatorValue(args->at(0));
2907 2912
2908 Label materialize_true, materialize_false; 2913 Label materialize_true, materialize_false;
2909 Label* if_true = NULL; 2914 Label* if_true = NULL;
2910 Label* if_false = NULL; 2915 Label* if_false = NULL;
2911 Label* fall_through = NULL; 2916 Label* fall_through = NULL;
2912 context()->PrepareTest(&materialize_true, &materialize_false, 2917 context()->PrepareTest(&materialize_true, &materialize_false,
2913 &if_true, &if_false, &fall_through); 2918 &if_true, &if_false, &fall_through);
2914 2919
2915 __ JumpIfSmi(rax, if_false); 2920 __ JumpIfSmi(rax, if_false);
2916 __ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset)); 2921 __ movp(rbx, FieldOperand(rax, HeapObject::kMapOffset));
2917 __ testb(FieldOperand(rbx, Map::kBitFieldOffset), 2922 __ testb(FieldOperand(rbx, Map::kBitFieldOffset),
2918 Immediate(1 << Map::kIsUndetectable)); 2923 Immediate(1 << Map::kIsUndetectable));
2919 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 2924 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2920 Split(not_zero, if_true, if_false, fall_through); 2925 Split(not_zero, if_true, if_false, fall_through);
2921 2926
2922 context()->Plug(if_true, if_false); 2927 context()->Plug(if_true, if_false);
2923 } 2928 }
2924 2929
2925 2930
2926 void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf( 2931 void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf(
2927 CallRuntime* expr) { 2932 CallRuntime* expr) {
2928 ZoneList<Expression*>* args = expr->arguments(); 2933 ZoneList<Expression*>* args = expr->arguments();
2929 ASSERT(args->length() == 1); 2934 ASSERT(args->length() == 1);
2930 2935
2931 VisitForAccumulatorValue(args->at(0)); 2936 VisitForAccumulatorValue(args->at(0));
2932 2937
2933 Label materialize_true, materialize_false, skip_lookup; 2938 Label materialize_true, materialize_false, skip_lookup;
2934 Label* if_true = NULL; 2939 Label* if_true = NULL;
2935 Label* if_false = NULL; 2940 Label* if_false = NULL;
2936 Label* fall_through = NULL; 2941 Label* fall_through = NULL;
2937 context()->PrepareTest(&materialize_true, &materialize_false, 2942 context()->PrepareTest(&materialize_true, &materialize_false,
2938 &if_true, &if_false, &fall_through); 2943 &if_true, &if_false, &fall_through);
2939 2944
2940 __ AssertNotSmi(rax); 2945 __ AssertNotSmi(rax);
2941 2946
2942 // Check whether this map has already been checked to be safe for default 2947 // Check whether this map has already been checked to be safe for default
2943 // valueOf. 2948 // valueOf.
2944 __ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset)); 2949 __ movp(rbx, FieldOperand(rax, HeapObject::kMapOffset));
2945 __ testb(FieldOperand(rbx, Map::kBitField2Offset), 2950 __ testb(FieldOperand(rbx, Map::kBitField2Offset),
2946 Immediate(1 << Map::kStringWrapperSafeForDefaultValueOf)); 2951 Immediate(1 << Map::kStringWrapperSafeForDefaultValueOf));
2947 __ j(not_zero, &skip_lookup); 2952 __ j(not_zero, &skip_lookup);
2948 2953
2949 // Check for fast case object. Generate false result for slow case object. 2954 // Check for fast case object. Generate false result for slow case object.
2950 __ movq(rcx, FieldOperand(rax, JSObject::kPropertiesOffset)); 2955 __ movp(rcx, FieldOperand(rax, JSObject::kPropertiesOffset));
2951 __ movq(rcx, FieldOperand(rcx, HeapObject::kMapOffset)); 2956 __ movp(rcx, FieldOperand(rcx, HeapObject::kMapOffset));
2952 __ CompareRoot(rcx, Heap::kHashTableMapRootIndex); 2957 __ CompareRoot(rcx, Heap::kHashTableMapRootIndex);
2953 __ j(equal, if_false); 2958 __ j(equal, if_false);
2954 2959
2955 // Look for valueOf string in the descriptor array, and indicate false if 2960 // Look for valueOf string in the descriptor array, and indicate false if
2956 // found. Since we omit an enumeration index check, if it is added via a 2961 // found. Since we omit an enumeration index check, if it is added via a
2957 // transition that shares its descriptor array, this is a false positive. 2962 // transition that shares its descriptor array, this is a false positive.
2958 Label entry, loop, done; 2963 Label entry, loop, done;
2959 2964
2960 // Skip loop if no descriptors are valid. 2965 // Skip loop if no descriptors are valid.
2961 __ NumberOfOwnDescriptors(rcx, rbx); 2966 __ NumberOfOwnDescriptors(rcx, rbx);
2962 __ cmpq(rcx, Immediate(0)); 2967 __ cmpq(rcx, Immediate(0));
2963 __ j(equal, &done); 2968 __ j(equal, &done);
2964 2969
2965 __ LoadInstanceDescriptors(rbx, r8); 2970 __ LoadInstanceDescriptors(rbx, r8);
2966 // rbx: descriptor array. 2971 // rbx: descriptor array.
2967 // rcx: valid entries in the descriptor array. 2972 // rcx: valid entries in the descriptor array.
2968 // Calculate the end of the descriptor array. 2973 // Calculate the end of the descriptor array.
2969 __ imul(rcx, rcx, Immediate(DescriptorArray::kDescriptorSize)); 2974 __ imul(rcx, rcx, Immediate(DescriptorArray::kDescriptorSize));
2970 SmiIndex index = masm_->SmiToIndex(rdx, rcx, kPointerSizeLog2); 2975 SmiIndex index = masm_->SmiToIndex(rdx, rcx, kPointerSizeLog2);
2971 __ lea(rcx, 2976 __ lea(rcx,
2972 Operand( 2977 Operand(
2973 r8, index.reg, index.scale, DescriptorArray::kFirstOffset)); 2978 r8, index.reg, index.scale, DescriptorArray::kFirstOffset));
2974 // Calculate location of the first key name. 2979 // Calculate location of the first key name.
2975 __ addq(r8, Immediate(DescriptorArray::kFirstOffset)); 2980 __ addq(r8, Immediate(DescriptorArray::kFirstOffset));
2976 // Loop through all the keys in the descriptor array. If one of these is the 2981 // Loop through all the keys in the descriptor array. If one of these is the
2977 // internalized string "valueOf" the result is false. 2982 // internalized string "valueOf" the result is false.
2978 __ jmp(&entry); 2983 __ jmp(&entry);
2979 __ bind(&loop); 2984 __ bind(&loop);
2980 __ movq(rdx, FieldOperand(r8, 0)); 2985 __ movp(rdx, FieldOperand(r8, 0));
2981 __ Cmp(rdx, isolate()->factory()->value_of_string()); 2986 __ Cmp(rdx, isolate()->factory()->value_of_string());
2982 __ j(equal, if_false); 2987 __ j(equal, if_false);
2983 __ addq(r8, Immediate(DescriptorArray::kDescriptorSize * kPointerSize)); 2988 __ addq(r8, Immediate(DescriptorArray::kDescriptorSize * kPointerSize));
2984 __ bind(&entry); 2989 __ bind(&entry);
2985 __ cmpq(r8, rcx); 2990 __ cmpq(r8, rcx);
2986 __ j(not_equal, &loop); 2991 __ j(not_equal, &loop);
2987 2992
2988 __ bind(&done); 2993 __ bind(&done);
2989 2994
2990 // Set the bit in the map to indicate that there is no local valueOf field. 2995 // Set the bit in the map to indicate that there is no local valueOf field.
2991 __ or_(FieldOperand(rbx, Map::kBitField2Offset), 2996 __ or_(FieldOperand(rbx, Map::kBitField2Offset),
2992 Immediate(1 << Map::kStringWrapperSafeForDefaultValueOf)); 2997 Immediate(1 << Map::kStringWrapperSafeForDefaultValueOf));
2993 2998
2994 __ bind(&skip_lookup); 2999 __ bind(&skip_lookup);
2995 3000
2996 // If a valueOf property is not found on the object check that its 3001 // If a valueOf property is not found on the object check that its
2997 // prototype is the un-modified String prototype. If not result is false. 3002 // prototype is the un-modified String prototype. If not result is false.
2998 __ movq(rcx, FieldOperand(rbx, Map::kPrototypeOffset)); 3003 __ movp(rcx, FieldOperand(rbx, Map::kPrototypeOffset));
2999 __ testq(rcx, Immediate(kSmiTagMask)); 3004 __ testq(rcx, Immediate(kSmiTagMask));
3000 __ j(zero, if_false); 3005 __ j(zero, if_false);
3001 __ movq(rcx, FieldOperand(rcx, HeapObject::kMapOffset)); 3006 __ movp(rcx, FieldOperand(rcx, HeapObject::kMapOffset));
3002 __ movq(rdx, Operand(rsi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); 3007 __ movp(rdx, Operand(rsi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
3003 __ movq(rdx, FieldOperand(rdx, GlobalObject::kNativeContextOffset)); 3008 __ movp(rdx, FieldOperand(rdx, GlobalObject::kNativeContextOffset));
3004 __ cmpq(rcx, 3009 __ cmpq(rcx,
3005 ContextOperand(rdx, Context::STRING_FUNCTION_PROTOTYPE_MAP_INDEX)); 3010 ContextOperand(rdx, Context::STRING_FUNCTION_PROTOTYPE_MAP_INDEX));
3006 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 3011 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
3007 Split(equal, if_true, if_false, fall_through); 3012 Split(equal, if_true, if_false, fall_through);
3008 3013
3009 context()->Plug(if_true, if_false); 3014 context()->Plug(if_true, if_false);
3010 } 3015 }
3011 3016
3012 3017
3013 void FullCodeGenerator::EmitIsFunction(CallRuntime* expr) { 3018 void FullCodeGenerator::EmitIsFunction(CallRuntime* expr) {
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
3108 ASSERT(expr->arguments()->length() == 0); 3113 ASSERT(expr->arguments()->length() == 0);
3109 3114
3110 Label materialize_true, materialize_false; 3115 Label materialize_true, materialize_false;
3111 Label* if_true = NULL; 3116 Label* if_true = NULL;
3112 Label* if_false = NULL; 3117 Label* if_false = NULL;
3113 Label* fall_through = NULL; 3118 Label* fall_through = NULL;
3114 context()->PrepareTest(&materialize_true, &materialize_false, 3119 context()->PrepareTest(&materialize_true, &materialize_false,
3115 &if_true, &if_false, &fall_through); 3120 &if_true, &if_false, &fall_through);
3116 3121
3117 // Get the frame pointer for the calling frame. 3122 // Get the frame pointer for the calling frame.
3118 __ movq(rax, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); 3123 __ movp(rax, Operand(rbp, StandardFrameConstants::kCallerFPOffset));
3119 3124
3120 // Skip the arguments adaptor frame if it exists. 3125 // Skip the arguments adaptor frame if it exists.
3121 Label check_frame_marker; 3126 Label check_frame_marker;
3122 __ Cmp(Operand(rax, StandardFrameConstants::kContextOffset), 3127 __ Cmp(Operand(rax, StandardFrameConstants::kContextOffset),
3123 Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); 3128 Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
3124 __ j(not_equal, &check_frame_marker); 3129 __ j(not_equal, &check_frame_marker);
3125 __ movq(rax, Operand(rax, StandardFrameConstants::kCallerFPOffset)); 3130 __ movp(rax, Operand(rax, StandardFrameConstants::kCallerFPOffset));
3126 3131
3127 // Check the marker in the calling frame. 3132 // Check the marker in the calling frame.
3128 __ bind(&check_frame_marker); 3133 __ bind(&check_frame_marker);
3129 __ Cmp(Operand(rax, StandardFrameConstants::kMarkerOffset), 3134 __ Cmp(Operand(rax, StandardFrameConstants::kMarkerOffset),
3130 Smi::FromInt(StackFrame::CONSTRUCT)); 3135 Smi::FromInt(StackFrame::CONSTRUCT));
3131 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 3136 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
3132 Split(equal, if_true, if_false, fall_through); 3137 Split(equal, if_true, if_false, fall_through);
3133 3138
3134 context()->Plug(if_true, if_false); 3139 context()->Plug(if_true, if_false);
3135 } 3140 }
(...skipping 23 matching lines...) Expand all
3159 } 3164 }
3160 3165
3161 3166
3162 void FullCodeGenerator::EmitArguments(CallRuntime* expr) { 3167 void FullCodeGenerator::EmitArguments(CallRuntime* expr) {
3163 ZoneList<Expression*>* args = expr->arguments(); 3168 ZoneList<Expression*>* args = expr->arguments();
3164 ASSERT(args->length() == 1); 3169 ASSERT(args->length() == 1);
3165 3170
3166 // ArgumentsAccessStub expects the key in rdx and the formal 3171 // ArgumentsAccessStub expects the key in rdx and the formal
3167 // parameter count in rax. 3172 // parameter count in rax.
3168 VisitForAccumulatorValue(args->at(0)); 3173 VisitForAccumulatorValue(args->at(0));
3169 __ movq(rdx, rax); 3174 __ movp(rdx, rax);
3170 __ Move(rax, Smi::FromInt(info_->scope()->num_parameters())); 3175 __ Move(rax, Smi::FromInt(info_->scope()->num_parameters()));
3171 ArgumentsAccessStub stub(ArgumentsAccessStub::READ_ELEMENT); 3176 ArgumentsAccessStub stub(ArgumentsAccessStub::READ_ELEMENT);
3172 __ CallStub(&stub); 3177 __ CallStub(&stub);
3173 context()->Plug(rax); 3178 context()->Plug(rax);
3174 } 3179 }
3175 3180
3176 3181
3177 void FullCodeGenerator::EmitArgumentsLength(CallRuntime* expr) { 3182 void FullCodeGenerator::EmitArgumentsLength(CallRuntime* expr) {
3178 ASSERT(expr->arguments()->length() == 0); 3183 ASSERT(expr->arguments()->length() == 0);
3179 3184
3180 Label exit; 3185 Label exit;
3181 // Get the number of formal parameters. 3186 // Get the number of formal parameters.
3182 __ Move(rax, Smi::FromInt(info_->scope()->num_parameters())); 3187 __ Move(rax, Smi::FromInt(info_->scope()->num_parameters()));
3183 3188
3184 // Check if the calling frame is an arguments adaptor frame. 3189 // Check if the calling frame is an arguments adaptor frame.
3185 __ movq(rbx, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); 3190 __ movp(rbx, Operand(rbp, StandardFrameConstants::kCallerFPOffset));
3186 __ Cmp(Operand(rbx, StandardFrameConstants::kContextOffset), 3191 __ Cmp(Operand(rbx, StandardFrameConstants::kContextOffset),
3187 Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); 3192 Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
3188 __ j(not_equal, &exit, Label::kNear); 3193 __ j(not_equal, &exit, Label::kNear);
3189 3194
3190 // Arguments adaptor case: Read the arguments length from the 3195 // Arguments adaptor case: Read the arguments length from the
3191 // adaptor frame. 3196 // adaptor frame.
3192 __ movq(rax, Operand(rbx, ArgumentsAdaptorFrameConstants::kLengthOffset)); 3197 __ movp(rax, Operand(rbx, ArgumentsAdaptorFrameConstants::kLengthOffset));
3193 3198
3194 __ bind(&exit); 3199 __ bind(&exit);
3195 __ AssertSmi(rax); 3200 __ AssertSmi(rax);
3196 context()->Plug(rax); 3201 context()->Plug(rax);
3197 } 3202 }
3198 3203
3199 3204
3200 void FullCodeGenerator::EmitClassOf(CallRuntime* expr) { 3205 void FullCodeGenerator::EmitClassOf(CallRuntime* expr) {
3201 ZoneList<Expression*>* args = expr->arguments(); 3206 ZoneList<Expression*>* args = expr->arguments();
3202 ASSERT(args->length() == 1); 3207 ASSERT(args->length() == 1);
(...skipping 17 matching lines...) Expand all
3220 __ j(equal, &function); 3225 __ j(equal, &function);
3221 3226
3222 __ CmpInstanceType(rax, LAST_SPEC_OBJECT_TYPE); 3227 __ CmpInstanceType(rax, LAST_SPEC_OBJECT_TYPE);
3223 STATIC_ASSERT(LAST_NONCALLABLE_SPEC_OBJECT_TYPE == 3228 STATIC_ASSERT(LAST_NONCALLABLE_SPEC_OBJECT_TYPE ==
3224 LAST_SPEC_OBJECT_TYPE - 1); 3229 LAST_SPEC_OBJECT_TYPE - 1);
3225 __ j(equal, &function); 3230 __ j(equal, &function);
3226 // Assume that there is no larger type. 3231 // Assume that there is no larger type.
3227 STATIC_ASSERT(LAST_NONCALLABLE_SPEC_OBJECT_TYPE == LAST_TYPE - 1); 3232 STATIC_ASSERT(LAST_NONCALLABLE_SPEC_OBJECT_TYPE == LAST_TYPE - 1);
3228 3233
3229 // Check if the constructor in the map is a JS function. 3234 // Check if the constructor in the map is a JS function.
3230 __ movq(rax, FieldOperand(rax, Map::kConstructorOffset)); 3235 __ movp(rax, FieldOperand(rax, Map::kConstructorOffset));
3231 __ CmpObjectType(rax, JS_FUNCTION_TYPE, rbx); 3236 __ CmpObjectType(rax, JS_FUNCTION_TYPE, rbx);
3232 __ j(not_equal, &non_function_constructor); 3237 __ j(not_equal, &non_function_constructor);
3233 3238
3234 // rax now contains the constructor function. Grab the 3239 // rax now contains the constructor function. Grab the
3235 // instance class name from there. 3240 // instance class name from there.
3236 __ movq(rax, FieldOperand(rax, JSFunction::kSharedFunctionInfoOffset)); 3241 __ movp(rax, FieldOperand(rax, JSFunction::kSharedFunctionInfoOffset));
3237 __ movq(rax, FieldOperand(rax, SharedFunctionInfo::kInstanceClassNameOffset)); 3242 __ movp(rax, FieldOperand(rax, SharedFunctionInfo::kInstanceClassNameOffset));
3238 __ jmp(&done); 3243 __ jmp(&done);
3239 3244
3240 // Functions have class 'Function'. 3245 // Functions have class 'Function'.
3241 __ bind(&function); 3246 __ bind(&function);
3242 __ Move(rax, isolate()->factory()->function_class_string()); 3247 __ Move(rax, isolate()->factory()->function_class_string());
3243 __ jmp(&done); 3248 __ jmp(&done);
3244 3249
3245 // Objects with a non-function constructor have class 'Object'. 3250 // Objects with a non-function constructor have class 'Object'.
3246 __ bind(&non_function_constructor); 3251 __ bind(&non_function_constructor);
3247 __ Move(rax, isolate()->factory()->Object_string()); 3252 __ Move(rax, isolate()->factory()->Object_string());
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
3311 ASSERT(args->length() == 1); 3316 ASSERT(args->length() == 1);
3312 3317
3313 VisitForAccumulatorValue(args->at(0)); // Load the object. 3318 VisitForAccumulatorValue(args->at(0)); // Load the object.
3314 3319
3315 Label done; 3320 Label done;
3316 // If the object is a smi return the object. 3321 // If the object is a smi return the object.
3317 __ JumpIfSmi(rax, &done); 3322 __ JumpIfSmi(rax, &done);
3318 // If the object is not a value type, return the object. 3323 // If the object is not a value type, return the object.
3319 __ CmpObjectType(rax, JS_VALUE_TYPE, rbx); 3324 __ CmpObjectType(rax, JS_VALUE_TYPE, rbx);
3320 __ j(not_equal, &done); 3325 __ j(not_equal, &done);
3321 __ movq(rax, FieldOperand(rax, JSValue::kValueOffset)); 3326 __ movp(rax, FieldOperand(rax, JSValue::kValueOffset));
3322 3327
3323 __ bind(&done); 3328 __ bind(&done);
3324 context()->Plug(rax); 3329 context()->Plug(rax);
3325 } 3330 }
3326 3331
3327 3332
3328 void FullCodeGenerator::EmitDateField(CallRuntime* expr) { 3333 void FullCodeGenerator::EmitDateField(CallRuntime* expr) {
3329 ZoneList<Expression*>* args = expr->arguments(); 3334 ZoneList<Expression*>* args = expr->arguments();
3330 ASSERT(args->length() == 2); 3335 ASSERT(args->length() == 2);
3331 ASSERT_NE(NULL, args->at(1)->AsLiteral()); 3336 ASSERT_NE(NULL, args->at(1)->AsLiteral());
3332 Smi* index = Smi::cast(*(args->at(1)->AsLiteral()->value())); 3337 Smi* index = Smi::cast(*(args->at(1)->AsLiteral()->value()));
3333 3338
3334 VisitForAccumulatorValue(args->at(0)); // Load the object. 3339 VisitForAccumulatorValue(args->at(0)); // Load the object.
3335 3340
3336 Label runtime, done, not_date_object; 3341 Label runtime, done, not_date_object;
3337 Register object = rax; 3342 Register object = rax;
3338 Register result = rax; 3343 Register result = rax;
3339 Register scratch = rcx; 3344 Register scratch = rcx;
3340 3345
3341 __ JumpIfSmi(object, &not_date_object); 3346 __ JumpIfSmi(object, &not_date_object);
3342 __ CmpObjectType(object, JS_DATE_TYPE, scratch); 3347 __ CmpObjectType(object, JS_DATE_TYPE, scratch);
3343 __ j(not_equal, &not_date_object); 3348 __ j(not_equal, &not_date_object);
3344 3349
3345 if (index->value() == 0) { 3350 if (index->value() == 0) {
3346 __ movq(result, FieldOperand(object, JSDate::kValueOffset)); 3351 __ movp(result, FieldOperand(object, JSDate::kValueOffset));
3347 __ jmp(&done); 3352 __ jmp(&done);
3348 } else { 3353 } else {
3349 if (index->value() < JSDate::kFirstUncachedField) { 3354 if (index->value() < JSDate::kFirstUncachedField) {
3350 ExternalReference stamp = ExternalReference::date_cache_stamp(isolate()); 3355 ExternalReference stamp = ExternalReference::date_cache_stamp(isolate());
3351 Operand stamp_operand = __ ExternalOperand(stamp); 3356 Operand stamp_operand = __ ExternalOperand(stamp);
3352 __ movq(scratch, stamp_operand); 3357 __ movp(scratch, stamp_operand);
3353 __ cmpq(scratch, FieldOperand(object, JSDate::kCacheStampOffset)); 3358 __ cmpq(scratch, FieldOperand(object, JSDate::kCacheStampOffset));
3354 __ j(not_equal, &runtime, Label::kNear); 3359 __ j(not_equal, &runtime, Label::kNear);
3355 __ movq(result, FieldOperand(object, JSDate::kValueOffset + 3360 __ movp(result, FieldOperand(object, JSDate::kValueOffset +
3356 kPointerSize * index->value())); 3361 kPointerSize * index->value()));
3357 __ jmp(&done); 3362 __ jmp(&done);
3358 } 3363 }
3359 __ bind(&runtime); 3364 __ bind(&runtime);
3360 __ PrepareCallCFunction(2); 3365 __ PrepareCallCFunction(2);
3361 __ movq(arg_reg_1, object); 3366 __ movp(arg_reg_1, object);
3362 __ Move(arg_reg_2, index, RelocInfo::NONE64); 3367 __ Move(arg_reg_2, index, RelocInfo::NONE64);
3363 __ CallCFunction(ExternalReference::get_date_field_function(isolate()), 2); 3368 __ CallCFunction(ExternalReference::get_date_field_function(isolate()), 2);
3364 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 3369 __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
3365 __ jmp(&done); 3370 __ jmp(&done);
3366 } 3371 }
3367 3372
3368 __ bind(&not_date_object); 3373 __ bind(&not_date_object);
3369 __ CallRuntime(Runtime::kThrowNotDateError, 0); 3374 __ CallRuntime(Runtime::kThrowNotDateError, 0);
3370 __ bind(&done); 3375 __ bind(&done);
3371 context()->Plug(rax); 3376 context()->Plug(rax);
3372 } 3377 }
3373 3378
3374 3379
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
3460 3465
3461 Label done; 3466 Label done;
3462 // If the object is a smi, return the value. 3467 // If the object is a smi, return the value.
3463 __ JumpIfSmi(rbx, &done); 3468 __ JumpIfSmi(rbx, &done);
3464 3469
3465 // If the object is not a value type, return the value. 3470 // If the object is not a value type, return the value.
3466 __ CmpObjectType(rbx, JS_VALUE_TYPE, rcx); 3471 __ CmpObjectType(rbx, JS_VALUE_TYPE, rcx);
3467 __ j(not_equal, &done); 3472 __ j(not_equal, &done);
3468 3473
3469 // Store the value. 3474 // Store the value.
3470 __ movq(FieldOperand(rbx, JSValue::kValueOffset), rax); 3475 __ movp(FieldOperand(rbx, JSValue::kValueOffset), rax);
3471 // Update the write barrier. Save the value as it will be 3476 // Update the write barrier. Save the value as it will be
3472 // overwritten by the write barrier code and is needed afterward. 3477 // overwritten by the write barrier code and is needed afterward.
3473 __ movq(rdx, rax); 3478 __ movp(rdx, rax);
3474 __ RecordWriteField(rbx, JSValue::kValueOffset, rdx, rcx, kDontSaveFPRegs); 3479 __ RecordWriteField(rbx, JSValue::kValueOffset, rdx, rcx, kDontSaveFPRegs);
3475 3480
3476 __ bind(&done); 3481 __ bind(&done);
3477 context()->Plug(rax); 3482 context()->Plug(rax);
3478 } 3483 }
3479 3484
3480 3485
3481 void FullCodeGenerator::EmitNumberToString(CallRuntime* expr) { 3486 void FullCodeGenerator::EmitNumberToString(CallRuntime* expr) {
3482 ZoneList<Expression*>* args = expr->arguments(); 3487 ZoneList<Expression*>* args = expr->arguments();
3483 ASSERT_EQ(args->length(), 1); 3488 ASSERT_EQ(args->length(), 1);
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after
3600 generator.GenerateSlow(masm_, call_helper); 3605 generator.GenerateSlow(masm_, call_helper);
3601 3606
3602 __ bind(&done); 3607 __ bind(&done);
3603 context()->Plug(result); 3608 context()->Plug(result);
3604 } 3609 }
3605 3610
3606 3611
3607 void FullCodeGenerator::EmitStringAdd(CallRuntime* expr) { 3612 void FullCodeGenerator::EmitStringAdd(CallRuntime* expr) {
3608 ZoneList<Expression*>* args = expr->arguments(); 3613 ZoneList<Expression*>* args = expr->arguments();
3609 ASSERT_EQ(2, args->length()); 3614 ASSERT_EQ(2, args->length());
3615 VisitForStackValue(args->at(0));
3616 VisitForAccumulatorValue(args->at(1));
3610 3617
3611 if (FLAG_new_string_add) { 3618 __ pop(rdx);
3612 VisitForStackValue(args->at(0)); 3619 StringAddStub stub(STRING_ADD_CHECK_BOTH, NOT_TENURED);
3613 VisitForAccumulatorValue(args->at(1)); 3620 __ CallStub(&stub);
3614
3615 __ pop(rdx);
3616 NewStringAddStub stub(STRING_ADD_CHECK_BOTH, NOT_TENURED);
3617 __ CallStub(&stub);
3618 } else {
3619 VisitForStackValue(args->at(0));
3620 VisitForStackValue(args->at(1));
3621
3622 StringAddStub stub(STRING_ADD_CHECK_BOTH);
3623 __ CallStub(&stub);
3624 }
3625 context()->Plug(rax); 3621 context()->Plug(rax);
3626 } 3622 }
3627 3623
3628 3624
3629 void FullCodeGenerator::EmitStringCompare(CallRuntime* expr) { 3625 void FullCodeGenerator::EmitStringCompare(CallRuntime* expr) {
3630 ZoneList<Expression*>* args = expr->arguments(); 3626 ZoneList<Expression*>* args = expr->arguments();
3631 ASSERT_EQ(2, args->length()); 3627 ASSERT_EQ(2, args->length());
3632 3628
3633 VisitForStackValue(args->at(0)); 3629 VisitForStackValue(args->at(0));
3634 VisitForStackValue(args->at(1)); 3630 VisitForStackValue(args->at(1));
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
3669 } 3665 }
3670 VisitForAccumulatorValue(args->last()); // Function. 3666 VisitForAccumulatorValue(args->last()); // Function.
3671 3667
3672 Label runtime, done; 3668 Label runtime, done;
3673 // Check for non-function argument (including proxy). 3669 // Check for non-function argument (including proxy).
3674 __ JumpIfSmi(rax, &runtime); 3670 __ JumpIfSmi(rax, &runtime);
3675 __ CmpObjectType(rax, JS_FUNCTION_TYPE, rbx); 3671 __ CmpObjectType(rax, JS_FUNCTION_TYPE, rbx);
3676 __ j(not_equal, &runtime); 3672 __ j(not_equal, &runtime);
3677 3673
3678 // InvokeFunction requires the function in rdi. Move it in there. 3674 // InvokeFunction requires the function in rdi. Move it in there.
3679 __ movq(rdi, result_register()); 3675 __ movp(rdi, result_register());
3680 ParameterCount count(arg_count); 3676 ParameterCount count(arg_count);
3681 __ InvokeFunction(rdi, count, CALL_FUNCTION, NullCallWrapper()); 3677 __ InvokeFunction(rdi, count, CALL_FUNCTION, NullCallWrapper());
3682 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 3678 __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
3683 __ jmp(&done); 3679 __ jmp(&done);
3684 3680
3685 __ bind(&runtime); 3681 __ bind(&runtime);
3686 __ push(rax); 3682 __ push(rax);
3687 __ CallRuntime(Runtime::kCall, args->length()); 3683 __ CallRuntime(Runtime::kCall, args->length());
3688 __ bind(&done); 3684 __ bind(&done);
3689 3685
3690 context()->Plug(rax); 3686 context()->Plug(rax);
3691 } 3687 }
3692 3688
(...skipping 24 matching lines...) Expand all
3717 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); 3713 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
3718 context()->Plug(rax); 3714 context()->Plug(rax);
3719 return; 3715 return;
3720 } 3716 }
3721 3717
3722 VisitForAccumulatorValue(args->at(1)); 3718 VisitForAccumulatorValue(args->at(1));
3723 3719
3724 Register key = rax; 3720 Register key = rax;
3725 Register cache = rbx; 3721 Register cache = rbx;
3726 Register tmp = rcx; 3722 Register tmp = rcx;
3727 __ movq(cache, ContextOperand(rsi, Context::GLOBAL_OBJECT_INDEX)); 3723 __ movp(cache, ContextOperand(rsi, Context::GLOBAL_OBJECT_INDEX));
3728 __ movq(cache, 3724 __ movp(cache,
3729 FieldOperand(cache, GlobalObject::kNativeContextOffset)); 3725 FieldOperand(cache, GlobalObject::kNativeContextOffset));
3730 __ movq(cache, 3726 __ movp(cache,
3731 ContextOperand(cache, Context::JSFUNCTION_RESULT_CACHES_INDEX)); 3727 ContextOperand(cache, Context::JSFUNCTION_RESULT_CACHES_INDEX));
3732 __ movq(cache, 3728 __ movp(cache,
3733 FieldOperand(cache, FixedArray::OffsetOfElementAt(cache_id))); 3729 FieldOperand(cache, FixedArray::OffsetOfElementAt(cache_id)));
3734 3730
3735 Label done, not_found; 3731 Label done, not_found;
3736 // tmp now holds finger offset as a smi. 3732 // tmp now holds finger offset as a smi.
3737 STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize == 1); 3733 STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize == 1);
3738 __ movq(tmp, FieldOperand(cache, JSFunctionResultCache::kFingerOffset)); 3734 __ movp(tmp, FieldOperand(cache, JSFunctionResultCache::kFingerOffset));
3739 SmiIndex index = 3735 SmiIndex index =
3740 __ SmiToIndex(kScratchRegister, tmp, kPointerSizeLog2); 3736 __ SmiToIndex(kScratchRegister, tmp, kPointerSizeLog2);
3741 __ cmpq(key, FieldOperand(cache, 3737 __ cmpq(key, FieldOperand(cache,
3742 index.reg, 3738 index.reg,
3743 index.scale, 3739 index.scale,
3744 FixedArray::kHeaderSize)); 3740 FixedArray::kHeaderSize));
3745 __ j(not_equal, &not_found, Label::kNear); 3741 __ j(not_equal, &not_found, Label::kNear);
3746 __ movq(rax, FieldOperand(cache, 3742 __ movp(rax, FieldOperand(cache,
3747 index.reg, 3743 index.reg,
3748 index.scale, 3744 index.scale,
3749 FixedArray::kHeaderSize + kPointerSize)); 3745 FixedArray::kHeaderSize + kPointerSize));
3750 __ jmp(&done, Label::kNear); 3746 __ jmp(&done, Label::kNear);
3751 3747
3752 __ bind(&not_found); 3748 __ bind(&not_found);
3753 // Call runtime to perform the lookup. 3749 // Call runtime to perform the lookup.
3754 __ push(cache); 3750 __ push(cache);
3755 __ push(key); 3751 __ push(key);
3756 __ CallRuntime(Runtime::kGetFromCache, 2); 3752 __ CallRuntime(Runtime::kGetFromCache, 2);
(...skipping 15 matching lines...) Expand all
3772 VisitForAccumulatorValue(args->at(1)); 3768 VisitForAccumulatorValue(args->at(1));
3773 __ pop(left); 3769 __ pop(left);
3774 3770
3775 Label done, fail, ok; 3771 Label done, fail, ok;
3776 __ cmpq(left, right); 3772 __ cmpq(left, right);
3777 __ j(equal, &ok, Label::kNear); 3773 __ j(equal, &ok, Label::kNear);
3778 // Fail if either is a non-HeapObject. 3774 // Fail if either is a non-HeapObject.
3779 Condition either_smi = masm()->CheckEitherSmi(left, right, tmp); 3775 Condition either_smi = masm()->CheckEitherSmi(left, right, tmp);
3780 __ j(either_smi, &fail, Label::kNear); 3776 __ j(either_smi, &fail, Label::kNear);
3781 __ j(zero, &fail, Label::kNear); 3777 __ j(zero, &fail, Label::kNear);
3782 __ movq(tmp, FieldOperand(left, HeapObject::kMapOffset)); 3778 __ movp(tmp, FieldOperand(left, HeapObject::kMapOffset));
3783 __ cmpb(FieldOperand(tmp, Map::kInstanceTypeOffset), 3779 __ cmpb(FieldOperand(tmp, Map::kInstanceTypeOffset),
3784 Immediate(JS_REGEXP_TYPE)); 3780 Immediate(JS_REGEXP_TYPE));
3785 __ j(not_equal, &fail, Label::kNear); 3781 __ j(not_equal, &fail, Label::kNear);
3786 __ cmpq(tmp, FieldOperand(right, HeapObject::kMapOffset)); 3782 __ cmpq(tmp, FieldOperand(right, HeapObject::kMapOffset));
3787 __ j(not_equal, &fail, Label::kNear); 3783 __ j(not_equal, &fail, Label::kNear);
3788 __ movq(tmp, FieldOperand(left, JSRegExp::kDataOffset)); 3784 __ movp(tmp, FieldOperand(left, JSRegExp::kDataOffset));
3789 __ cmpq(tmp, FieldOperand(right, JSRegExp::kDataOffset)); 3785 __ cmpq(tmp, FieldOperand(right, JSRegExp::kDataOffset));
3790 __ j(equal, &ok, Label::kNear); 3786 __ j(equal, &ok, Label::kNear);
3791 __ bind(&fail); 3787 __ bind(&fail);
3792 __ Move(rax, isolate()->factory()->false_value()); 3788 __ Move(rax, isolate()->factory()->false_value());
3793 __ jmp(&done, Label::kNear); 3789 __ jmp(&done, Label::kNear);
3794 __ bind(&ok); 3790 __ bind(&ok);
3795 __ Move(rax, isolate()->factory()->true_value()); 3791 __ Move(rax, isolate()->factory()->true_value());
3796 __ bind(&done); 3792 __ bind(&done);
3797 3793
3798 context()->Plug(rax); 3794 context()->Plug(rax);
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
3873 // Check that the array is a JSArray 3869 // Check that the array is a JSArray
3874 __ JumpIfSmi(array, &bailout); 3870 __ JumpIfSmi(array, &bailout);
3875 __ CmpObjectType(array, JS_ARRAY_TYPE, scratch); 3871 __ CmpObjectType(array, JS_ARRAY_TYPE, scratch);
3876 __ j(not_equal, &bailout); 3872 __ j(not_equal, &bailout);
3877 3873
3878 // Check that the array has fast elements. 3874 // Check that the array has fast elements.
3879 __ CheckFastElements(scratch, &bailout); 3875 __ CheckFastElements(scratch, &bailout);
3880 3876
3881 // Array has fast elements, so its length must be a smi. 3877 // Array has fast elements, so its length must be a smi.
3882 // If the array has length zero, return the empty string. 3878 // If the array has length zero, return the empty string.
3883 __ movq(array_length, FieldOperand(array, JSArray::kLengthOffset)); 3879 __ movp(array_length, FieldOperand(array, JSArray::kLengthOffset));
3884 __ SmiCompare(array_length, Smi::FromInt(0)); 3880 __ SmiCompare(array_length, Smi::FromInt(0));
3885 __ j(not_zero, &non_trivial_array); 3881 __ j(not_zero, &non_trivial_array);
3886 __ LoadRoot(rax, Heap::kempty_stringRootIndex); 3882 __ LoadRoot(rax, Heap::kempty_stringRootIndex);
3887 __ jmp(&return_result); 3883 __ jmp(&return_result);
3888 3884
3889 // Save the array length on the stack. 3885 // Save the array length on the stack.
3890 __ bind(&non_trivial_array); 3886 __ bind(&non_trivial_array);
3891 __ SmiToInteger32(array_length, array_length); 3887 __ SmiToInteger32(array_length, array_length);
3892 __ movl(array_length_operand, array_length); 3888 __ movl(array_length_operand, array_length);
3893 3889
3894 // Save the FixedArray containing array's elements. 3890 // Save the FixedArray containing array's elements.
3895 // End of array's live range. 3891 // End of array's live range.
3896 elements = array; 3892 elements = array;
3897 __ movq(elements, FieldOperand(array, JSArray::kElementsOffset)); 3893 __ movp(elements, FieldOperand(array, JSArray::kElementsOffset));
3898 array = no_reg; 3894 array = no_reg;
3899 3895
3900 3896
3901 // Check that all array elements are sequential ASCII strings, and 3897 // Check that all array elements are sequential ASCII strings, and
3902 // accumulate the sum of their lengths, as a smi-encoded value. 3898 // accumulate the sum of their lengths, as a smi-encoded value.
3903 __ Set(index, 0); 3899 __ Set(index, 0);
3904 __ Set(string_length, 0); 3900 __ Set(string_length, 0);
3905 // Loop condition: while (index < array_length). 3901 // Loop condition: while (index < array_length).
3906 // Live loop registers: index(int32), array_length(int32), string(String*), 3902 // Live loop registers: index(int32), array_length(int32), string(String*),
3907 // scratch, string_length(int32), elements(FixedArray*). 3903 // scratch, string_length(int32), elements(FixedArray*).
3908 if (generate_debug_code_) { 3904 if (generate_debug_code_) {
3909 __ cmpq(index, array_length); 3905 __ cmpq(index, array_length);
3910 __ Assert(below, kNoEmptyArraysHereInEmitFastAsciiArrayJoin); 3906 __ Assert(below, kNoEmptyArraysHereInEmitFastAsciiArrayJoin);
3911 } 3907 }
3912 __ bind(&loop); 3908 __ bind(&loop);
3913 __ movq(string, FieldOperand(elements, 3909 __ movp(string, FieldOperand(elements,
3914 index, 3910 index,
3915 times_pointer_size, 3911 times_pointer_size,
3916 FixedArray::kHeaderSize)); 3912 FixedArray::kHeaderSize));
3917 __ JumpIfSmi(string, &bailout); 3913 __ JumpIfSmi(string, &bailout);
3918 __ movq(scratch, FieldOperand(string, HeapObject::kMapOffset)); 3914 __ movp(scratch, FieldOperand(string, HeapObject::kMapOffset));
3919 __ movzxbl(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset)); 3915 __ movzxbl(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset));
3920 __ andb(scratch, Immediate( 3916 __ andb(scratch, Immediate(
3921 kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask)); 3917 kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask));
3922 __ cmpb(scratch, Immediate(kStringTag | kOneByteStringTag | kSeqStringTag)); 3918 __ cmpb(scratch, Immediate(kStringTag | kOneByteStringTag | kSeqStringTag));
3923 __ j(not_equal, &bailout); 3919 __ j(not_equal, &bailout);
3924 __ AddSmiField(string_length, 3920 __ AddSmiField(string_length,
3925 FieldOperand(string, SeqOneByteString::kLengthOffset)); 3921 FieldOperand(string, SeqOneByteString::kLengthOffset));
3926 __ j(overflow, &bailout); 3922 __ j(overflow, &bailout);
3927 __ incl(index); 3923 __ incl(index);
3928 __ cmpl(index, array_length); 3924 __ cmpl(index, array_length);
3929 __ j(less, &loop); 3925 __ j(less, &loop);
3930 3926
3931 // Live registers: 3927 // Live registers:
3932 // string_length: Sum of string lengths. 3928 // string_length: Sum of string lengths.
3933 // elements: FixedArray of strings. 3929 // elements: FixedArray of strings.
3934 // index: Array length. 3930 // index: Array length.
3935 // array_length: Array length. 3931 // array_length: Array length.
3936 3932
3937 // If array_length is 1, return elements[0], a string. 3933 // If array_length is 1, return elements[0], a string.
3938 __ cmpl(array_length, Immediate(1)); 3934 __ cmpl(array_length, Immediate(1));
3939 __ j(not_equal, &not_size_one_array); 3935 __ j(not_equal, &not_size_one_array);
3940 __ movq(rax, FieldOperand(elements, FixedArray::kHeaderSize)); 3936 __ movp(rax, FieldOperand(elements, FixedArray::kHeaderSize));
3941 __ jmp(&return_result); 3937 __ jmp(&return_result);
3942 3938
3943 __ bind(&not_size_one_array); 3939 __ bind(&not_size_one_array);
3944 3940
3945 // End of array_length live range. 3941 // End of array_length live range.
3946 result_pos = array_length; 3942 result_pos = array_length;
3947 array_length = no_reg; 3943 array_length = no_reg;
3948 3944
3949 // Live registers: 3945 // Live registers:
3950 // string_length: Sum of string lengths. 3946 // string_length: Sum of string lengths.
3951 // elements: FixedArray of strings. 3947 // elements: FixedArray of strings.
3952 // index: Array length. 3948 // index: Array length.
3953 3949
3954 // Check that the separator is a sequential ASCII string. 3950 // Check that the separator is a sequential ASCII string.
3955 __ movq(string, separator_operand); 3951 __ movp(string, separator_operand);
3956 __ JumpIfSmi(string, &bailout); 3952 __ JumpIfSmi(string, &bailout);
3957 __ movq(scratch, FieldOperand(string, HeapObject::kMapOffset)); 3953 __ movp(scratch, FieldOperand(string, HeapObject::kMapOffset));
3958 __ movzxbl(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset)); 3954 __ movzxbl(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset));
3959 __ andb(scratch, Immediate( 3955 __ andb(scratch, Immediate(
3960 kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask)); 3956 kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask));
3961 __ cmpb(scratch, Immediate(kStringTag | kOneByteStringTag | kSeqStringTag)); 3957 __ cmpb(scratch, Immediate(kStringTag | kOneByteStringTag | kSeqStringTag));
3962 __ j(not_equal, &bailout); 3958 __ j(not_equal, &bailout);
3963 3959
3964 // Live registers: 3960 // Live registers:
3965 // string_length: Sum of string lengths. 3961 // string_length: Sum of string lengths.
3966 // elements: FixedArray of strings. 3962 // elements: FixedArray of strings.
3967 // index: Array length. 3963 // index: Array length.
3968 // string: Separator string. 3964 // string: Separator string.
3969 3965
3970 // Add (separator length times (array_length - 1)) to string_length. 3966 // Add (separator length times (array_length - 1)) to string_length.
3971 __ SmiToInteger32(scratch, 3967 __ SmiToInteger32(scratch,
3972 FieldOperand(string, SeqOneByteString::kLengthOffset)); 3968 FieldOperand(string, SeqOneByteString::kLengthOffset));
3973 __ decl(index); 3969 __ decl(index);
3974 __ imull(scratch, index); 3970 __ imull(scratch, index);
3975 __ j(overflow, &bailout); 3971 __ j(overflow, &bailout);
3976 __ addl(string_length, scratch); 3972 __ addl(string_length, scratch);
3977 __ j(overflow, &bailout); 3973 __ j(overflow, &bailout);
3978 3974
3979 // Live registers and stack values: 3975 // Live registers and stack values:
3980 // string_length: Total length of result string. 3976 // string_length: Total length of result string.
3981 // elements: FixedArray of strings. 3977 // elements: FixedArray of strings.
3982 __ AllocateAsciiString(result_pos, string_length, scratch, 3978 __ AllocateAsciiString(result_pos, string_length, scratch,
3983 index, string, &bailout); 3979 index, string, &bailout);
3984 __ movq(result_operand, result_pos); 3980 __ movp(result_operand, result_pos);
3985 __ lea(result_pos, FieldOperand(result_pos, SeqOneByteString::kHeaderSize)); 3981 __ lea(result_pos, FieldOperand(result_pos, SeqOneByteString::kHeaderSize));
3986 3982
3987 __ movq(string, separator_operand); 3983 __ movp(string, separator_operand);
3988 __ SmiCompare(FieldOperand(string, SeqOneByteString::kLengthOffset), 3984 __ SmiCompare(FieldOperand(string, SeqOneByteString::kLengthOffset),
3989 Smi::FromInt(1)); 3985 Smi::FromInt(1));
3990 __ j(equal, &one_char_separator); 3986 __ j(equal, &one_char_separator);
3991 __ j(greater, &long_separator); 3987 __ j(greater, &long_separator);
3992 3988
3993 3989
3994 // Empty separator case: 3990 // Empty separator case:
3995 __ Set(index, 0); 3991 __ Set(index, 0);
3996 __ movl(scratch, array_length_operand); 3992 __ movl(scratch, array_length_operand);
3997 __ jmp(&loop_1_condition); 3993 __ jmp(&loop_1_condition);
3998 // Loop condition: while (index < array_length). 3994 // Loop condition: while (index < array_length).
3999 __ bind(&loop_1); 3995 __ bind(&loop_1);
4000 // Each iteration of the loop concatenates one string to the result. 3996 // Each iteration of the loop concatenates one string to the result.
4001 // Live values in registers: 3997 // Live values in registers:
4002 // index: which element of the elements array we are adding to the result. 3998 // index: which element of the elements array we are adding to the result.
4003 // result_pos: the position to which we are currently copying characters. 3999 // result_pos: the position to which we are currently copying characters.
4004 // elements: the FixedArray of strings we are joining. 4000 // elements: the FixedArray of strings we are joining.
4005 // scratch: array length. 4001 // scratch: array length.
4006 4002
4007 // Get string = array[index]. 4003 // Get string = array[index].
4008 __ movq(string, FieldOperand(elements, index, 4004 __ movp(string, FieldOperand(elements, index,
4009 times_pointer_size, 4005 times_pointer_size,
4010 FixedArray::kHeaderSize)); 4006 FixedArray::kHeaderSize));
4011 __ SmiToInteger32(string_length, 4007 __ SmiToInteger32(string_length,
4012 FieldOperand(string, String::kLengthOffset)); 4008 FieldOperand(string, String::kLengthOffset));
4013 __ lea(string, 4009 __ lea(string,
4014 FieldOperand(string, SeqOneByteString::kHeaderSize)); 4010 FieldOperand(string, SeqOneByteString::kHeaderSize));
4015 __ CopyBytes(result_pos, string, string_length); 4011 __ CopyBytes(result_pos, string, string_length);
4016 __ incl(index); 4012 __ incl(index);
4017 __ bind(&loop_1_condition); 4013 __ bind(&loop_1_condition);
4018 __ cmpl(index, scratch); 4014 __ cmpl(index, scratch);
(...skipping 23 matching lines...) Expand all
4042 // index: which element of the elements array we are adding to the result. 4038 // index: which element of the elements array we are adding to the result.
4043 // result_pos: the position to which we are currently copying characters. 4039 // result_pos: the position to which we are currently copying characters.
4044 // scratch: Separator character. 4040 // scratch: Separator character.
4045 4041
4046 // Copy the separator character to the result. 4042 // Copy the separator character to the result.
4047 __ movb(Operand(result_pos, 0), scratch); 4043 __ movb(Operand(result_pos, 0), scratch);
4048 __ incq(result_pos); 4044 __ incq(result_pos);
4049 4045
4050 __ bind(&loop_2_entry); 4046 __ bind(&loop_2_entry);
4051 // Get string = array[index]. 4047 // Get string = array[index].
4052 __ movq(string, FieldOperand(elements, index, 4048 __ movp(string, FieldOperand(elements, index,
4053 times_pointer_size, 4049 times_pointer_size,
4054 FixedArray::kHeaderSize)); 4050 FixedArray::kHeaderSize));
4055 __ SmiToInteger32(string_length, 4051 __ SmiToInteger32(string_length,
4056 FieldOperand(string, String::kLengthOffset)); 4052 FieldOperand(string, String::kLengthOffset));
4057 __ lea(string, 4053 __ lea(string,
4058 FieldOperand(string, SeqOneByteString::kHeaderSize)); 4054 FieldOperand(string, SeqOneByteString::kHeaderSize));
4059 __ CopyBytes(result_pos, string, string_length); 4055 __ CopyBytes(result_pos, string, string_length);
4060 __ incl(index); 4056 __ incl(index);
4061 __ cmpl(index, array_length_operand); 4057 __ cmpl(index, array_length_operand);
4062 __ j(less, &loop_2); // End while (index < length). 4058 __ j(less, &loop_2); // End while (index < length).
4063 __ jmp(&done); 4059 __ jmp(&done);
4064 4060
4065 4061
4066 // Long separator case (separator is more than one character). 4062 // Long separator case (separator is more than one character).
4067 __ bind(&long_separator); 4063 __ bind(&long_separator);
4068 4064
4069 // Make elements point to end of elements array, and index 4065 // Make elements point to end of elements array, and index
4070 // count from -array_length to zero, so we don't need to maintain 4066 // count from -array_length to zero, so we don't need to maintain
4071 // a loop limit. 4067 // a loop limit.
4072 __ movl(index, array_length_operand); 4068 __ movl(index, array_length_operand);
4073 __ lea(elements, FieldOperand(elements, index, times_pointer_size, 4069 __ lea(elements, FieldOperand(elements, index, times_pointer_size,
4074 FixedArray::kHeaderSize)); 4070 FixedArray::kHeaderSize));
4075 __ neg(index); 4071 __ neg(index);
4076 4072
4077 // Replace separator string with pointer to its first character, and 4073 // Replace separator string with pointer to its first character, and
4078 // make scratch be its length. 4074 // make scratch be its length.
4079 __ movq(string, separator_operand); 4075 __ movp(string, separator_operand);
4080 __ SmiToInteger32(scratch, 4076 __ SmiToInteger32(scratch,
4081 FieldOperand(string, String::kLengthOffset)); 4077 FieldOperand(string, String::kLengthOffset));
4082 __ lea(string, 4078 __ lea(string,
4083 FieldOperand(string, SeqOneByteString::kHeaderSize)); 4079 FieldOperand(string, SeqOneByteString::kHeaderSize));
4084 __ movq(separator_operand, string); 4080 __ movp(separator_operand, string);
4085 4081
4086 // Jump into the loop after the code that copies the separator, so the first 4082 // Jump into the loop after the code that copies the separator, so the first
4087 // element is not preceded by a separator 4083 // element is not preceded by a separator
4088 __ jmp(&loop_3_entry); 4084 __ jmp(&loop_3_entry);
4089 // Loop condition: while (index < length). 4085 // Loop condition: while (index < length).
4090 __ bind(&loop_3); 4086 __ bind(&loop_3);
4091 // Each iteration of the loop concatenates one string to the result. 4087 // Each iteration of the loop concatenates one string to the result.
4092 // Live values in registers: 4088 // Live values in registers:
4093 // index: which element of the elements array we are adding to the result. 4089 // index: which element of the elements array we are adding to the result.
4094 // result_pos: the position to which we are currently copying characters. 4090 // result_pos: the position to which we are currently copying characters.
4095 // scratch: Separator length. 4091 // scratch: Separator length.
4096 // separator_operand (rsp[0x10]): Address of first char of separator. 4092 // separator_operand (rsp[0x10]): Address of first char of separator.
4097 4093
4098 // Copy the separator to the result. 4094 // Copy the separator to the result.
4099 __ movq(string, separator_operand); 4095 __ movp(string, separator_operand);
4100 __ movl(string_length, scratch); 4096 __ movl(string_length, scratch);
4101 __ CopyBytes(result_pos, string, string_length, 2); 4097 __ CopyBytes(result_pos, string, string_length, 2);
4102 4098
4103 __ bind(&loop_3_entry); 4099 __ bind(&loop_3_entry);
4104 // Get string = array[index]. 4100 // Get string = array[index].
4105 __ movq(string, Operand(elements, index, times_pointer_size, 0)); 4101 __ movp(string, Operand(elements, index, times_pointer_size, 0));
4106 __ SmiToInteger32(string_length, 4102 __ SmiToInteger32(string_length,
4107 FieldOperand(string, String::kLengthOffset)); 4103 FieldOperand(string, String::kLengthOffset));
4108 __ lea(string, 4104 __ lea(string,
4109 FieldOperand(string, SeqOneByteString::kHeaderSize)); 4105 FieldOperand(string, SeqOneByteString::kHeaderSize));
4110 __ CopyBytes(result_pos, string, string_length); 4106 __ CopyBytes(result_pos, string, string_length);
4111 __ incq(index); 4107 __ incq(index);
4112 __ j(not_equal, &loop_3); // Loop while (index < 0). 4108 __ j(not_equal, &loop_3); // Loop while (index < 0).
4113 4109
4114 __ bind(&done); 4110 __ bind(&done);
4115 __ movq(rax, result_operand); 4111 __ movp(rax, result_operand);
4116 4112
4117 __ bind(&return_result); 4113 __ bind(&return_result);
4118 // Drop temp values from the stack, and restore context register. 4114 // Drop temp values from the stack, and restore context register.
4119 __ addq(rsp, Immediate(3 * kPointerSize)); 4115 __ addq(rsp, Immediate(3 * kPointerSize));
4120 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 4116 __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
4121 context()->Plug(rax); 4117 context()->Plug(rax);
4122 } 4118 }
4123 4119
4124 4120
4125 void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) { 4121 void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
4126 Handle<String> name = expr->name(); 4122 Handle<String> name = expr->name();
4127 if (name->length() > 0 && name->Get(0) == '_') { 4123 if (name->length() > 0 && name->Get(0) == '_') {
4128 Comment cmnt(masm_, "[ InlineRuntimeCall"); 4124 Comment cmnt(masm_, "[ InlineRuntimeCall");
4129 EmitInlineRuntimeCall(expr); 4125 EmitInlineRuntimeCall(expr);
4130 return; 4126 return;
4131 } 4127 }
4132 4128
4133 Comment cmnt(masm_, "[ CallRuntime"); 4129 Comment cmnt(masm_, "[ CallRuntime");
4134 ZoneList<Expression*>* args = expr->arguments(); 4130 ZoneList<Expression*>* args = expr->arguments();
4135 4131
4136 if (expr->is_jsruntime()) { 4132 if (expr->is_jsruntime()) {
4137 // Prepare for calling JS runtime function. 4133 // Prepare for calling JS runtime function.
4138 __ movq(rax, GlobalObjectOperand()); 4134 __ movp(rax, GlobalObjectOperand());
4139 __ push(FieldOperand(rax, GlobalObject::kBuiltinsOffset)); 4135 __ push(FieldOperand(rax, GlobalObject::kBuiltinsOffset));
4140 } 4136 }
4141 4137
4142 // Push the arguments ("left-to-right"). 4138 // Push the arguments ("left-to-right").
4143 int arg_count = args->length(); 4139 int arg_count = args->length();
4144 for (int i = 0; i < arg_count; i++) { 4140 for (int i = 0; i < arg_count; i++) {
4145 VisitForStackValue(args->at(i)); 4141 VisitForStackValue(args->at(i));
4146 } 4142 }
4147 4143
4148 if (expr->is_jsruntime()) { 4144 if (expr->is_jsruntime()) {
4149 // Call the JS runtime function using a call IC. 4145 // Call the JS runtime function using a call IC.
4150 __ Move(rcx, expr->name()); 4146 __ Move(rcx, expr->name());
4151 Handle<Code> ic = isolate()->stub_cache()->ComputeCallInitialize(arg_count); 4147 Handle<Code> ic = isolate()->stub_cache()->ComputeCallInitialize(arg_count);
4152 CallIC(ic, NOT_CONTEXTUAL, expr->CallRuntimeFeedbackId()); 4148 CallIC(ic, NOT_CONTEXTUAL, expr->CallRuntimeFeedbackId());
4153 // Restore context register. 4149 // Restore context register.
4154 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 4150 __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
4155 } else { 4151 } else {
4156 __ CallRuntime(expr->function(), arg_count); 4152 __ CallRuntime(expr->function(), arg_count);
4157 } 4153 }
4158 context()->Plug(rax); 4154 context()->Plug(rax);
4159 } 4155 }
4160 4156
4161 4157
4162 void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { 4158 void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
4163 switch (expr->op()) { 4159 switch (expr->op()) {
4164 case Token::DELETE: { 4160 case Token::DELETE: {
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after
4308 if (expr->is_postfix() && !context()->IsEffect()) { 4304 if (expr->is_postfix() && !context()->IsEffect()) {
4309 __ Push(Smi::FromInt(0)); 4305 __ Push(Smi::FromInt(0));
4310 } 4306 }
4311 if (assign_type == NAMED_PROPERTY) { 4307 if (assign_type == NAMED_PROPERTY) {
4312 VisitForAccumulatorValue(prop->obj()); 4308 VisitForAccumulatorValue(prop->obj());
4313 __ push(rax); // Copy of receiver, needed for later store. 4309 __ push(rax); // Copy of receiver, needed for later store.
4314 EmitNamedPropertyLoad(prop); 4310 EmitNamedPropertyLoad(prop);
4315 } else { 4311 } else {
4316 VisitForStackValue(prop->obj()); 4312 VisitForStackValue(prop->obj());
4317 VisitForAccumulatorValue(prop->key()); 4313 VisitForAccumulatorValue(prop->key());
4318 __ movq(rdx, Operand(rsp, 0)); // Leave receiver on stack 4314 __ movp(rdx, Operand(rsp, 0)); // Leave receiver on stack
4319 __ push(rax); // Copy of key, needed for later store. 4315 __ push(rax); // Copy of key, needed for later store.
4320 EmitKeyedPropertyLoad(prop); 4316 EmitKeyedPropertyLoad(prop);
4321 } 4317 }
4322 } 4318 }
4323 4319
4324 // We need a second deoptimization point after loading the value 4320 // We need a second deoptimization point after loading the value
4325 // in case evaluating the property load my have a side effect. 4321 // in case evaluating the property load my have a side effect.
4326 if (assign_type == VARIABLE) { 4322 if (assign_type == VARIABLE) {
4327 PrepareForBailout(expr->expression(), TOS_REG); 4323 PrepareForBailout(expr->expression(), TOS_REG);
4328 } else { 4324 } else {
(...skipping 11 matching lines...) Expand all
4340 if (expr->is_postfix()) { 4336 if (expr->is_postfix()) {
4341 if (!context()->IsEffect()) { 4337 if (!context()->IsEffect()) {
4342 // Save the result on the stack. If we have a named or keyed property 4338 // Save the result on the stack. If we have a named or keyed property
4343 // we store the result under the receiver that is currently on top 4339 // we store the result under the receiver that is currently on top
4344 // of the stack. 4340 // of the stack.
4345 switch (assign_type) { 4341 switch (assign_type) {
4346 case VARIABLE: 4342 case VARIABLE:
4347 __ push(rax); 4343 __ push(rax);
4348 break; 4344 break;
4349 case NAMED_PROPERTY: 4345 case NAMED_PROPERTY:
4350 __ movq(Operand(rsp, kPointerSize), rax); 4346 __ movp(Operand(rsp, kPointerSize), rax);
4351 break; 4347 break;
4352 case KEYED_PROPERTY: 4348 case KEYED_PROPERTY:
4353 __ movq(Operand(rsp, 2 * kPointerSize), rax); 4349 __ movp(Operand(rsp, 2 * kPointerSize), rax);
4354 break; 4350 break;
4355 } 4351 }
4356 } 4352 }
4357 } 4353 }
4358 4354
4359 SmiOperationExecutionMode mode; 4355 SmiOperationExecutionMode mode;
4360 mode.Add(PRESERVE_SOURCE_REGISTER); 4356 mode.Add(PRESERVE_SOURCE_REGISTER);
4361 mode.Add(BAILOUT_ON_NO_OVERFLOW); 4357 mode.Add(BAILOUT_ON_NO_OVERFLOW);
4362 if (expr->op() == Token::INC) { 4358 if (expr->op() == Token::INC) {
4363 __ SmiAddConstant(rax, rax, Smi::FromInt(1), mode, &done, Label::kNear); 4359 __ SmiAddConstant(rax, rax, Smi::FromInt(1), mode, &done, Label::kNear);
(...skipping 11 matching lines...) Expand all
4375 if (expr->is_postfix()) { 4371 if (expr->is_postfix()) {
4376 if (!context()->IsEffect()) { 4372 if (!context()->IsEffect()) {
4377 // Save the result on the stack. If we have a named or keyed property 4373 // Save the result on the stack. If we have a named or keyed property
4378 // we store the result under the receiver that is currently on top 4374 // we store the result under the receiver that is currently on top
4379 // of the stack. 4375 // of the stack.
4380 switch (assign_type) { 4376 switch (assign_type) {
4381 case VARIABLE: 4377 case VARIABLE:
4382 __ push(rax); 4378 __ push(rax);
4383 break; 4379 break;
4384 case NAMED_PROPERTY: 4380 case NAMED_PROPERTY:
4385 __ movq(Operand(rsp, kPointerSize), rax); 4381 __ movp(Operand(rsp, kPointerSize), rax);
4386 break; 4382 break;
4387 case KEYED_PROPERTY: 4383 case KEYED_PROPERTY:
4388 __ movq(Operand(rsp, 2 * kPointerSize), rax); 4384 __ movp(Operand(rsp, 2 * kPointerSize), rax);
4389 break; 4385 break;
4390 } 4386 }
4391 } 4387 }
4392 } 4388 }
4393 4389
4394 // Record position before stub call. 4390 // Record position before stub call.
4395 SetSourcePosition(expr->position()); 4391 SetSourcePosition(expr->position());
4396 4392
4397 // Call stub for +1/-1. 4393 // Call stub for +1/-1.
4398 __ bind(&stub_call); 4394 __ bind(&stub_call);
4399 __ movq(rdx, rax); 4395 __ movp(rdx, rax);
4400 __ Move(rax, Smi::FromInt(1)); 4396 __ Move(rax, Smi::FromInt(1));
4401 BinaryOpICStub stub(expr->binary_op(), NO_OVERWRITE); 4397 BinaryOpICStub stub(expr->binary_op(), NO_OVERWRITE);
4402 CallIC(stub.GetCode(isolate()), 4398 CallIC(stub.GetCode(isolate()),
4403 NOT_CONTEXTUAL, 4399 NOT_CONTEXTUAL,
4404 expr->CountBinOpFeedbackId()); 4400 expr->CountBinOpFeedbackId());
4405 patch_site.EmitPatchInfo(); 4401 patch_site.EmitPatchInfo();
4406 __ bind(&done); 4402 __ bind(&done);
4407 4403
4408 // Store the value returned in rax. 4404 // Store the value returned in rax.
4409 switch (assign_type) { 4405 switch (assign_type) {
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
4465 4461
4466 4462
4467 void FullCodeGenerator::VisitForTypeofValue(Expression* expr) { 4463 void FullCodeGenerator::VisitForTypeofValue(Expression* expr) {
4468 VariableProxy* proxy = expr->AsVariableProxy(); 4464 VariableProxy* proxy = expr->AsVariableProxy();
4469 ASSERT(!context()->IsEffect()); 4465 ASSERT(!context()->IsEffect());
4470 ASSERT(!context()->IsTest()); 4466 ASSERT(!context()->IsTest());
4471 4467
4472 if (proxy != NULL && proxy->var()->IsUnallocated()) { 4468 if (proxy != NULL && proxy->var()->IsUnallocated()) {
4473 Comment cmnt(masm_, "Global variable"); 4469 Comment cmnt(masm_, "Global variable");
4474 __ Move(rcx, proxy->name()); 4470 __ Move(rcx, proxy->name());
4475 __ movq(rax, GlobalObjectOperand()); 4471 __ movp(rax, GlobalObjectOperand());
4476 // Use a regular load, not a contextual load, to avoid a reference 4472 // Use a regular load, not a contextual load, to avoid a reference
4477 // error. 4473 // error.
4478 CallLoadIC(NOT_CONTEXTUAL); 4474 CallLoadIC(NOT_CONTEXTUAL);
4479 PrepareForBailout(expr, TOS_REG); 4475 PrepareForBailout(expr, TOS_REG);
4480 context()->Plug(rax); 4476 context()->Plug(rax);
4481 } else if (proxy != NULL && proxy->var()->IsLookupSlot()) { 4477 } else if (proxy != NULL && proxy->var()->IsLookupSlot()) {
4482 Label done, slow; 4478 Label done, slow;
4483 4479
4484 // Generate code for loading from variables potentially shadowed 4480 // Generate code for loading from variables potentially shadowed
4485 // by eval-introduced variables. 4481 // by eval-introduced variables.
(...skipping 24 matching lines...) Expand all
4510 context()->PrepareTest(&materialize_true, &materialize_false, 4506 context()->PrepareTest(&materialize_true, &materialize_false,
4511 &if_true, &if_false, &fall_through); 4507 &if_true, &if_false, &fall_through);
4512 4508
4513 { AccumulatorValueContext context(this); 4509 { AccumulatorValueContext context(this);
4514 VisitForTypeofValue(sub_expr); 4510 VisitForTypeofValue(sub_expr);
4515 } 4511 }
4516 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 4512 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
4517 4513
4518 if (check->Equals(isolate()->heap()->number_string())) { 4514 if (check->Equals(isolate()->heap()->number_string())) {
4519 __ JumpIfSmi(rax, if_true); 4515 __ JumpIfSmi(rax, if_true);
4520 __ movq(rax, FieldOperand(rax, HeapObject::kMapOffset)); 4516 __ movp(rax, FieldOperand(rax, HeapObject::kMapOffset));
4521 __ CompareRoot(rax, Heap::kHeapNumberMapRootIndex); 4517 __ CompareRoot(rax, Heap::kHeapNumberMapRootIndex);
4522 Split(equal, if_true, if_false, fall_through); 4518 Split(equal, if_true, if_false, fall_through);
4523 } else if (check->Equals(isolate()->heap()->string_string())) { 4519 } else if (check->Equals(isolate()->heap()->string_string())) {
4524 __ JumpIfSmi(rax, if_false); 4520 __ JumpIfSmi(rax, if_false);
4525 // Check for undetectable objects => false. 4521 // Check for undetectable objects => false.
4526 __ CmpObjectType(rax, FIRST_NONSTRING_TYPE, rdx); 4522 __ CmpObjectType(rax, FIRST_NONSTRING_TYPE, rdx);
4527 __ j(above_equal, if_false); 4523 __ j(above_equal, if_false);
4528 __ testb(FieldOperand(rdx, Map::kBitFieldOffset), 4524 __ testb(FieldOperand(rdx, Map::kBitFieldOffset),
4529 Immediate(1 << Map::kIsUndetectable)); 4525 Immediate(1 << Map::kIsUndetectable));
4530 Split(zero, if_true, if_false, fall_through); 4526 Split(zero, if_true, if_false, fall_through);
4531 } else if (check->Equals(isolate()->heap()->symbol_string())) { 4527 } else if (check->Equals(isolate()->heap()->symbol_string())) {
4532 __ JumpIfSmi(rax, if_false); 4528 __ JumpIfSmi(rax, if_false);
4533 __ CmpObjectType(rax, SYMBOL_TYPE, rdx); 4529 __ CmpObjectType(rax, SYMBOL_TYPE, rdx);
4534 Split(equal, if_true, if_false, fall_through); 4530 Split(equal, if_true, if_false, fall_through);
4535 } else if (check->Equals(isolate()->heap()->boolean_string())) { 4531 } else if (check->Equals(isolate()->heap()->boolean_string())) {
4536 __ CompareRoot(rax, Heap::kTrueValueRootIndex); 4532 __ CompareRoot(rax, Heap::kTrueValueRootIndex);
4537 __ j(equal, if_true); 4533 __ j(equal, if_true);
4538 __ CompareRoot(rax, Heap::kFalseValueRootIndex); 4534 __ CompareRoot(rax, Heap::kFalseValueRootIndex);
4539 Split(equal, if_true, if_false, fall_through); 4535 Split(equal, if_true, if_false, fall_through);
4540 } else if (FLAG_harmony_typeof && 4536 } else if (FLAG_harmony_typeof &&
4541 check->Equals(isolate()->heap()->null_string())) { 4537 check->Equals(isolate()->heap()->null_string())) {
4542 __ CompareRoot(rax, Heap::kNullValueRootIndex); 4538 __ CompareRoot(rax, Heap::kNullValueRootIndex);
4543 Split(equal, if_true, if_false, fall_through); 4539 Split(equal, if_true, if_false, fall_through);
4544 } else if (check->Equals(isolate()->heap()->undefined_string())) { 4540 } else if (check->Equals(isolate()->heap()->undefined_string())) {
4545 __ CompareRoot(rax, Heap::kUndefinedValueRootIndex); 4541 __ CompareRoot(rax, Heap::kUndefinedValueRootIndex);
4546 __ j(equal, if_true); 4542 __ j(equal, if_true);
4547 __ JumpIfSmi(rax, if_false); 4543 __ JumpIfSmi(rax, if_false);
4548 // Check for undetectable objects => true. 4544 // Check for undetectable objects => true.
4549 __ movq(rdx, FieldOperand(rax, HeapObject::kMapOffset)); 4545 __ movp(rdx, FieldOperand(rax, HeapObject::kMapOffset));
4550 __ testb(FieldOperand(rdx, Map::kBitFieldOffset), 4546 __ testb(FieldOperand(rdx, Map::kBitFieldOffset),
4551 Immediate(1 << Map::kIsUndetectable)); 4547 Immediate(1 << Map::kIsUndetectable));
4552 Split(not_zero, if_true, if_false, fall_through); 4548 Split(not_zero, if_true, if_false, fall_through);
4553 } else if (check->Equals(isolate()->heap()->function_string())) { 4549 } else if (check->Equals(isolate()->heap()->function_string())) {
4554 __ JumpIfSmi(rax, if_false); 4550 __ JumpIfSmi(rax, if_false);
4555 STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2); 4551 STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2);
4556 __ CmpObjectType(rax, JS_FUNCTION_TYPE, rdx); 4552 __ CmpObjectType(rax, JS_FUNCTION_TYPE, rdx);
4557 __ j(equal, if_true); 4553 __ j(equal, if_true);
4558 __ CmpInstanceType(rdx, JS_FUNCTION_PROXY_TYPE); 4554 __ CmpInstanceType(rdx, JS_FUNCTION_PROXY_TYPE);
4559 Split(equal, if_true, if_false, fall_through); 4555 Split(equal, if_true, if_false, fall_through);
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
4619 4615
4620 default: { 4616 default: {
4621 VisitForAccumulatorValue(expr->right()); 4617 VisitForAccumulatorValue(expr->right());
4622 Condition cc = CompareIC::ComputeCondition(op); 4618 Condition cc = CompareIC::ComputeCondition(op);
4623 __ pop(rdx); 4619 __ pop(rdx);
4624 4620
4625 bool inline_smi_code = ShouldInlineSmiCase(op); 4621 bool inline_smi_code = ShouldInlineSmiCase(op);
4626 JumpPatchSite patch_site(masm_); 4622 JumpPatchSite patch_site(masm_);
4627 if (inline_smi_code) { 4623 if (inline_smi_code) {
4628 Label slow_case; 4624 Label slow_case;
4629 __ movq(rcx, rdx); 4625 __ movp(rcx, rdx);
4630 __ or_(rcx, rax); 4626 __ or_(rcx, rax);
4631 patch_site.EmitJumpIfNotSmi(rcx, &slow_case, Label::kNear); 4627 patch_site.EmitJumpIfNotSmi(rcx, &slow_case, Label::kNear);
4632 __ cmpq(rdx, rax); 4628 __ cmpq(rdx, rax);
4633 Split(cc, if_true, if_false, NULL); 4629 Split(cc, if_true, if_false, NULL);
4634 __ bind(&slow_case); 4630 __ bind(&slow_case);
4635 } 4631 }
4636 4632
4637 // Record position and call the compare IC. 4633 // Record position and call the compare IC.
4638 SetSourcePosition(expr->position()); 4634 SetSourcePosition(expr->position());
4639 Handle<Code> ic = CompareIC::GetUninitialized(isolate(), op); 4635 Handle<Code> ic = CompareIC::GetUninitialized(isolate(), op);
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
4674 Handle<Code> ic = CompareNilICStub::GetUninitialized(isolate(), nil); 4670 Handle<Code> ic = CompareNilICStub::GetUninitialized(isolate(), nil);
4675 CallIC(ic, NOT_CONTEXTUAL, expr->CompareOperationFeedbackId()); 4671 CallIC(ic, NOT_CONTEXTUAL, expr->CompareOperationFeedbackId());
4676 __ testq(rax, rax); 4672 __ testq(rax, rax);
4677 Split(not_zero, if_true, if_false, fall_through); 4673 Split(not_zero, if_true, if_false, fall_through);
4678 } 4674 }
4679 context()->Plug(if_true, if_false); 4675 context()->Plug(if_true, if_false);
4680 } 4676 }
4681 4677
4682 4678
4683 void FullCodeGenerator::VisitThisFunction(ThisFunction* expr) { 4679 void FullCodeGenerator::VisitThisFunction(ThisFunction* expr) {
4684 __ movq(rax, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); 4680 __ movp(rax, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
4685 context()->Plug(rax); 4681 context()->Plug(rax);
4686 } 4682 }
4687 4683
4688 4684
4689 Register FullCodeGenerator::result_register() { 4685 Register FullCodeGenerator::result_register() {
4690 return rax; 4686 return rax;
4691 } 4687 }
4692 4688
4693 4689
4694 Register FullCodeGenerator::context_register() { 4690 Register FullCodeGenerator::context_register() {
4695 return rsi; 4691 return rsi;
4696 } 4692 }
4697 4693
4698 4694
4699 void FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) { 4695 void FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) {
4700 ASSERT(IsAligned(frame_offset, kPointerSize)); 4696 ASSERT(IsAligned(frame_offset, kPointerSize));
4701 __ movq(Operand(rbp, frame_offset), value); 4697 __ movp(Operand(rbp, frame_offset), value);
4702 } 4698 }
4703 4699
4704 4700
4705 void FullCodeGenerator::LoadContextField(Register dst, int context_index) { 4701 void FullCodeGenerator::LoadContextField(Register dst, int context_index) {
4706 __ movq(dst, ContextOperand(rsi, context_index)); 4702 __ movp(dst, ContextOperand(rsi, context_index));
4707 } 4703 }
4708 4704
4709 4705
4710 void FullCodeGenerator::PushFunctionArgumentForContextAllocation() { 4706 void FullCodeGenerator::PushFunctionArgumentForContextAllocation() {
4711 Scope* declaration_scope = scope()->DeclarationScope(); 4707 Scope* declaration_scope = scope()->DeclarationScope();
4712 if (declaration_scope->is_global_scope() || 4708 if (declaration_scope->is_global_scope() ||
4713 declaration_scope->is_module_scope()) { 4709 declaration_scope->is_module_scope()) {
4714 // Contexts nested in the native context have a canonical empty function 4710 // Contexts nested in the native context have a canonical empty function
4715 // as their closure, not the anonymous closure containing the global 4711 // as their closure, not the anonymous closure containing the global
4716 // code. Pass a smi sentinel and let the runtime look up the empty 4712 // code. Pass a smi sentinel and let the runtime look up the empty
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
4805 int* context_length) { 4801 int* context_length) {
4806 // The macros used here must preserve the result register. 4802 // The macros used here must preserve the result register.
4807 4803
4808 // Because the handler block contains the context of the finally 4804 // Because the handler block contains the context of the finally
4809 // code, we can restore it directly from there for the finally code 4805 // code, we can restore it directly from there for the finally code
4810 // rather than iteratively unwinding contexts via their previous 4806 // rather than iteratively unwinding contexts via their previous
4811 // links. 4807 // links.
4812 __ Drop(*stack_depth); // Down to the handler block. 4808 __ Drop(*stack_depth); // Down to the handler block.
4813 if (*context_length > 0) { 4809 if (*context_length > 0) {
4814 // Restore the context to its dedicated register and the stack. 4810 // Restore the context to its dedicated register and the stack.
4815 __ movq(rsi, Operand(rsp, StackHandlerConstants::kContextOffset)); 4811 __ movp(rsi, Operand(rsp, StackHandlerConstants::kContextOffset));
4816 __ movq(Operand(rbp, StandardFrameConstants::kContextOffset), rsi); 4812 __ movp(Operand(rbp, StandardFrameConstants::kContextOffset), rsi);
4817 } 4813 }
4818 __ PopTryHandler(); 4814 __ PopTryHandler();
4819 __ call(finally_entry_); 4815 __ call(finally_entry_);
4820 4816
4821 *stack_depth = 0; 4817 *stack_depth = 0;
4822 *context_length = 0; 4818 *context_length = 0;
4823 return previous_; 4819 return previous_;
4824 } 4820 }
4825 4821
4826 4822
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
4897 4893
4898 ASSERT_EQ(isolate->builtins()->OsrAfterStackCheck()->entry(), 4894 ASSERT_EQ(isolate->builtins()->OsrAfterStackCheck()->entry(),
4899 Assembler::target_address_at(call_target_address)); 4895 Assembler::target_address_at(call_target_address));
4900 return OSR_AFTER_STACK_CHECK; 4896 return OSR_AFTER_STACK_CHECK;
4901 } 4897 }
4902 4898
4903 4899
4904 } } // namespace v8::internal 4900 } } // namespace v8::internal
4905 4901
4906 #endif // V8_TARGET_ARCH_X64 4902 #endif // V8_TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « src/x64/deoptimizer-x64.cc ('k') | src/x64/ic-x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698