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

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

Issue 6697023: Merge 6800:7180 from the bleeding edge branch to the experimental/gc branch. (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/gc/
Patch Set: Created 9 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/ia32/lithium-codegen-ia32.h ('k') | src/ia32/lithium-ia32.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2011 the V8 project authors. All rights reserved. 1 // Copyright 2011 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
48 : codegen_(codegen), 48 : codegen_(codegen),
49 pointers_(pointers), 49 pointers_(pointers),
50 deoptimization_index_(deoptimization_index), 50 deoptimization_index_(deoptimization_index),
51 ensure_reloc_space_(ensure_reloc_space) { } 51 ensure_reloc_space_(ensure_reloc_space) { }
52 virtual ~SafepointGenerator() { } 52 virtual ~SafepointGenerator() { }
53 53
54 virtual void Generate() { 54 virtual void Generate() {
55 // Ensure that we have enough space in the reloc info to patch 55 // Ensure that we have enough space in the reloc info to patch
56 // this with calls when doing deoptimization. 56 // this with calls when doing deoptimization.
57 if (ensure_reloc_space_) { 57 if (ensure_reloc_space_) {
58 codegen_->masm()->RecordComment(RelocInfo::kFillerCommentString, true); 58 codegen_->EnsureRelocSpaceForDeoptimization();
59 } 59 }
60 codegen_->RecordSafepoint(pointers_, deoptimization_index_); 60 codegen_->RecordSafepoint(pointers_, deoptimization_index_);
61 } 61 }
62 62
63 private: 63 private:
64 LCodeGen* codegen_; 64 LCodeGen* codegen_;
65 LPointerMap* pointers_; 65 LPointerMap* pointers_;
66 int deoptimization_index_; 66 int deoptimization_index_;
67 bool ensure_reloc_space_; 67 bool ensure_reloc_space_;
68 }; 68 };
69 69
70 70
71 #define __ masm()-> 71 #define __ masm()->
72 72
73 bool LCodeGen::GenerateCode() { 73 bool LCodeGen::GenerateCode() {
74 HPhase phase("Code generation", chunk()); 74 HPhase phase("Code generation", chunk());
75 ASSERT(is_unused()); 75 ASSERT(is_unused());
76 status_ = GENERATING; 76 status_ = GENERATING;
77 CpuFeatures::Scope scope(SSE2); 77 CpuFeatures::Scope scope(SSE2);
78 return GeneratePrologue() && 78 return GeneratePrologue() &&
79 GenerateBody() && 79 GenerateBody() &&
80 GenerateDeferredCode() && 80 GenerateDeferredCode() &&
81 GenerateRelocPadding() &&
81 GenerateSafepointTable(); 82 GenerateSafepointTable();
82 } 83 }
83 84
84 85
85 void LCodeGen::FinishCode(Handle<Code> code) { 86 void LCodeGen::FinishCode(Handle<Code> code) {
86 ASSERT(is_done()); 87 ASSERT(is_done());
87 code->set_stack_slots(StackSlotCount()); 88 code->set_stack_slots(StackSlotCount());
88 code->set_safepoint_table_offset(safepoints_.GetCodeOffset()); 89 code->set_safepoint_table_offset(safepoints_.GetCodeOffset());
89 PopulateDeoptimizationData(code); 90 PopulateDeoptimizationData(code);
90 } 91 }
91 92
92 93
93 void LCodeGen::Abort(const char* format, ...) { 94 void LCodeGen::Abort(const char* format, ...) {
94 if (FLAG_trace_bailout) { 95 if (FLAG_trace_bailout) {
95 SmartPointer<char> debug_name = graph()->debug_name()->ToCString(); 96 SmartPointer<char> name(info()->shared_info()->DebugName()->ToCString());
96 PrintF("Aborting LCodeGen in @\"%s\": ", *debug_name); 97 PrintF("Aborting LCodeGen in @\"%s\": ", *name);
97 va_list arguments; 98 va_list arguments;
98 va_start(arguments, format); 99 va_start(arguments, format);
99 OS::VPrint(format, arguments); 100 OS::VPrint(format, arguments);
100 va_end(arguments); 101 va_end(arguments);
101 PrintF("\n"); 102 PrintF("\n");
102 } 103 }
103 status_ = ABORTED; 104 status_ = ABORTED;
104 } 105 }
105 106
106 107
107 void LCodeGen::Comment(const char* format, ...) { 108 void LCodeGen::Comment(const char* format, ...) {
108 if (!FLAG_code_comments) return; 109 if (!FLAG_code_comments) return;
109 char buffer[4 * KB]; 110 char buffer[4 * KB];
110 StringBuilder builder(buffer, ARRAY_SIZE(buffer)); 111 StringBuilder builder(buffer, ARRAY_SIZE(buffer));
111 va_list arguments; 112 va_list arguments;
112 va_start(arguments, format); 113 va_start(arguments, format);
113 builder.AddFormattedList(format, arguments); 114 builder.AddFormattedList(format, arguments);
114 va_end(arguments); 115 va_end(arguments);
115 116
116 // Copy the string before recording it in the assembler to avoid 117 // Copy the string before recording it in the assembler to avoid
117 // issues when the stack allocated buffer goes out of scope. 118 // issues when the stack allocated buffer goes out of scope.
118 size_t length = builder.position(); 119 size_t length = builder.position();
119 Vector<char> copy = Vector<char>::New(length + 1); 120 Vector<char> copy = Vector<char>::New(length + 1);
120 memcpy(copy.start(), builder.Finalize(), copy.length()); 121 memcpy(copy.start(), builder.Finalize(), copy.length());
121 masm()->RecordComment(copy.start()); 122 masm()->RecordComment(copy.start());
122 } 123 }
123 124
124 125
126 bool LCodeGen::GenerateRelocPadding() {
127 int reloc_size = masm()->relocation_writer_size();
128 while (reloc_size < deoptimization_reloc_size.min_size) {
129 __ RecordComment(RelocInfo::kFillerCommentString, true);
130 reloc_size += RelocInfo::kMinRelocCommentSize;
131 }
132 return !is_aborted();
133 }
134
135
125 bool LCodeGen::GeneratePrologue() { 136 bool LCodeGen::GeneratePrologue() {
126 ASSERT(is_generating()); 137 ASSERT(is_generating());
127 138
128 #ifdef DEBUG 139 #ifdef DEBUG
129 if (strlen(FLAG_stop_at) > 0 && 140 if (strlen(FLAG_stop_at) > 0 &&
130 info_->function()->name()->IsEqualTo(CStrVector(FLAG_stop_at))) { 141 info_->function()->name()->IsEqualTo(CStrVector(FLAG_stop_at))) {
131 __ int3(); 142 __ int3();
132 } 143 }
133 #endif 144 #endif
134 145
(...skipping 21 matching lines...) Expand all
156 const int kPageSize = 4 * KB; 167 const int kPageSize = 4 * KB;
157 for (int offset = slots * kPointerSize - kPageSize; 168 for (int offset = slots * kPointerSize - kPageSize;
158 offset > 0; 169 offset > 0;
159 offset -= kPageSize) { 170 offset -= kPageSize) {
160 __ mov(Operand(esp, offset), eax); 171 __ mov(Operand(esp, offset), eax);
161 } 172 }
162 #endif 173 #endif
163 } 174 }
164 } 175 }
165 176
177 // Possibly allocate a local context.
178 int heap_slots = scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
179 if (heap_slots > 0) {
180 Comment(";;; Allocate local context");
181 // Argument to NewContext is the function, which is still in edi.
182 __ push(edi);
183 if (heap_slots <= FastNewContextStub::kMaximumSlots) {
184 FastNewContextStub stub(heap_slots);
185 __ CallStub(&stub);
186 } else {
187 __ CallRuntime(Runtime::kNewContext, 1);
188 }
189 RecordSafepoint(Safepoint::kNoDeoptimizationIndex);
190 // Context is returned in both eax and esi. It replaces the context
191 // passed to us. It's saved in the stack and kept live in esi.
192 __ mov(Operand(ebp, StandardFrameConstants::kContextOffset), esi);
193
194 // Copy parameters into context if necessary.
195 int num_parameters = scope()->num_parameters();
196 for (int i = 0; i < num_parameters; i++) {
197 Slot* slot = scope()->parameter(i)->AsSlot();
198 if (slot != NULL && slot->type() == Slot::CONTEXT) {
199 int parameter_offset = StandardFrameConstants::kCallerSPOffset +
200 (num_parameters - 1 - i) * kPointerSize;
201 // Load parameter from stack.
202 __ mov(eax, Operand(ebp, parameter_offset));
203 // Store it in the context.
204 int context_offset = Context::SlotOffset(slot->index());
205 __ mov(Operand(esi, context_offset), eax);
206 // Update the write barrier. This clobbers all involved
207 // registers, so we have to use a third register to avoid
208 // clobbering esi.
209 __ mov(ecx, esi);
210 __ RecordWrite(ecx, context_offset, eax, ebx);
211 }
212 }
213 Comment(";;; End allocate local context");
214 }
215
166 // Trace the call. 216 // Trace the call.
167 if (FLAG_trace) { 217 if (FLAG_trace) {
168 // We have not executed any compiled code yet, so esi still holds the 218 // We have not executed any compiled code yet, so esi still holds the
169 // incoming context. 219 // incoming context.
170 __ CallRuntime(Runtime::kTraceEnter, 0); 220 __ CallRuntime(Runtime::kTraceEnter, 0);
171 } 221 }
172 return !is_aborted(); 222 return !is_aborted();
173 } 223 }
174 224
175 225
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after
328 environment->spilled_double_registers()[value->index()], 378 environment->spilled_double_registers()[value->index()],
329 false); 379 false);
330 } 380 }
331 } 381 }
332 382
333 AddToTranslation(translation, value, environment->HasTaggedValueAt(i)); 383 AddToTranslation(translation, value, environment->HasTaggedValueAt(i));
334 } 384 }
335 } 385 }
336 386
337 387
388 void LCodeGen::EnsureRelocSpaceForDeoptimization() {
389 // Since we patch the reloc info with RUNTIME_ENTRY calls every patch
390 // site will take up 2 bytes + any pc-jumps.
391 // We are conservative and always reserver 6 bytes in case where a
392 // simple pc-jump is not enough.
393 uint32_t pc_delta =
394 masm()->pc_offset() - deoptimization_reloc_size.last_pc_offset;
395 if (is_uintn(pc_delta, 6)) {
396 deoptimization_reloc_size.min_size += 2;
397 } else {
398 deoptimization_reloc_size.min_size += 6;
399 }
400 deoptimization_reloc_size.last_pc_offset = masm()->pc_offset();
401 }
402
403
338 void LCodeGen::AddToTranslation(Translation* translation, 404 void LCodeGen::AddToTranslation(Translation* translation,
339 LOperand* op, 405 LOperand* op,
340 bool is_tagged) { 406 bool is_tagged) {
341 if (op == NULL) { 407 if (op == NULL) {
342 // TODO(twuerthinger): Introduce marker operands to indicate that this value 408 // TODO(twuerthinger): Introduce marker operands to indicate that this value
343 // is not present and must be reconstructed from the deoptimizer. Currently 409 // is not present and must be reconstructed from the deoptimizer. Currently
344 // this is only used for the arguments object. 410 // this is only used for the arguments object.
345 translation->StoreArgumentsObject(); 411 translation->StoreArgumentsObject();
346 } else if (op->IsStackSlot()) { 412 } else if (op->IsStackSlot()) {
347 if (is_tagged) { 413 if (is_tagged) {
(...skipping 27 matching lines...) Expand all
375 } 441 }
376 442
377 443
378 void LCodeGen::CallCode(Handle<Code> code, 444 void LCodeGen::CallCode(Handle<Code> code,
379 RelocInfo::Mode mode, 445 RelocInfo::Mode mode,
380 LInstruction* instr, 446 LInstruction* instr,
381 bool adjusted) { 447 bool adjusted) {
382 ASSERT(instr != NULL); 448 ASSERT(instr != NULL);
383 LPointerMap* pointers = instr->pointer_map(); 449 LPointerMap* pointers = instr->pointer_map();
384 RecordPosition(pointers->position()); 450 RecordPosition(pointers->position());
451
385 if (!adjusted) { 452 if (!adjusted) {
386 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); 453 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
387 } 454 }
388 __ call(code, mode); 455 __ call(code, mode);
456
457 EnsureRelocSpaceForDeoptimization();
389 RegisterLazyDeoptimization(instr); 458 RegisterLazyDeoptimization(instr);
390 459
391 // Signal that we don't inline smi code before these stubs in the 460 // Signal that we don't inline smi code before these stubs in the
392 // optimizing code generator. 461 // optimizing code generator.
393 if (code->kind() == Code::TYPE_RECORDING_BINARY_OP_IC || 462 if (code->kind() == Code::TYPE_RECORDING_BINARY_OP_IC ||
394 code->kind() == Code::COMPARE_IC) { 463 code->kind() == Code::COMPARE_IC) {
395 __ nop(); 464 __ nop();
396 } 465 }
397 } 466 }
398 467
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
512 } 581 }
513 582
514 583
515 void LCodeGen::PopulateDeoptimizationData(Handle<Code> code) { 584 void LCodeGen::PopulateDeoptimizationData(Handle<Code> code) {
516 int length = deoptimizations_.length(); 585 int length = deoptimizations_.length();
517 if (length == 0) return; 586 if (length == 0) return;
518 ASSERT(FLAG_deopt); 587 ASSERT(FLAG_deopt);
519 Handle<DeoptimizationInputData> data = 588 Handle<DeoptimizationInputData> data =
520 Factory::NewDeoptimizationInputData(length, TENURED); 589 Factory::NewDeoptimizationInputData(length, TENURED);
521 590
522 data->SetTranslationByteArray(*translations_.CreateByteArray()); 591 Handle<ByteArray> translations = translations_.CreateByteArray();
592 data->SetTranslationByteArray(*translations);
523 data->SetInlinedFunctionCount(Smi::FromInt(inlined_function_count_)); 593 data->SetInlinedFunctionCount(Smi::FromInt(inlined_function_count_));
524 594
525 Handle<FixedArray> literals = 595 Handle<FixedArray> literals =
526 Factory::NewFixedArray(deoptimization_literals_.length(), TENURED); 596 Factory::NewFixedArray(deoptimization_literals_.length(), TENURED);
527 for (int i = 0; i < deoptimization_literals_.length(); i++) { 597 for (int i = 0; i < deoptimization_literals_.length(); i++) {
528 literals->set(i, *deoptimization_literals_[i]); 598 literals->set(i, *deoptimization_literals_[i]);
529 } 599 }
530 data->SetLiteralArray(*literals); 600 data->SetLiteralArray(*literals);
531 601
532 data->SetOsrAstId(Smi::FromInt(info_->osr_ast_id())); 602 data->SetOsrAstId(Smi::FromInt(info_->osr_ast_id()));
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
588 } 658 }
589 } 659 }
590 660
591 661
592 void LCodeGen::RecordSafepoint(LPointerMap* pointers, 662 void LCodeGen::RecordSafepoint(LPointerMap* pointers,
593 int deoptimization_index) { 663 int deoptimization_index) {
594 RecordSafepoint(pointers, Safepoint::kSimple, 0, deoptimization_index); 664 RecordSafepoint(pointers, Safepoint::kSimple, 0, deoptimization_index);
595 } 665 }
596 666
597 667
668 void LCodeGen::RecordSafepoint(int deoptimization_index) {
669 LPointerMap empty_pointers(RelocInfo::kNoPosition);
670 RecordSafepoint(&empty_pointers, deoptimization_index);
671 }
672
673
598 void LCodeGen::RecordSafepointWithRegisters(LPointerMap* pointers, 674 void LCodeGen::RecordSafepointWithRegisters(LPointerMap* pointers,
599 int arguments, 675 int arguments,
600 int deoptimization_index) { 676 int deoptimization_index) {
601 RecordSafepoint(pointers, Safepoint::kWithRegisters, arguments, 677 RecordSafepoint(pointers, Safepoint::kWithRegisters, arguments,
602 deoptimization_index); 678 deoptimization_index);
603 } 679 }
604 680
605 681
606 void LCodeGen::RecordPosition(int position) { 682 void LCodeGen::RecordPosition(int position) {
607 if (!FLAG_debug_info || position == RelocInfo::kNoPosition) return; 683 if (!FLAG_debug_info || position == RelocInfo::kNoPosition) return;
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
660 case CodeStub::RegExpExec: { 736 case CodeStub::RegExpExec: {
661 RegExpExecStub stub; 737 RegExpExecStub stub;
662 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); 738 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
663 break; 739 break;
664 } 740 }
665 case CodeStub::SubString: { 741 case CodeStub::SubString: {
666 SubStringStub stub; 742 SubStringStub stub;
667 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); 743 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
668 break; 744 break;
669 } 745 }
670 case CodeStub::StringCharAt: {
671 StringCharAtStub stub;
672 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
673 break;
674 }
675 case CodeStub::MathPow: {
676 MathPowStub stub;
677 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
678 break;
679 }
680 case CodeStub::NumberToString: { 746 case CodeStub::NumberToString: {
681 NumberToStringStub stub; 747 NumberToStringStub stub;
682 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); 748 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
683 break; 749 break;
684 } 750 }
685 case CodeStub::StringAdd: { 751 case CodeStub::StringAdd: {
686 StringAddStub stub(NO_STRING_ADD_FLAGS); 752 StringAddStub stub(NO_STRING_ADD_FLAGS);
687 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); 753 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
688 break; 754 break;
689 } 755 }
(...skipping 13 matching lines...) Expand all
703 } 769 }
704 } 770 }
705 771
706 772
707 void LCodeGen::DoUnknownOSRValue(LUnknownOSRValue* instr) { 773 void LCodeGen::DoUnknownOSRValue(LUnknownOSRValue* instr) {
708 // Nothing to do. 774 // Nothing to do.
709 } 775 }
710 776
711 777
712 void LCodeGen::DoModI(LModI* instr) { 778 void LCodeGen::DoModI(LModI* instr) {
713 LOperand* right = instr->InputAt(1); 779 if (instr->hydrogen()->HasPowerOf2Divisor()) {
714 ASSERT(ToRegister(instr->result()).is(edx)); 780 Register dividend = ToRegister(instr->InputAt(0));
715 ASSERT(ToRegister(instr->InputAt(0)).is(eax));
716 ASSERT(!ToRegister(instr->InputAt(1)).is(eax));
717 ASSERT(!ToRegister(instr->InputAt(1)).is(edx));
718 781
719 Register right_reg = ToRegister(right); 782 int32_t divisor =
783 HConstant::cast(instr->hydrogen()->right())->Integer32Value();
720 784
721 // Check for x % 0. 785 if (divisor < 0) divisor = -divisor;
722 if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) {
723 __ test(right_reg, ToOperand(right));
724 DeoptimizeIf(zero, instr->environment());
725 }
726 786
727 // Sign extend to edx. 787 NearLabel positive_dividend, done;
728 __ cdq(); 788 __ test(dividend, Operand(dividend));
729 789 __ j(not_sign, &positive_dividend);
730 // Check for (0 % -x) that will produce negative zero. 790 __ neg(dividend);
731 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 791 __ and_(dividend, divisor - 1);
732 NearLabel positive_left; 792 __ neg(dividend);
733 NearLabel done; 793 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
734 __ test(eax, Operand(eax)); 794 __ j(not_zero, &done);
735 __ j(not_sign, &positive_left); 795 DeoptimizeIf(no_condition, instr->environment());
736 __ idiv(right_reg); 796 }
737 797 __ bind(&positive_dividend);
738 // Test the remainder for 0, because then the result would be -0. 798 __ and_(dividend, divisor - 1);
739 __ test(edx, Operand(edx));
740 __ j(not_zero, &done);
741
742 DeoptimizeIf(no_condition, instr->environment());
743 __ bind(&positive_left);
744 __ idiv(right_reg);
745 __ bind(&done); 799 __ bind(&done);
746 } else { 800 } else {
747 __ idiv(right_reg); 801 LOperand* right = instr->InputAt(1);
802 ASSERT(ToRegister(instr->InputAt(0)).is(eax));
803 ASSERT(ToRegister(instr->result()).is(edx));
804
805 Register right_reg = ToRegister(right);
806 ASSERT(!right_reg.is(eax));
807 ASSERT(!right_reg.is(edx));
808
809 // Check for x % 0.
810 if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) {
811 __ test(right_reg, ToOperand(right));
812 DeoptimizeIf(zero, instr->environment());
813 }
814
815 // Sign extend to edx.
816 __ cdq();
817
818 // Check for (0 % -x) that will produce negative zero.
819 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
820 NearLabel positive_left;
821 NearLabel done;
822 __ test(eax, Operand(eax));
823 __ j(not_sign, &positive_left);
824 __ idiv(right_reg);
825
826 // Test the remainder for 0, because then the result would be -0.
827 __ test(edx, Operand(edx));
828 __ j(not_zero, &done);
829
830 DeoptimizeIf(no_condition, instr->environment());
831 __ bind(&positive_left);
832 __ idiv(right_reg);
833 __ bind(&done);
834 } else {
835 __ idiv(right_reg);
836 }
748 } 837 }
749 } 838 }
750 839
751 840
752 void LCodeGen::DoDivI(LDivI* instr) { 841 void LCodeGen::DoDivI(LDivI* instr) {
753 LOperand* right = instr->InputAt(1); 842 LOperand* right = instr->InputAt(1);
754 ASSERT(ToRegister(instr->result()).is(eax)); 843 ASSERT(ToRegister(instr->result()).is(eax));
755 ASSERT(ToRegister(instr->InputAt(0)).is(eax)); 844 ASSERT(ToRegister(instr->InputAt(0)).is(eax));
756 ASSERT(!ToRegister(instr->InputAt(1)).is(eax)); 845 ASSERT(!ToRegister(instr->InputAt(1)).is(eax));
757 ASSERT(!ToRegister(instr->InputAt(1)).is(edx)); 846 ASSERT(!ToRegister(instr->InputAt(1)).is(edx));
(...skipping 245 matching lines...) Expand 10 before | Expand all | Expand 10 after
1003 } 1092 }
1004 1093
1005 1094
1006 void LCodeGen::DoFixedArrayLength(LFixedArrayLength* instr) { 1095 void LCodeGen::DoFixedArrayLength(LFixedArrayLength* instr) {
1007 Register result = ToRegister(instr->result()); 1096 Register result = ToRegister(instr->result());
1008 Register array = ToRegister(instr->InputAt(0)); 1097 Register array = ToRegister(instr->InputAt(0));
1009 __ mov(result, FieldOperand(array, FixedArray::kLengthOffset)); 1098 __ mov(result, FieldOperand(array, FixedArray::kLengthOffset));
1010 } 1099 }
1011 1100
1012 1101
1013 void LCodeGen::DoPixelArrayLength(LPixelArrayLength* instr) { 1102 void LCodeGen::DoExternalArrayLength(LExternalArrayLength* instr) {
1014 Register result = ToRegister(instr->result()); 1103 Register result = ToRegister(instr->result());
1015 Register array = ToRegister(instr->InputAt(0)); 1104 Register array = ToRegister(instr->InputAt(0));
1016 __ mov(result, FieldOperand(array, PixelArray::kLengthOffset)); 1105 __ mov(result, FieldOperand(array, ExternalArray::kLengthOffset));
1017 } 1106 }
1018 1107
1019 1108
1020 void LCodeGen::DoValueOf(LValueOf* instr) { 1109 void LCodeGen::DoValueOf(LValueOf* instr) {
1021 Register input = ToRegister(instr->InputAt(0)); 1110 Register input = ToRegister(instr->InputAt(0));
1022 Register result = ToRegister(instr->result()); 1111 Register result = ToRegister(instr->result());
1023 Register map = ToRegister(instr->TempAt(0)); 1112 Register map = ToRegister(instr->TempAt(0));
1024 ASSERT(input.is(result)); 1113 ASSERT(input.is(result));
1025 NearLabel done; 1114 NearLabel done;
1026 // If the object is a smi return the object. 1115 // If the object is a smi return the object.
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
1065 __ add(ToRegister(left), ToOperand(right)); 1154 __ add(ToRegister(left), ToOperand(right));
1066 } 1155 }
1067 1156
1068 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { 1157 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) {
1069 DeoptimizeIf(overflow, instr->environment()); 1158 DeoptimizeIf(overflow, instr->environment());
1070 } 1159 }
1071 } 1160 }
1072 1161
1073 1162
1074 void LCodeGen::DoArithmeticD(LArithmeticD* instr) { 1163 void LCodeGen::DoArithmeticD(LArithmeticD* instr) {
1075 LOperand* left = instr->InputAt(0); 1164 XMMRegister left = ToDoubleRegister(instr->InputAt(0));
1076 LOperand* right = instr->InputAt(1); 1165 XMMRegister right = ToDoubleRegister(instr->InputAt(1));
1166 XMMRegister result = ToDoubleRegister(instr->result());
1077 // Modulo uses a fixed result register. 1167 // Modulo uses a fixed result register.
1078 ASSERT(instr->op() == Token::MOD || left->Equals(instr->result())); 1168 ASSERT(instr->op() == Token::MOD || left.is(result));
1079 switch (instr->op()) { 1169 switch (instr->op()) {
1080 case Token::ADD: 1170 case Token::ADD:
1081 __ addsd(ToDoubleRegister(left), ToDoubleRegister(right)); 1171 __ addsd(left, right);
1082 break; 1172 break;
1083 case Token::SUB: 1173 case Token::SUB:
1084 __ subsd(ToDoubleRegister(left), ToDoubleRegister(right)); 1174 __ subsd(left, right);
1085 break; 1175 break;
1086 case Token::MUL: 1176 case Token::MUL:
1087 __ mulsd(ToDoubleRegister(left), ToDoubleRegister(right)); 1177 __ mulsd(left, right);
1088 break; 1178 break;
1089 case Token::DIV: 1179 case Token::DIV:
1090 __ divsd(ToDoubleRegister(left), ToDoubleRegister(right)); 1180 __ divsd(left, right);
1091 break; 1181 break;
1092 case Token::MOD: { 1182 case Token::MOD: {
1093 // Pass two doubles as arguments on the stack. 1183 // Pass two doubles as arguments on the stack.
1094 __ PrepareCallCFunction(4, eax); 1184 __ PrepareCallCFunction(4, eax);
1095 __ movdbl(Operand(esp, 0 * kDoubleSize), ToDoubleRegister(left)); 1185 __ movdbl(Operand(esp, 0 * kDoubleSize), left);
1096 __ movdbl(Operand(esp, 1 * kDoubleSize), ToDoubleRegister(right)); 1186 __ movdbl(Operand(esp, 1 * kDoubleSize), right);
1097 __ CallCFunction(ExternalReference::double_fp_operation(Token::MOD), 4); 1187 __ CallCFunction(ExternalReference::double_fp_operation(Token::MOD), 4);
1098 1188
1099 // Return value is in st(0) on ia32. 1189 // Return value is in st(0) on ia32.
1100 // Store it into the (fixed) result register. 1190 // Store it into the (fixed) result register.
1101 __ sub(Operand(esp), Immediate(kDoubleSize)); 1191 __ sub(Operand(esp), Immediate(kDoubleSize));
1102 __ fstp_d(Operand(esp, 0)); 1192 __ fstp_d(Operand(esp, 0));
1103 __ movdbl(ToDoubleRegister(instr->result()), Operand(esp, 0)); 1193 __ movdbl(result, Operand(esp, 0));
1104 __ add(Operand(esp), Immediate(kDoubleSize)); 1194 __ add(Operand(esp), Immediate(kDoubleSize));
1105 break; 1195 break;
1106 } 1196 }
1107 default: 1197 default:
1108 UNREACHABLE(); 1198 UNREACHABLE();
1109 break; 1199 break;
1110 } 1200 }
1111 } 1201 }
1112 1202
1113 1203
(...skipping 456 matching lines...) Expand 10 before | Expand all | Expand 10 after
1570 Label* false_label = chunk_->GetAssemblyLabel(false_block); 1660 Label* false_label = chunk_->GetAssemblyLabel(false_block);
1571 1661
1572 __ test(input, Immediate(kSmiTagMask)); 1662 __ test(input, Immediate(kSmiTagMask));
1573 __ j(zero, false_label); 1663 __ j(zero, false_label);
1574 1664
1575 __ CmpObjectType(input, TestType(instr->hydrogen()), temp); 1665 __ CmpObjectType(input, TestType(instr->hydrogen()), temp);
1576 EmitBranch(true_block, false_block, BranchCondition(instr->hydrogen())); 1666 EmitBranch(true_block, false_block, BranchCondition(instr->hydrogen()));
1577 } 1667 }
1578 1668
1579 1669
1670 void LCodeGen::DoGetCachedArrayIndex(LGetCachedArrayIndex* instr) {
1671 Register input = ToRegister(instr->InputAt(0));
1672 Register result = ToRegister(instr->result());
1673
1674 if (FLAG_debug_code) {
1675 __ AbortIfNotString(input);
1676 }
1677
1678 __ mov(result, FieldOperand(input, String::kHashFieldOffset));
1679 __ IndexFromHash(result, result);
1680 }
1681
1682
1580 void LCodeGen::DoHasCachedArrayIndex(LHasCachedArrayIndex* instr) { 1683 void LCodeGen::DoHasCachedArrayIndex(LHasCachedArrayIndex* instr) {
1581 Register input = ToRegister(instr->InputAt(0)); 1684 Register input = ToRegister(instr->InputAt(0));
1582 Register result = ToRegister(instr->result()); 1685 Register result = ToRegister(instr->result());
1583 1686
1584 ASSERT(instr->hydrogen()->value()->representation().IsTagged()); 1687 ASSERT(instr->hydrogen()->value()->representation().IsTagged());
1585 __ mov(result, Factory::true_value()); 1688 __ mov(result, Factory::true_value());
1586 __ test(FieldOperand(input, String::kHashFieldOffset), 1689 __ test(FieldOperand(input, String::kHashFieldOffset),
1587 Immediate(String::kContainsCachedArrayIndexMask)); 1690 Immediate(String::kContainsCachedArrayIndexMask));
1588 NearLabel done; 1691 NearLabel done;
1589 __ j(not_zero, &done); 1692 __ j(zero, &done);
1590 __ mov(result, Factory::false_value()); 1693 __ mov(result, Factory::false_value());
1591 __ bind(&done); 1694 __ bind(&done);
1592 } 1695 }
1593 1696
1594 1697
1595 void LCodeGen::DoHasCachedArrayIndexAndBranch( 1698 void LCodeGen::DoHasCachedArrayIndexAndBranch(
1596 LHasCachedArrayIndexAndBranch* instr) { 1699 LHasCachedArrayIndexAndBranch* instr) {
1597 Register input = ToRegister(instr->InputAt(0)); 1700 Register input = ToRegister(instr->InputAt(0));
1598 1701
1599 int true_block = chunk_->LookupDestination(instr->true_block_id()); 1702 int true_block = chunk_->LookupDestination(instr->true_block_id());
1600 int false_block = chunk_->LookupDestination(instr->false_block_id()); 1703 int false_block = chunk_->LookupDestination(instr->false_block_id());
1601 1704
1602 __ test(FieldOperand(input, String::kHashFieldOffset), 1705 __ test(FieldOperand(input, String::kHashFieldOffset),
1603 Immediate(String::kContainsCachedArrayIndexMask)); 1706 Immediate(String::kContainsCachedArrayIndexMask));
1604 EmitBranch(true_block, false_block, not_equal); 1707 EmitBranch(true_block, false_block, equal);
1605 } 1708 }
1606 1709
1607 1710
1608 // Branches to a label or falls through with the answer in the z flag. Trashes 1711 // Branches to a label or falls through with the answer in the z flag. Trashes
1609 // the temp registers, but not the input. Only input and temp2 may alias. 1712 // the temp registers, but not the input. Only input and temp2 may alias.
1610 void LCodeGen::EmitClassOfTest(Label* is_true, 1713 void LCodeGen::EmitClassOfTest(Label* is_true,
1611 Label* is_false, 1714 Label* is_false,
1612 Handle<String>class_name, 1715 Handle<String>class_name,
1613 Register input, 1716 Register input,
1614 Register temp, 1717 Register temp,
(...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after
1826 InstanceofStub stub(flags); 1929 InstanceofStub stub(flags);
1827 1930
1828 // Get the temp register reserved by the instruction. This needs to be edi as 1931 // Get the temp register reserved by the instruction. This needs to be edi as
1829 // its slot of the pushing of safepoint registers is used to communicate the 1932 // its slot of the pushing of safepoint registers is used to communicate the
1830 // offset to the location of the map check. 1933 // offset to the location of the map check.
1831 Register temp = ToRegister(instr->TempAt(0)); 1934 Register temp = ToRegister(instr->TempAt(0));
1832 ASSERT(temp.is(edi)); 1935 ASSERT(temp.is(edi));
1833 __ mov(InstanceofStub::right(), Immediate(instr->function())); 1936 __ mov(InstanceofStub::right(), Immediate(instr->function()));
1834 static const int kAdditionalDelta = 16; 1937 static const int kAdditionalDelta = 16;
1835 int delta = masm_->SizeOfCodeGeneratedSince(map_check) + kAdditionalDelta; 1938 int delta = masm_->SizeOfCodeGeneratedSince(map_check) + kAdditionalDelta;
1836 Label before_push_delta;
1837 __ bind(&before_push_delta);
1838 __ mov(temp, Immediate(delta)); 1939 __ mov(temp, Immediate(delta));
1839 __ mov(Operand(esp, EspIndexForPushAll(temp) * kPointerSize), temp); 1940 __ StoreToSafepointRegisterSlot(temp, temp);
1840 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); 1941 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr, false);
1841 __ call(stub.GetCode(), RelocInfo::CODE_TARGET);
1842 ASSERT_EQ(kAdditionalDelta,
1843 masm_->SizeOfCodeGeneratedSince(&before_push_delta));
1844 RecordSafepointWithRegisters(
1845 instr->pointer_map(), 0, Safepoint::kNoDeoptimizationIndex);
1846 // Put the result value into the eax slot and restore all registers. 1942 // Put the result value into the eax slot and restore all registers.
1847 __ mov(Operand(esp, EspIndexForPushAll(eax) * kPointerSize), eax); 1943 __ StoreToSafepointRegisterSlot(eax, eax);
1848
1849 __ PopSafepointRegisters(); 1944 __ PopSafepointRegisters();
1850 } 1945 }
1851 1946
1852 1947
1853 static Condition ComputeCompareCondition(Token::Value op) { 1948 static Condition ComputeCompareCondition(Token::Value op) {
1854 switch (op) { 1949 switch (op) {
1855 case Token::EQ_STRICT: 1950 case Token::EQ_STRICT:
1856 case Token::EQ: 1951 case Token::EQ:
1857 return equal; 1952 return equal;
1858 case Token::LT: 1953 case Token::LT:
(...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after
2052 void LCodeGen::DoLoadElements(LLoadElements* instr) { 2147 void LCodeGen::DoLoadElements(LLoadElements* instr) {
2053 Register result = ToRegister(instr->result()); 2148 Register result = ToRegister(instr->result());
2054 Register input = ToRegister(instr->InputAt(0)); 2149 Register input = ToRegister(instr->InputAt(0));
2055 __ mov(result, FieldOperand(input, JSObject::kElementsOffset)); 2150 __ mov(result, FieldOperand(input, JSObject::kElementsOffset));
2056 if (FLAG_debug_code) { 2151 if (FLAG_debug_code) {
2057 NearLabel done; 2152 NearLabel done;
2058 __ cmp(FieldOperand(result, HeapObject::kMapOffset), 2153 __ cmp(FieldOperand(result, HeapObject::kMapOffset),
2059 Immediate(Factory::fixed_array_map())); 2154 Immediate(Factory::fixed_array_map()));
2060 __ j(equal, &done); 2155 __ j(equal, &done);
2061 __ cmp(FieldOperand(result, HeapObject::kMapOffset), 2156 __ cmp(FieldOperand(result, HeapObject::kMapOffset),
2062 Immediate(Factory::pixel_array_map())); 2157 Immediate(Factory::external_pixel_array_map()));
2063 __ j(equal, &done); 2158 __ j(equal, &done);
2064 __ cmp(FieldOperand(result, HeapObject::kMapOffset), 2159 __ cmp(FieldOperand(result, HeapObject::kMapOffset),
2065 Immediate(Factory::fixed_cow_array_map())); 2160 Immediate(Factory::fixed_cow_array_map()));
2066 __ Check(equal, "Check for fast elements or pixel array failed."); 2161 __ Check(equal, "Check for fast elements or pixel array failed.");
2067 __ bind(&done); 2162 __ bind(&done);
2068 } 2163 }
2069 } 2164 }
2070 2165
2071 2166
2072 void LCodeGen::DoLoadPixelArrayExternalPointer( 2167 void LCodeGen::DoLoadExternalArrayPointer(
2073 LLoadPixelArrayExternalPointer* instr) { 2168 LLoadExternalArrayPointer* instr) {
2074 Register result = ToRegister(instr->result()); 2169 Register result = ToRegister(instr->result());
2075 Register input = ToRegister(instr->InputAt(0)); 2170 Register input = ToRegister(instr->InputAt(0));
2076 __ mov(result, FieldOperand(input, PixelArray::kExternalPointerOffset)); 2171 __ mov(result, FieldOperand(input,
2172 ExternalArray::kExternalPointerOffset));
2077 } 2173 }
2078 2174
2079 2175
2080 void LCodeGen::DoAccessArgumentsAt(LAccessArgumentsAt* instr) { 2176 void LCodeGen::DoAccessArgumentsAt(LAccessArgumentsAt* instr) {
2081 Register arguments = ToRegister(instr->arguments()); 2177 Register arguments = ToRegister(instr->arguments());
2082 Register length = ToRegister(instr->length()); 2178 Register length = ToRegister(instr->length());
2083 Operand index = ToOperand(instr->index()); 2179 Operand index = ToOperand(instr->index());
2084 Register result = ToRegister(instr->result()); 2180 Register result = ToRegister(instr->result());
2085 2181
2086 __ sub(length, index); 2182 __ sub(length, index);
(...skipping 17 matching lines...) Expand all
2104 times_pointer_size, 2200 times_pointer_size,
2105 FixedArray::kHeaderSize)); 2201 FixedArray::kHeaderSize));
2106 2202
2107 // Check for the hole value. 2203 // Check for the hole value.
2108 __ cmp(result, Factory::the_hole_value()); 2204 __ cmp(result, Factory::the_hole_value());
2109 DeoptimizeIf(equal, instr->environment()); 2205 DeoptimizeIf(equal, instr->environment());
2110 } 2206 }
2111 2207
2112 2208
2113 void LCodeGen::DoLoadPixelArrayElement(LLoadPixelArrayElement* instr) { 2209 void LCodeGen::DoLoadPixelArrayElement(LLoadPixelArrayElement* instr) {
2114 Register external_elements = ToRegister(instr->external_pointer()); 2210 Register external_pointer = ToRegister(instr->external_pointer());
2115 Register key = ToRegister(instr->key()); 2211 Register key = ToRegister(instr->key());
2116 Register result = ToRegister(instr->result()); 2212 Register result = ToRegister(instr->result());
2117 ASSERT(result.is(external_elements)); 2213 ASSERT(result.is(external_pointer));
2118 2214
2119 // Load the result. 2215 // Load the result.
2120 __ movzx_b(result, Operand(external_elements, key, times_1, 0)); 2216 __ movzx_b(result, Operand(external_pointer, key, times_1, 0));
2121 } 2217 }
2122 2218
2123 2219
2124 void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) { 2220 void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) {
2125 ASSERT(ToRegister(instr->context()).is(esi)); 2221 ASSERT(ToRegister(instr->context()).is(esi));
2126 ASSERT(ToRegister(instr->object()).is(edx)); 2222 ASSERT(ToRegister(instr->object()).is(edx));
2127 ASSERT(ToRegister(instr->key()).is(eax)); 2223 ASSERT(ToRegister(instr->key()).is(eax));
2128 2224
2129 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); 2225 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
2130 CallCode(ic, RelocInfo::CODE_TARGET, instr); 2226 CallCode(ic, RelocInfo::CODE_TARGET, instr);
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after
2283 Register result = ToRegister(instr->result()); 2379 Register result = ToRegister(instr->result());
2284 __ mov(result, FieldOperand(global, GlobalObject::kGlobalReceiverOffset)); 2380 __ mov(result, FieldOperand(global, GlobalObject::kGlobalReceiverOffset));
2285 } 2381 }
2286 2382
2287 2383
2288 void LCodeGen::CallKnownFunction(Handle<JSFunction> function, 2384 void LCodeGen::CallKnownFunction(Handle<JSFunction> function,
2289 int arity, 2385 int arity,
2290 LInstruction* instr) { 2386 LInstruction* instr) {
2291 // Change context if needed. 2387 // Change context if needed.
2292 bool change_context = 2388 bool change_context =
2293 (graph()->info()->closure()->context() != function->context()) || 2389 (info()->closure()->context() != function->context()) ||
2294 scope()->contains_with() || 2390 scope()->contains_with() ||
2295 (scope()->num_heap_slots() > 0); 2391 (scope()->num_heap_slots() > 0);
2296 if (change_context) { 2392 if (change_context) {
2297 __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); 2393 __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset));
2298 } else { 2394 } else {
2299 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); 2395 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
2300 } 2396 }
2301 2397
2302 // Set eax to arguments count if adaption is not needed. Assumes that eax 2398 // Set eax to arguments count if adaption is not needed. Assumes that eax
2303 // is available to write to at this point. 2399 // is available to write to at this point.
2304 if (!function->NeedsArgumentsAdaption()) { 2400 if (!function->NeedsArgumentsAdaption()) {
2305 __ mov(eax, arity); 2401 __ mov(eax, arity);
2306 } 2402 }
2307 2403
2308 LPointerMap* pointers = instr->pointer_map(); 2404 LPointerMap* pointers = instr->pointer_map();
2309 RecordPosition(pointers->position()); 2405 RecordPosition(pointers->position());
2310 2406
2311 // Invoke function. 2407 // Invoke function.
2312 if (*function == *graph()->info()->closure()) { 2408 if (*function == *info()->closure()) {
2313 __ CallSelf(); 2409 __ CallSelf();
2314 } else { 2410 } else {
2315 // This is an indirect call and will not be recorded in the reloc info.
2316 // Add a comment to the reloc info in case we need to patch this during
2317 // deoptimization.
2318 __ RecordComment(RelocInfo::kFillerCommentString, true);
2319 __ call(FieldOperand(edi, JSFunction::kCodeEntryOffset)); 2411 __ call(FieldOperand(edi, JSFunction::kCodeEntryOffset));
2412 EnsureRelocSpaceForDeoptimization();
2320 } 2413 }
2321 2414
2322 // Setup deoptimization. 2415 // Setup deoptimization.
2323 RegisterLazyDeoptimization(instr); 2416 RegisterLazyDeoptimization(instr);
2324 } 2417 }
2325 2418
2326 2419
2327 void LCodeGen::DoCallConstantFunction(LCallConstantFunction* instr) { 2420 void LCodeGen::DoCallConstantFunction(LCallConstantFunction* instr) {
2328 ASSERT(ToRegister(instr->result()).is(eax)); 2421 ASSERT(ToRegister(instr->result()).is(eax));
2329 __ mov(edi, instr->function()); 2422 __ mov(edi, instr->function());
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
2364 __ bind(&slow); 2457 __ bind(&slow);
2365 2458
2366 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); 2459 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
2367 __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber); 2460 __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber);
2368 RecordSafepointWithRegisters( 2461 RecordSafepointWithRegisters(
2369 instr->pointer_map(), 0, Safepoint::kNoDeoptimizationIndex); 2462 instr->pointer_map(), 0, Safepoint::kNoDeoptimizationIndex);
2370 // Set the pointer to the new heap number in tmp. 2463 // Set the pointer to the new heap number in tmp.
2371 if (!tmp.is(eax)) __ mov(tmp, eax); 2464 if (!tmp.is(eax)) __ mov(tmp, eax);
2372 2465
2373 // Restore input_reg after call to runtime. 2466 // Restore input_reg after call to runtime.
2374 __ mov(input_reg, Operand(esp, EspIndexForPushAll(input_reg) * kPointerSize)); 2467 __ LoadFromSafepointRegisterSlot(input_reg, input_reg);
2375 2468
2376 __ bind(&allocated); 2469 __ bind(&allocated);
2377 __ mov(tmp2, FieldOperand(input_reg, HeapNumber::kExponentOffset)); 2470 __ mov(tmp2, FieldOperand(input_reg, HeapNumber::kExponentOffset));
2378 __ and_(tmp2, ~HeapNumber::kSignMask); 2471 __ and_(tmp2, ~HeapNumber::kSignMask);
2379 __ mov(FieldOperand(tmp, HeapNumber::kExponentOffset), tmp2); 2472 __ mov(FieldOperand(tmp, HeapNumber::kExponentOffset), tmp2);
2380 __ mov(tmp2, FieldOperand(input_reg, HeapNumber::kMantissaOffset)); 2473 __ mov(tmp2, FieldOperand(input_reg, HeapNumber::kMantissaOffset));
2381 __ mov(FieldOperand(tmp, HeapNumber::kMantissaOffset), tmp2); 2474 __ mov(FieldOperand(tmp, HeapNumber::kMantissaOffset), tmp2);
2382 __ mov(Operand(esp, EspIndexForPushAll(input_reg) * kPointerSize), tmp); 2475 __ StoreToSafepointRegisterSlot(input_reg, tmp);
2383 2476
2384 __ bind(&done); 2477 __ bind(&done);
2385 __ PopSafepointRegisters(); 2478 __ PopSafepointRegisters();
2386 } 2479 }
2387 2480
2388 2481
2389 void LCodeGen::EmitIntegerMathAbs(LUnaryMathOperation* instr) { 2482 void LCodeGen::EmitIntegerMathAbs(LUnaryMathOperation* instr) {
2390 Register input_reg = ToRegister(instr->InputAt(0)); 2483 Register input_reg = ToRegister(instr->InputAt(0));
2391 __ test(input_reg, Operand(input_reg)); 2484 __ test(input_reg, Operand(input_reg));
2392 Label is_positive; 2485 Label is_positive;
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
2497 XMMRegister input_reg = ToDoubleRegister(instr->InputAt(0)); 2590 XMMRegister input_reg = ToDoubleRegister(instr->InputAt(0));
2498 ASSERT(ToDoubleRegister(instr->result()).is(input_reg)); 2591 ASSERT(ToDoubleRegister(instr->result()).is(input_reg));
2499 __ sqrtsd(input_reg, input_reg); 2592 __ sqrtsd(input_reg, input_reg);
2500 } 2593 }
2501 2594
2502 2595
2503 void LCodeGen::DoMathPowHalf(LUnaryMathOperation* instr) { 2596 void LCodeGen::DoMathPowHalf(LUnaryMathOperation* instr) {
2504 XMMRegister xmm_scratch = xmm0; 2597 XMMRegister xmm_scratch = xmm0;
2505 XMMRegister input_reg = ToDoubleRegister(instr->InputAt(0)); 2598 XMMRegister input_reg = ToDoubleRegister(instr->InputAt(0));
2506 ASSERT(ToDoubleRegister(instr->result()).is(input_reg)); 2599 ASSERT(ToDoubleRegister(instr->result()).is(input_reg));
2507 ExternalReference negative_infinity =
2508 ExternalReference::address_of_negative_infinity();
2509 __ movdbl(xmm_scratch, Operand::StaticVariable(negative_infinity));
2510 __ ucomisd(xmm_scratch, input_reg);
2511 DeoptimizeIf(equal, instr->environment());
2512 __ xorpd(xmm_scratch, xmm_scratch); 2600 __ xorpd(xmm_scratch, xmm_scratch);
2513 __ addsd(input_reg, xmm_scratch); // Convert -0 to +0. 2601 __ addsd(input_reg, xmm_scratch); // Convert -0 to +0.
2514 __ sqrtsd(input_reg, input_reg); 2602 __ sqrtsd(input_reg, input_reg);
2515 } 2603 }
2516 2604
2517 2605
2518 void LCodeGen::DoPower(LPower* instr) { 2606 void LCodeGen::DoPower(LPower* instr) {
2519 LOperand* left = instr->InputAt(0); 2607 LOperand* left = instr->InputAt(0);
2520 LOperand* right = instr->InputAt(1); 2608 LOperand* right = instr->InputAt(1);
2521 DoubleRegister result_reg = ToDoubleRegister(instr->result()); 2609 DoubleRegister result_reg = ToDoubleRegister(instr->result());
(...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after
2724 } 2812 }
2725 } 2813 }
2726 2814
2727 2815
2728 void LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) { 2816 void LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) {
2729 ASSERT(ToRegister(instr->context()).is(esi)); 2817 ASSERT(ToRegister(instr->context()).is(esi));
2730 ASSERT(ToRegister(instr->object()).is(edx)); 2818 ASSERT(ToRegister(instr->object()).is(edx));
2731 ASSERT(ToRegister(instr->value()).is(eax)); 2819 ASSERT(ToRegister(instr->value()).is(eax));
2732 2820
2733 __ mov(ecx, instr->name()); 2821 __ mov(ecx, instr->name());
2734 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); 2822 Handle<Code> ic(Builtins::builtin(
2823 info_->is_strict() ? Builtins::StoreIC_Initialize_Strict
2824 : Builtins::StoreIC_Initialize));
2735 CallCode(ic, RelocInfo::CODE_TARGET, instr); 2825 CallCode(ic, RelocInfo::CODE_TARGET, instr);
2736 } 2826 }
2737 2827
2738 2828
2739 void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) { 2829 void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) {
2740 __ cmp(ToRegister(instr->index()), ToOperand(instr->length())); 2830 __ cmp(ToRegister(instr->index()), ToOperand(instr->length()));
2741 DeoptimizeIf(above_equal, instr->environment()); 2831 DeoptimizeIf(above_equal, instr->environment());
2742 } 2832 }
2743 2833
2744 2834
2835 void LCodeGen::DoStorePixelArrayElement(LStorePixelArrayElement* instr) {
2836 Register external_pointer = ToRegister(instr->external_pointer());
2837 Register key = ToRegister(instr->key());
2838 Register value = ToRegister(instr->value());
2839 ASSERT(ToRegister(instr->TempAt(0)).is(eax));
2840
2841 __ mov(eax, value);
2842 { // Clamp the value to [0..255].
2843 NearLabel done;
2844 __ test(eax, Immediate(0xFFFFFF00));
2845 __ j(zero, &done);
2846 __ setcc(negative, eax); // 1 if negative, 0 if positive.
2847 __ dec_b(eax); // 0 if negative, 255 if positive.
2848 __ bind(&done);
2849 }
2850 __ mov_b(Operand(external_pointer, key, times_1, 0), eax);
2851 }
2852
2853
2745 void LCodeGen::DoStoreKeyedFastElement(LStoreKeyedFastElement* instr) { 2854 void LCodeGen::DoStoreKeyedFastElement(LStoreKeyedFastElement* instr) {
2746 Register value = ToRegister(instr->value()); 2855 Register value = ToRegister(instr->value());
2747 Register elements = ToRegister(instr->object()); 2856 Register elements = ToRegister(instr->object());
2748 Register key = instr->key()->IsRegister() ? ToRegister(instr->key()) : no_reg; 2857 Register key = instr->key()->IsRegister() ? ToRegister(instr->key()) : no_reg;
2749 2858
2750 // Do the store. 2859 // Do the store.
2751 if (instr->key()->IsConstantOperand()) { 2860 if (instr->key()->IsConstantOperand()) {
2752 ASSERT(!instr->hydrogen()->NeedsWriteBarrier()); 2861 ASSERT(!instr->hydrogen()->NeedsWriteBarrier());
2753 LConstantOperand* const_operand = LConstantOperand::cast(instr->key()); 2862 LConstantOperand* const_operand = LConstantOperand::cast(instr->key());
2754 int offset = 2863 int offset =
(...skipping 18 matching lines...) Expand all
2773 } 2882 }
2774 } 2883 }
2775 2884
2776 2885
2777 void LCodeGen::DoStoreKeyedGeneric(LStoreKeyedGeneric* instr) { 2886 void LCodeGen::DoStoreKeyedGeneric(LStoreKeyedGeneric* instr) {
2778 ASSERT(ToRegister(instr->context()).is(esi)); 2887 ASSERT(ToRegister(instr->context()).is(esi));
2779 ASSERT(ToRegister(instr->object()).is(edx)); 2888 ASSERT(ToRegister(instr->object()).is(edx));
2780 ASSERT(ToRegister(instr->key()).is(ecx)); 2889 ASSERT(ToRegister(instr->key()).is(ecx));
2781 ASSERT(ToRegister(instr->value()).is(eax)); 2890 ASSERT(ToRegister(instr->value()).is(eax));
2782 2891
2783 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); 2892 Handle<Code> ic(Builtins::builtin(
2893 info_->is_strict() ? Builtins::KeyedStoreIC_Initialize_Strict
2894 : Builtins::KeyedStoreIC_Initialize));
2784 CallCode(ic, RelocInfo::CODE_TARGET, instr); 2895 CallCode(ic, RelocInfo::CODE_TARGET, instr);
2785 } 2896 }
2786 2897
2787 2898
2788 void LCodeGen::DoStringCharCodeAt(LStringCharCodeAt* instr) { 2899 void LCodeGen::DoStringCharCodeAt(LStringCharCodeAt* instr) {
2789 class DeferredStringCharCodeAt: public LDeferredCode { 2900 class DeferredStringCharCodeAt: public LDeferredCode {
2790 public: 2901 public:
2791 DeferredStringCharCodeAt(LCodeGen* codegen, LStringCharCodeAt* instr) 2902 DeferredStringCharCodeAt(LCodeGen* codegen, LStringCharCodeAt* instr)
2792 : LDeferredCode(codegen), instr_(instr) { } 2903 : LDeferredCode(codegen), instr_(instr) { }
2793 virtual void Generate() { codegen()->DoDeferredStringCharCodeAt(instr_); } 2904 virtual void Generate() { codegen()->DoDeferredStringCharCodeAt(instr_); }
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
2844 __ j(not_equal, deferred->entry()); 2955 __ j(not_equal, deferred->entry());
2845 // Get the first of the two strings and load its instance type. 2956 // Get the first of the two strings and load its instance type.
2846 __ mov(string, FieldOperand(string, ConsString::kFirstOffset)); 2957 __ mov(string, FieldOperand(string, ConsString::kFirstOffset));
2847 __ mov(result, FieldOperand(string, HeapObject::kMapOffset)); 2958 __ mov(result, FieldOperand(string, HeapObject::kMapOffset));
2848 __ movzx_b(result, FieldOperand(result, Map::kInstanceTypeOffset)); 2959 __ movzx_b(result, FieldOperand(result, Map::kInstanceTypeOffset));
2849 // If the first cons component is also non-flat, then go to runtime. 2960 // If the first cons component is also non-flat, then go to runtime.
2850 STATIC_ASSERT(kSeqStringTag == 0); 2961 STATIC_ASSERT(kSeqStringTag == 0);
2851 __ test(result, Immediate(kStringRepresentationMask)); 2962 __ test(result, Immediate(kStringRepresentationMask));
2852 __ j(not_zero, deferred->entry()); 2963 __ j(not_zero, deferred->entry());
2853 2964
2854 // Check for 1-byte or 2-byte string. 2965 // Check for ASCII or two-byte string.
2855 __ bind(&flat_string); 2966 __ bind(&flat_string);
2856 STATIC_ASSERT(kAsciiStringTag != 0); 2967 STATIC_ASSERT(kAsciiStringTag != 0);
2857 __ test(result, Immediate(kStringEncodingMask)); 2968 __ test(result, Immediate(kStringEncodingMask));
2858 __ j(not_zero, &ascii_string); 2969 __ j(not_zero, &ascii_string);
2859 2970
2860 // 2-byte string. 2971 // Two-byte string.
2861 // Load the 2-byte character code into the result register. 2972 // Load the two-byte character code into the result register.
2862 STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize == 1); 2973 STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize == 1);
2863 if (instr->index()->IsConstantOperand()) { 2974 if (instr->index()->IsConstantOperand()) {
2864 __ movzx_w(result, 2975 __ movzx_w(result,
2865 FieldOperand(string, 2976 FieldOperand(string,
2866 SeqTwoByteString::kHeaderSize + 2 * const_index)); 2977 SeqTwoByteString::kHeaderSize +
2978 (kUC16Size * const_index)));
2867 } else { 2979 } else {
2868 __ movzx_w(result, FieldOperand(string, 2980 __ movzx_w(result, FieldOperand(string,
2869 index, 2981 index,
2870 times_2, 2982 times_2,
2871 SeqTwoByteString::kHeaderSize)); 2983 SeqTwoByteString::kHeaderSize));
2872 } 2984 }
2873 __ jmp(&done); 2985 __ jmp(&done);
2874 2986
2875 // ASCII string. 2987 // ASCII string.
2876 // Load the byte into the result register. 2988 // Load the byte into the result register.
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
2912 __ push(index); 3024 __ push(index);
2913 } 3025 }
2914 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); 3026 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
2915 __ CallRuntimeSaveDoubles(Runtime::kStringCharCodeAt); 3027 __ CallRuntimeSaveDoubles(Runtime::kStringCharCodeAt);
2916 RecordSafepointWithRegisters( 3028 RecordSafepointWithRegisters(
2917 instr->pointer_map(), 2, Safepoint::kNoDeoptimizationIndex); 3029 instr->pointer_map(), 2, Safepoint::kNoDeoptimizationIndex);
2918 if (FLAG_debug_code) { 3030 if (FLAG_debug_code) {
2919 __ AbortIfNotSmi(eax); 3031 __ AbortIfNotSmi(eax);
2920 } 3032 }
2921 __ SmiUntag(eax); 3033 __ SmiUntag(eax);
2922 __ mov(Operand(esp, EspIndexForPushAll(result) * kPointerSize), eax); 3034 __ StoreToSafepointRegisterSlot(result, eax);
3035 __ PopSafepointRegisters();
3036 }
3037
3038
3039 void LCodeGen::DoStringCharFromCode(LStringCharFromCode* instr) {
3040 class DeferredStringCharFromCode: public LDeferredCode {
3041 public:
3042 DeferredStringCharFromCode(LCodeGen* codegen, LStringCharFromCode* instr)
3043 : LDeferredCode(codegen), instr_(instr) { }
3044 virtual void Generate() { codegen()->DoDeferredStringCharFromCode(instr_); }
3045 private:
3046 LStringCharFromCode* instr_;
3047 };
3048
3049 DeferredStringCharFromCode* deferred =
3050 new DeferredStringCharFromCode(this, instr);
3051
3052 ASSERT(instr->hydrogen()->value()->representation().IsInteger32());
3053 Register char_code = ToRegister(instr->char_code());
3054 Register result = ToRegister(instr->result());
3055 ASSERT(!char_code.is(result));
3056
3057 __ cmp(char_code, String::kMaxAsciiCharCode);
3058 __ j(above, deferred->entry());
3059 __ Set(result, Immediate(Factory::single_character_string_cache()));
3060 __ mov(result, FieldOperand(result,
3061 char_code, times_pointer_size,
3062 FixedArray::kHeaderSize));
3063 __ cmp(result, Factory::undefined_value());
3064 __ j(equal, deferred->entry());
3065 __ bind(deferred->exit());
3066 }
3067
3068
3069 void LCodeGen::DoDeferredStringCharFromCode(LStringCharFromCode* instr) {
3070 Register char_code = ToRegister(instr->char_code());
3071 Register result = ToRegister(instr->result());
3072
3073 // TODO(3095996): Get rid of this. For now, we need to make the
3074 // result register contain a valid pointer because it is already
3075 // contained in the register pointer map.
3076 __ Set(result, Immediate(0));
3077
3078 __ PushSafepointRegisters();
3079 __ SmiTag(char_code);
3080 __ push(char_code);
3081 __ CallRuntimeSaveDoubles(Runtime::kCharFromCode);
3082 RecordSafepointWithRegisters(
3083 instr->pointer_map(), 1, Safepoint::kNoDeoptimizationIndex);
3084 __ StoreToSafepointRegisterSlot(result, eax);
2923 __ PopSafepointRegisters(); 3085 __ PopSafepointRegisters();
2924 } 3086 }
2925 3087
2926 3088
2927 void LCodeGen::DoStringLength(LStringLength* instr) { 3089 void LCodeGen::DoStringLength(LStringLength* instr) {
2928 Register string = ToRegister(instr->string()); 3090 Register string = ToRegister(instr->string());
2929 Register result = ToRegister(instr->result()); 3091 Register result = ToRegister(instr->result());
2930 __ mov(result, FieldOperand(string, String::kLengthOffset)); 3092 __ mov(result, FieldOperand(string, String::kLengthOffset));
2931 } 3093 }
2932 3094
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
2980 __ AllocateHeapNumber(reg, tmp, no_reg, &slow); 3142 __ AllocateHeapNumber(reg, tmp, no_reg, &slow);
2981 __ jmp(&done); 3143 __ jmp(&done);
2982 } 3144 }
2983 3145
2984 // Slow case: Call the runtime system to do the number allocation. 3146 // Slow case: Call the runtime system to do the number allocation.
2985 __ bind(&slow); 3147 __ bind(&slow);
2986 3148
2987 // TODO(3095996): Put a valid pointer value in the stack slot where the result 3149 // TODO(3095996): Put a valid pointer value in the stack slot where the result
2988 // register is stored, as this register is in the pointer map, but contains an 3150 // register is stored, as this register is in the pointer map, but contains an
2989 // integer value. 3151 // integer value.
2990 __ mov(Operand(esp, EspIndexForPushAll(reg) * kPointerSize), Immediate(0)); 3152 __ StoreToSafepointRegisterSlot(reg, Immediate(0));
2991 3153
2992 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); 3154 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
2993 __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber); 3155 __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber);
2994 RecordSafepointWithRegisters( 3156 RecordSafepointWithRegisters(
2995 instr->pointer_map(), 0, Safepoint::kNoDeoptimizationIndex); 3157 instr->pointer_map(), 0, Safepoint::kNoDeoptimizationIndex);
2996 if (!reg.is(eax)) __ mov(reg, eax); 3158 if (!reg.is(eax)) __ mov(reg, eax);
2997 3159
2998 // Done. Put the value in xmm0 into the value of the allocated heap 3160 // Done. Put the value in xmm0 into the value of the allocated heap
2999 // number. 3161 // number.
3000 __ bind(&done); 3162 __ bind(&done);
3001 __ movdbl(FieldOperand(reg, HeapNumber::kValueOffset), xmm0); 3163 __ movdbl(FieldOperand(reg, HeapNumber::kValueOffset), xmm0);
3002 __ mov(Operand(esp, EspIndexForPushAll(reg) * kPointerSize), reg); 3164 __ StoreToSafepointRegisterSlot(reg, reg);
3003 __ PopSafepointRegisters(); 3165 __ PopSafepointRegisters();
3004 } 3166 }
3005 3167
3006 3168
3007 void LCodeGen::DoNumberTagD(LNumberTagD* instr) { 3169 void LCodeGen::DoNumberTagD(LNumberTagD* instr) {
3008 class DeferredNumberTagD: public LDeferredCode { 3170 class DeferredNumberTagD: public LDeferredCode {
3009 public: 3171 public:
3010 DeferredNumberTagD(LCodeGen* codegen, LNumberTagD* instr) 3172 DeferredNumberTagD(LCodeGen* codegen, LNumberTagD* instr)
3011 : LDeferredCode(codegen), instr_(instr) { } 3173 : LDeferredCode(codegen), instr_(instr) { }
3012 virtual void Generate() { codegen()->DoDeferredNumberTagD(instr_); } 3174 virtual void Generate() { codegen()->DoDeferredNumberTagD(instr_); }
(...skipping 21 matching lines...) Expand all
3034 // result register contain a valid pointer because it is already 3196 // result register contain a valid pointer because it is already
3035 // contained in the register pointer map. 3197 // contained in the register pointer map.
3036 Register reg = ToRegister(instr->result()); 3198 Register reg = ToRegister(instr->result());
3037 __ Set(reg, Immediate(0)); 3199 __ Set(reg, Immediate(0));
3038 3200
3039 __ PushSafepointRegisters(); 3201 __ PushSafepointRegisters();
3040 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); 3202 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
3041 __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber); 3203 __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber);
3042 RecordSafepointWithRegisters( 3204 RecordSafepointWithRegisters(
3043 instr->pointer_map(), 0, Safepoint::kNoDeoptimizationIndex); 3205 instr->pointer_map(), 0, Safepoint::kNoDeoptimizationIndex);
3044 __ mov(Operand(esp, EspIndexForPushAll(reg) * kPointerSize), eax); 3206 __ StoreToSafepointRegisterSlot(reg, eax);
3045 __ PopSafepointRegisters(); 3207 __ PopSafepointRegisters();
3046 } 3208 }
3047 3209
3048 3210
3049 void LCodeGen::DoSmiTag(LSmiTag* instr) { 3211 void LCodeGen::DoSmiTag(LSmiTag* instr) {
3050 LOperand* input = instr->InputAt(0); 3212 LOperand* input = instr->InputAt(0);
3051 ASSERT(input->IsRegister() && input->Equals(instr->result())); 3213 ASSERT(input->IsRegister() && input->Equals(instr->result()));
3052 ASSERT(!instr->hydrogen_value()->CheckFlag(HValue::kCanOverflow)); 3214 ASSERT(!instr->hydrogen_value()->CheckFlag(HValue::kCanOverflow));
3053 __ SmiTag(ToRegister(input)); 3215 __ SmiTag(ToRegister(input));
3054 } 3216 }
(...skipping 551 matching lines...) Expand 10 before | Expand all | Expand 10 after
3606 EmitBranch(true_block, false_block, final_branch_condition); 3768 EmitBranch(true_block, false_block, final_branch_condition);
3607 } 3769 }
3608 3770
3609 3771
3610 Condition LCodeGen::EmitTypeofIs(Label* true_label, 3772 Condition LCodeGen::EmitTypeofIs(Label* true_label,
3611 Label* false_label, 3773 Label* false_label,
3612 Register input, 3774 Register input,
3613 Handle<String> type_name) { 3775 Handle<String> type_name) {
3614 Condition final_branch_condition = no_condition; 3776 Condition final_branch_condition = no_condition;
3615 if (type_name->Equals(Heap::number_symbol())) { 3777 if (type_name->Equals(Heap::number_symbol())) {
3616 __ test(input, Immediate(kSmiTagMask)); 3778 __ JumpIfSmi(input, true_label);
3617 __ j(zero, true_label);
3618 __ cmp(FieldOperand(input, HeapObject::kMapOffset), 3779 __ cmp(FieldOperand(input, HeapObject::kMapOffset),
3619 Factory::heap_number_map()); 3780 Factory::heap_number_map());
3620 final_branch_condition = equal; 3781 final_branch_condition = equal;
3621 3782
3622 } else if (type_name->Equals(Heap::string_symbol())) { 3783 } else if (type_name->Equals(Heap::string_symbol())) {
3623 __ test(input, Immediate(kSmiTagMask)); 3784 __ JumpIfSmi(input, false_label);
3624 __ j(zero, false_label); 3785 __ CmpObjectType(input, FIRST_NONSTRING_TYPE, input);
3625 __ mov(input, FieldOperand(input, HeapObject::kMapOffset)); 3786 __ j(above_equal, false_label);
3626 __ test_b(FieldOperand(input, Map::kBitFieldOffset), 3787 __ test_b(FieldOperand(input, Map::kBitFieldOffset),
3627 1 << Map::kIsUndetectable); 3788 1 << Map::kIsUndetectable);
3628 __ j(not_zero, false_label); 3789 final_branch_condition = zero;
3629 __ CmpInstanceType(input, FIRST_NONSTRING_TYPE);
3630 final_branch_condition = below;
3631 3790
3632 } else if (type_name->Equals(Heap::boolean_symbol())) { 3791 } else if (type_name->Equals(Heap::boolean_symbol())) {
3633 __ cmp(input, Factory::true_value()); 3792 __ cmp(input, Factory::true_value());
3634 __ j(equal, true_label); 3793 __ j(equal, true_label);
3635 __ cmp(input, Factory::false_value()); 3794 __ cmp(input, Factory::false_value());
3636 final_branch_condition = equal; 3795 final_branch_condition = equal;
3637 3796
3638 } else if (type_name->Equals(Heap::undefined_symbol())) { 3797 } else if (type_name->Equals(Heap::undefined_symbol())) {
3639 __ cmp(input, Factory::undefined_value()); 3798 __ cmp(input, Factory::undefined_value());
3640 __ j(equal, true_label); 3799 __ j(equal, true_label);
3641 __ test(input, Immediate(kSmiTagMask)); 3800 __ JumpIfSmi(input, false_label);
3642 __ j(zero, false_label);
3643 // Check for undetectable objects => true. 3801 // Check for undetectable objects => true.
3644 __ mov(input, FieldOperand(input, HeapObject::kMapOffset)); 3802 __ mov(input, FieldOperand(input, HeapObject::kMapOffset));
3645 __ test_b(FieldOperand(input, Map::kBitFieldOffset), 3803 __ test_b(FieldOperand(input, Map::kBitFieldOffset),
3646 1 << Map::kIsUndetectable); 3804 1 << Map::kIsUndetectable);
3647 final_branch_condition = not_zero; 3805 final_branch_condition = not_zero;
3648 3806
3649 } else if (type_name->Equals(Heap::function_symbol())) { 3807 } else if (type_name->Equals(Heap::function_symbol())) {
3650 __ test(input, Immediate(kSmiTagMask)); 3808 __ JumpIfSmi(input, false_label);
3651 __ j(zero, false_label);
3652 __ CmpObjectType(input, JS_FUNCTION_TYPE, input); 3809 __ CmpObjectType(input, JS_FUNCTION_TYPE, input);
3653 __ j(equal, true_label); 3810 __ j(equal, true_label);
3654 // Regular expressions => 'function' (they are callable). 3811 // Regular expressions => 'function' (they are callable).
3655 __ CmpInstanceType(input, JS_REGEXP_TYPE); 3812 __ CmpInstanceType(input, JS_REGEXP_TYPE);
3656 final_branch_condition = equal; 3813 final_branch_condition = equal;
3657 3814
3658 } else if (type_name->Equals(Heap::object_symbol())) { 3815 } else if (type_name->Equals(Heap::object_symbol())) {
3659 __ test(input, Immediate(kSmiTagMask)); 3816 __ JumpIfSmi(input, false_label);
3660 __ j(zero, false_label);
3661 __ cmp(input, Factory::null_value()); 3817 __ cmp(input, Factory::null_value());
3662 __ j(equal, true_label); 3818 __ j(equal, true_label);
3663 // Regular expressions => 'function', not 'object'. 3819 // Regular expressions => 'function', not 'object'.
3664 __ CmpObjectType(input, JS_REGEXP_TYPE, input); 3820 __ CmpObjectType(input, FIRST_JS_OBJECT_TYPE, input);
3665 __ j(equal, false_label); 3821 __ j(below, false_label);
3822 __ CmpInstanceType(input, FIRST_FUNCTION_CLASS_TYPE);
3823 __ j(above_equal, false_label);
3666 // Check for undetectable objects => false. 3824 // Check for undetectable objects => false.
3667 __ test_b(FieldOperand(input, Map::kBitFieldOffset), 3825 __ test_b(FieldOperand(input, Map::kBitFieldOffset),
3668 1 << Map::kIsUndetectable); 3826 1 << Map::kIsUndetectable);
3669 __ j(not_zero, false_label); 3827 final_branch_condition = zero;
3670 // Check for JS objects => true.
3671 __ CmpInstanceType(input, FIRST_JS_OBJECT_TYPE);
3672 __ j(below, false_label);
3673 __ CmpInstanceType(input, LAST_JS_OBJECT_TYPE);
3674 final_branch_condition = below_equal;
3675 3828
3676 } else { 3829 } else {
3677 final_branch_condition = not_equal; 3830 final_branch_condition = not_equal;
3678 __ jmp(false_label); 3831 __ jmp(false_label);
3679 // A dead branch instruction will be generated after this point. 3832 // A dead branch instruction will be generated after this point.
3680 } 3833 }
3681 3834
3682 return final_branch_condition; 3835 return final_branch_condition;
3683 } 3836 }
3684 3837
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
3796 ASSERT(osr_pc_offset_ == -1); 3949 ASSERT(osr_pc_offset_ == -1);
3797 osr_pc_offset_ = masm()->pc_offset(); 3950 osr_pc_offset_ = masm()->pc_offset();
3798 } 3951 }
3799 3952
3800 3953
3801 #undef __ 3954 #undef __
3802 3955
3803 } } // namespace v8::internal 3956 } } // namespace v8::internal
3804 3957
3805 #endif // V8_TARGET_ARCH_IA32 3958 #endif // V8_TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « src/ia32/lithium-codegen-ia32.h ('k') | src/ia32/lithium-ia32.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698