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

Side by Side Diff: src/arm/lithium-codegen-arm.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/arm/lithium-codegen-arm.h ('k') | src/arm/lithium-gap-resolver-arm.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
11 // with the distribution. 11 // with the distribution.
12 // * Neither the name of Google Inc. nor the names of its 12 // * Neither the name of Google Inc. nor the names of its
13 // contributors may be used to endorse or promote products derived 13 // contributors may be used to endorse or promote products derived
14 // from this software without specific prior written permission. 14 // from this software without specific prior written permission.
15 // 15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 27
28 #include "arm/lithium-codegen-arm.h" 28 #include "arm/lithium-codegen-arm.h"
29 #include "arm/lithium-gap-resolver-arm.h"
29 #include "code-stubs.h" 30 #include "code-stubs.h"
30 #include "stub-cache.h" 31 #include "stub-cache.h"
31 32
32 namespace v8 { 33 namespace v8 {
33 namespace internal { 34 namespace internal {
34 35
35 36
36 class SafepointGenerator : public PostCallGenerator { 37 class SafepointGenerator : public CallWrapper {
37 public: 38 public:
38 SafepointGenerator(LCodeGen* codegen, 39 SafepointGenerator(LCodeGen* codegen,
39 LPointerMap* pointers, 40 LPointerMap* pointers,
40 int deoptimization_index) 41 int deoptimization_index)
41 : codegen_(codegen), 42 : codegen_(codegen),
42 pointers_(pointers), 43 pointers_(pointers),
43 deoptimization_index_(deoptimization_index) { } 44 deoptimization_index_(deoptimization_index) { }
44 virtual ~SafepointGenerator() { } 45 virtual ~SafepointGenerator() { }
45 46
46 virtual void Generate() { 47 virtual void BeforeCall(int call_size) {
48 ASSERT(call_size >= 0);
49 // Ensure that we have enough space after the previous safepoint position
50 // for the generated code there.
51 int call_end = codegen_->masm()->pc_offset() + call_size;
52 int prev_jump_end =
53 codegen_->LastSafepointEnd() + Deoptimizer::patch_size();
54 if (call_end < prev_jump_end) {
55 int padding_size = prev_jump_end - call_end;
56 ASSERT_EQ(0, padding_size % Assembler::kInstrSize);
57 while (padding_size > 0) {
58 codegen_->masm()->nop();
59 padding_size -= Assembler::kInstrSize;
60 }
61 }
62 }
63
64 virtual void AfterCall() {
47 codegen_->RecordSafepoint(pointers_, deoptimization_index_); 65 codegen_->RecordSafepoint(pointers_, deoptimization_index_);
48 } 66 }
49 67
50 private: 68 private:
51 LCodeGen* codegen_; 69 LCodeGen* codegen_;
52 LPointerMap* pointers_; 70 LPointerMap* pointers_;
53 int deoptimization_index_; 71 int deoptimization_index_;
54 }; 72 };
55 73
56 74
57 class LGapNode: public ZoneObject {
58 public:
59 explicit LGapNode(LOperand* operand)
60 : operand_(operand), resolved_(false), visited_id_(-1) { }
61
62 LOperand* operand() const { return operand_; }
63 bool IsResolved() const { return !IsAssigned() || resolved_; }
64 void MarkResolved() {
65 ASSERT(!IsResolved());
66 resolved_ = true;
67 }
68 int visited_id() const { return visited_id_; }
69 void set_visited_id(int id) {
70 ASSERT(id > visited_id_);
71 visited_id_ = id;
72 }
73
74 bool IsAssigned() const { return assigned_from_.is_set(); }
75 LGapNode* assigned_from() const { return assigned_from_.get(); }
76 void set_assigned_from(LGapNode* n) { assigned_from_.set(n); }
77
78 private:
79 LOperand* operand_;
80 SetOncePointer<LGapNode> assigned_from_;
81 bool resolved_;
82 int visited_id_;
83 };
84
85
86 LGapResolver::LGapResolver()
87 : nodes_(32),
88 identified_cycles_(4),
89 result_(16),
90 next_visited_id_(0) {
91 }
92
93
94 const ZoneList<LMoveOperands>* LGapResolver::Resolve(
95 const ZoneList<LMoveOperands>* moves,
96 LOperand* marker_operand) {
97 nodes_.Rewind(0);
98 identified_cycles_.Rewind(0);
99 result_.Rewind(0);
100 next_visited_id_ = 0;
101
102 for (int i = 0; i < moves->length(); ++i) {
103 LMoveOperands move = moves->at(i);
104 if (!move.IsRedundant()) RegisterMove(move);
105 }
106
107 for (int i = 0; i < identified_cycles_.length(); ++i) {
108 ResolveCycle(identified_cycles_[i], marker_operand);
109 }
110
111 int unresolved_nodes;
112 do {
113 unresolved_nodes = 0;
114 for (int j = 0; j < nodes_.length(); j++) {
115 LGapNode* node = nodes_[j];
116 if (!node->IsResolved() && node->assigned_from()->IsResolved()) {
117 AddResultMove(node->assigned_from(), node);
118 node->MarkResolved();
119 }
120 if (!node->IsResolved()) ++unresolved_nodes;
121 }
122 } while (unresolved_nodes > 0);
123 return &result_;
124 }
125
126
127 void LGapResolver::AddResultMove(LGapNode* from, LGapNode* to) {
128 AddResultMove(from->operand(), to->operand());
129 }
130
131
132 void LGapResolver::AddResultMove(LOperand* from, LOperand* to) {
133 result_.Add(LMoveOperands(from, to));
134 }
135
136
137 void LGapResolver::ResolveCycle(LGapNode* start, LOperand* marker_operand) {
138 ZoneList<LOperand*> cycle_operands(8);
139 cycle_operands.Add(marker_operand);
140 LGapNode* cur = start;
141 do {
142 cur->MarkResolved();
143 cycle_operands.Add(cur->operand());
144 cur = cur->assigned_from();
145 } while (cur != start);
146 cycle_operands.Add(marker_operand);
147
148 for (int i = cycle_operands.length() - 1; i > 0; --i) {
149 LOperand* from = cycle_operands[i];
150 LOperand* to = cycle_operands[i - 1];
151 AddResultMove(from, to);
152 }
153 }
154
155
156 bool LGapResolver::CanReach(LGapNode* a, LGapNode* b, int visited_id) {
157 ASSERT(a != b);
158 LGapNode* cur = a;
159 while (cur != b && cur->visited_id() != visited_id && cur->IsAssigned()) {
160 cur->set_visited_id(visited_id);
161 cur = cur->assigned_from();
162 }
163
164 return cur == b;
165 }
166
167
168 bool LGapResolver::CanReach(LGapNode* a, LGapNode* b) {
169 ASSERT(a != b);
170 return CanReach(a, b, next_visited_id_++);
171 }
172
173
174 void LGapResolver::RegisterMove(LMoveOperands move) {
175 if (move.source()->IsConstantOperand()) {
176 // Constant moves should be last in the machine code. Therefore add them
177 // first to the result set.
178 AddResultMove(move.source(), move.destination());
179 } else {
180 LGapNode* from = LookupNode(move.source());
181 LGapNode* to = LookupNode(move.destination());
182 if (to->IsAssigned() && to->assigned_from() == from) {
183 move.Eliminate();
184 return;
185 }
186 ASSERT(!to->IsAssigned());
187 if (CanReach(from, to)) {
188 // This introduces a cycle. Save.
189 identified_cycles_.Add(from);
190 }
191 to->set_assigned_from(from);
192 }
193 }
194
195
196 LGapNode* LGapResolver::LookupNode(LOperand* operand) {
197 for (int i = 0; i < nodes_.length(); ++i) {
198 if (nodes_[i]->operand()->Equals(operand)) return nodes_[i];
199 }
200
201 // No node found => create a new one.
202 LGapNode* result = new LGapNode(operand);
203 nodes_.Add(result);
204 return result;
205 }
206
207
208 #define __ masm()-> 75 #define __ masm()->
209 76
210 bool LCodeGen::GenerateCode() { 77 bool LCodeGen::GenerateCode() {
211 HPhase phase("Code generation", chunk()); 78 HPhase phase("Code generation", chunk());
212 ASSERT(is_unused()); 79 ASSERT(is_unused());
213 status_ = GENERATING; 80 status_ = GENERATING;
214 CpuFeatures::Scope scope1(VFP3); 81 CpuFeatures::Scope scope1(VFP3);
215 CpuFeatures::Scope scope2(ARMv7); 82 CpuFeatures::Scope scope2(ARMv7);
216 return GeneratePrologue() && 83 return GeneratePrologue() &&
217 GenerateBody() && 84 GenerateBody() &&
218 GenerateDeferredCode() && 85 GenerateDeferredCode() &&
219 GenerateSafepointTable(); 86 GenerateSafepointTable();
220 } 87 }
221 88
222 89
223 void LCodeGen::FinishCode(Handle<Code> code) { 90 void LCodeGen::FinishCode(Handle<Code> code) {
224 ASSERT(is_done()); 91 ASSERT(is_done());
225 code->set_stack_slots(StackSlotCount()); 92 code->set_stack_slots(StackSlotCount());
226 code->set_safepoint_table_offset(safepoints_.GetCodeOffset()); 93 code->set_safepoint_table_offset(safepoints_.GetCodeOffset());
227 PopulateDeoptimizationData(code); 94 PopulateDeoptimizationData(code);
228 } 95 }
229 96
230 97
231 void LCodeGen::Abort(const char* format, ...) { 98 void LCodeGen::Abort(const char* format, ...) {
232 if (FLAG_trace_bailout) { 99 if (FLAG_trace_bailout) {
233 SmartPointer<char> debug_name = graph()->debug_name()->ToCString(); 100 SmartPointer<char> name(info()->shared_info()->DebugName()->ToCString());
234 PrintF("Aborting LCodeGen in @\"%s\": ", *debug_name); 101 PrintF("Aborting LCodeGen in @\"%s\": ", *name);
235 va_list arguments; 102 va_list arguments;
236 va_start(arguments, format); 103 va_start(arguments, format);
237 OS::VPrint(format, arguments); 104 OS::VPrint(format, arguments);
238 va_end(arguments); 105 va_end(arguments);
239 PrintF("\n"); 106 PrintF("\n");
240 } 107 }
241 status_ = ABORTED; 108 status_ = ABORTED;
242 } 109 }
243 110
244 111
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
287 Label loop; 154 Label loop;
288 __ bind(&loop); 155 __ bind(&loop);
289 __ push(r2); 156 __ push(r2);
290 __ sub(r0, r0, Operand(1), SetCC); 157 __ sub(r0, r0, Operand(1), SetCC);
291 __ b(ne, &loop); 158 __ b(ne, &loop);
292 } else { 159 } else {
293 __ sub(sp, sp, Operand(slots * kPointerSize)); 160 __ sub(sp, sp, Operand(slots * kPointerSize));
294 } 161 }
295 } 162 }
296 163
164 // Possibly allocate a local context.
165 int heap_slots = scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
166 if (heap_slots > 0) {
167 Comment(";;; Allocate local context");
168 // Argument to NewContext is the function, which is in r1.
169 __ push(r1);
170 if (heap_slots <= FastNewContextStub::kMaximumSlots) {
171 FastNewContextStub stub(heap_slots);
172 __ CallStub(&stub);
173 } else {
174 __ CallRuntime(Runtime::kNewContext, 1);
175 }
176 RecordSafepoint(Safepoint::kNoDeoptimizationIndex);
177 // Context is returned in both r0 and cp. It replaces the context
178 // passed to us. It's saved in the stack and kept live in cp.
179 __ str(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
180 // Copy any necessary parameters into the context.
181 int num_parameters = scope()->num_parameters();
182 for (int i = 0; i < num_parameters; i++) {
183 Slot* slot = scope()->parameter(i)->AsSlot();
184 if (slot != NULL && slot->type() == Slot::CONTEXT) {
185 int parameter_offset = StandardFrameConstants::kCallerSPOffset +
186 (num_parameters - 1 - i) * kPointerSize;
187 // Load parameter from stack.
188 __ ldr(r0, MemOperand(fp, parameter_offset));
189 // Store it in the context.
190 __ mov(r1, Operand(Context::SlotOffset(slot->index())));
191 __ str(r0, MemOperand(cp, r1));
192 // Update the write barrier. This clobbers all involved
193 // registers, so we have to use two more registers to avoid
194 // clobbering cp.
195 __ mov(r2, Operand(cp));
196 __ RecordWrite(r2, Operand(r1), r3, r0);
197 }
198 }
199 Comment(";;; End allocate local context");
200 }
201
297 // Trace the call. 202 // Trace the call.
298 if (FLAG_trace) { 203 if (FLAG_trace) {
299 __ CallRuntime(Runtime::kTraceEnter, 0); 204 __ CallRuntime(Runtime::kTraceEnter, 0);
300 } 205 }
301 return !is_aborted(); 206 return !is_aborted();
302 } 207 }
303 208
304 209
305 bool LCodeGen::GenerateBody() { 210 bool LCodeGen::GenerateBody() {
306 ASSERT(is_generating()); 211 ASSERT(is_generating());
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after
457 Abort("ToOperand IsDoubleRegister unimplemented"); 362 Abort("ToOperand IsDoubleRegister unimplemented");
458 return Operand(0); 363 return Operand(0);
459 } 364 }
460 // Stack slots not implemented, use ToMemOperand instead. 365 // Stack slots not implemented, use ToMemOperand instead.
461 UNREACHABLE(); 366 UNREACHABLE();
462 return Operand(0); 367 return Operand(0);
463 } 368 }
464 369
465 370
466 MemOperand LCodeGen::ToMemOperand(LOperand* op) const { 371 MemOperand LCodeGen::ToMemOperand(LOperand* op) const {
467 // TODO(regis): Revisit.
468 ASSERT(!op->IsRegister()); 372 ASSERT(!op->IsRegister());
469 ASSERT(!op->IsDoubleRegister()); 373 ASSERT(!op->IsDoubleRegister());
470 ASSERT(op->IsStackSlot() || op->IsDoubleStackSlot()); 374 ASSERT(op->IsStackSlot() || op->IsDoubleStackSlot());
471 int index = op->index(); 375 int index = op->index();
472 if (index >= 0) { 376 if (index >= 0) {
473 // Local or spill slot. Skip the frame pointer, function, and 377 // Local or spill slot. Skip the frame pointer, function, and
474 // context in the fixed part of the frame. 378 // context in the fixed part of the frame.
475 return MemOperand(fp, -(index + 3) * kPointerSize); 379 return MemOperand(fp, -(index + 3) * kPointerSize);
476 } else { 380 } else {
477 // Incoming parameter. Skip the return address. 381 // Incoming parameter. Skip the return address.
478 return MemOperand(fp, -(index - 1) * kPointerSize); 382 return MemOperand(fp, -(index - 1) * kPointerSize);
479 } 383 }
480 } 384 }
481 385
482 386
387 MemOperand LCodeGen::ToHighMemOperand(LOperand* op) const {
388 ASSERT(op->IsDoubleStackSlot());
389 int index = op->index();
390 if (index >= 0) {
391 // Local or spill slot. Skip the frame pointer, function, context,
392 // and the first word of the double in the fixed part of the frame.
393 return MemOperand(fp, -(index + 3) * kPointerSize + kPointerSize);
394 } else {
395 // Incoming parameter. Skip the return address and the first word of
396 // the double.
397 return MemOperand(fp, -(index - 1) * kPointerSize + kPointerSize);
398 }
399 }
400
401
483 void LCodeGen::WriteTranslation(LEnvironment* environment, 402 void LCodeGen::WriteTranslation(LEnvironment* environment,
484 Translation* translation) { 403 Translation* translation) {
485 if (environment == NULL) return; 404 if (environment == NULL) return;
486 405
487 // The translation includes one command per value in the environment. 406 // The translation includes one command per value in the environment.
488 int translation_size = environment->values()->length(); 407 int translation_size = environment->values()->length();
489 // The output frame height does not include the parameters. 408 // The output frame height does not include the parameters.
490 int height = translation_size - environment->parameter_count(); 409 int height = translation_size - environment->parameter_count();
491 410
492 WriteTranslation(environment->outer(), translation); 411 WriteTranslation(environment->outer(), translation);
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after
664 } 583 }
665 584
666 585
667 void LCodeGen::PopulateDeoptimizationData(Handle<Code> code) { 586 void LCodeGen::PopulateDeoptimizationData(Handle<Code> code) {
668 int length = deoptimizations_.length(); 587 int length = deoptimizations_.length();
669 if (length == 0) return; 588 if (length == 0) return;
670 ASSERT(FLAG_deopt); 589 ASSERT(FLAG_deopt);
671 Handle<DeoptimizationInputData> data = 590 Handle<DeoptimizationInputData> data =
672 Factory::NewDeoptimizationInputData(length, TENURED); 591 Factory::NewDeoptimizationInputData(length, TENURED);
673 592
674 data->SetTranslationByteArray(*translations_.CreateByteArray()); 593 Handle<ByteArray> translations = translations_.CreateByteArray();
594 data->SetTranslationByteArray(*translations);
675 data->SetInlinedFunctionCount(Smi::FromInt(inlined_function_count_)); 595 data->SetInlinedFunctionCount(Smi::FromInt(inlined_function_count_));
676 596
677 Handle<FixedArray> literals = 597 Handle<FixedArray> literals =
678 Factory::NewFixedArray(deoptimization_literals_.length(), TENURED); 598 Factory::NewFixedArray(deoptimization_literals_.length(), TENURED);
679 for (int i = 0; i < deoptimization_literals_.length(); i++) { 599 for (int i = 0; i < deoptimization_literals_.length(); i++) {
680 literals->set(i, *deoptimization_literals_[i]); 600 literals->set(i, *deoptimization_literals_[i]);
681 } 601 }
682 data->SetLiteralArray(*literals); 602 data->SetLiteralArray(*literals);
683 603
684 data->SetOsrAstId(Smi::FromInt(info_->osr_ast_id())); 604 data->SetOsrAstId(Smi::FromInt(info_->osr_ast_id()));
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
744 } 664 }
745 } 665 }
746 666
747 667
748 void LCodeGen::RecordSafepoint(LPointerMap* pointers, 668 void LCodeGen::RecordSafepoint(LPointerMap* pointers,
749 int deoptimization_index) { 669 int deoptimization_index) {
750 RecordSafepoint(pointers, Safepoint::kSimple, 0, deoptimization_index); 670 RecordSafepoint(pointers, Safepoint::kSimple, 0, deoptimization_index);
751 } 671 }
752 672
753 673
674 void LCodeGen::RecordSafepoint(int deoptimization_index) {
675 LPointerMap empty_pointers(RelocInfo::kNoPosition);
676 RecordSafepoint(&empty_pointers, deoptimization_index);
677 }
678
679
754 void LCodeGen::RecordSafepointWithRegisters(LPointerMap* pointers, 680 void LCodeGen::RecordSafepointWithRegisters(LPointerMap* pointers,
755 int arguments, 681 int arguments,
756 int deoptimization_index) { 682 int deoptimization_index) {
757 RecordSafepoint(pointers, Safepoint::kWithRegisters, arguments, 683 RecordSafepoint(pointers, Safepoint::kWithRegisters, arguments,
758 deoptimization_index); 684 deoptimization_index);
759 } 685 }
760 686
761 687
762 void LCodeGen::RecordSafepointWithRegistersAndDoubles( 688 void LCodeGen::RecordSafepointWithRegistersAndDoubles(
763 LPointerMap* pointers, 689 LPointerMap* pointers,
(...skipping 16 matching lines...) Expand all
780 } else { 706 } else {
781 Comment(";;; B%d", label->block_id()); 707 Comment(";;; B%d", label->block_id());
782 } 708 }
783 __ bind(label->label()); 709 __ bind(label->label());
784 current_block_ = label->block_id(); 710 current_block_ = label->block_id();
785 LCodeGen::DoGap(label); 711 LCodeGen::DoGap(label);
786 } 712 }
787 713
788 714
789 void LCodeGen::DoParallelMove(LParallelMove* move) { 715 void LCodeGen::DoParallelMove(LParallelMove* move) {
790 // d0 must always be a scratch register. 716 resolver_.Resolve(move);
791 DoubleRegister dbl_scratch = d0;
792 LUnallocated marker_operand(LUnallocated::NONE);
793
794 Register core_scratch = scratch0();
795 bool destroys_core_scratch = false;
796
797 const ZoneList<LMoveOperands>* moves =
798 resolver_.Resolve(move->move_operands(), &marker_operand);
799 for (int i = moves->length() - 1; i >= 0; --i) {
800 LMoveOperands move = moves->at(i);
801 LOperand* from = move.source();
802 LOperand* to = move.destination();
803 ASSERT(!from->IsDoubleRegister() ||
804 !ToDoubleRegister(from).is(dbl_scratch));
805 ASSERT(!to->IsDoubleRegister() || !ToDoubleRegister(to).is(dbl_scratch));
806 ASSERT(!from->IsRegister() || !ToRegister(from).is(core_scratch));
807 ASSERT(!to->IsRegister() || !ToRegister(to).is(core_scratch));
808 if (from == &marker_operand) {
809 if (to->IsRegister()) {
810 __ mov(ToRegister(to), core_scratch);
811 ASSERT(destroys_core_scratch);
812 } else if (to->IsStackSlot()) {
813 __ str(core_scratch, ToMemOperand(to));
814 ASSERT(destroys_core_scratch);
815 } else if (to->IsDoubleRegister()) {
816 __ vmov(ToDoubleRegister(to), dbl_scratch);
817 } else {
818 ASSERT(to->IsDoubleStackSlot());
819 // TODO(regis): Why is vstr not taking a MemOperand?
820 // __ vstr(dbl_scratch, ToMemOperand(to));
821 MemOperand to_operand = ToMemOperand(to);
822 __ vstr(dbl_scratch, to_operand.rn(), to_operand.offset());
823 }
824 } else if (to == &marker_operand) {
825 if (from->IsRegister() || from->IsConstantOperand()) {
826 __ mov(core_scratch, ToOperand(from));
827 destroys_core_scratch = true;
828 } else if (from->IsStackSlot()) {
829 __ ldr(core_scratch, ToMemOperand(from));
830 destroys_core_scratch = true;
831 } else if (from->IsDoubleRegister()) {
832 __ vmov(dbl_scratch, ToDoubleRegister(from));
833 } else {
834 ASSERT(from->IsDoubleStackSlot());
835 // TODO(regis): Why is vldr not taking a MemOperand?
836 // __ vldr(dbl_scratch, ToMemOperand(from));
837 MemOperand from_operand = ToMemOperand(from);
838 __ vldr(dbl_scratch, from_operand.rn(), from_operand.offset());
839 }
840 } else if (from->IsConstantOperand()) {
841 if (to->IsRegister()) {
842 __ mov(ToRegister(to), ToOperand(from));
843 } else {
844 ASSERT(to->IsStackSlot());
845 __ mov(ip, ToOperand(from));
846 __ str(ip, ToMemOperand(to));
847 }
848 } else if (from->IsRegister()) {
849 if (to->IsRegister()) {
850 __ mov(ToRegister(to), ToOperand(from));
851 } else {
852 ASSERT(to->IsStackSlot());
853 __ str(ToRegister(from), ToMemOperand(to));
854 }
855 } else if (to->IsRegister()) {
856 ASSERT(from->IsStackSlot());
857 __ ldr(ToRegister(to), ToMemOperand(from));
858 } else if (from->IsStackSlot()) {
859 ASSERT(to->IsStackSlot());
860 __ ldr(ip, ToMemOperand(from));
861 __ str(ip, ToMemOperand(to));
862 } else if (from->IsDoubleRegister()) {
863 if (to->IsDoubleRegister()) {
864 __ vmov(ToDoubleRegister(to), ToDoubleRegister(from));
865 } else {
866 ASSERT(to->IsDoubleStackSlot());
867 // TODO(regis): Why is vstr not taking a MemOperand?
868 // __ vstr(dbl_scratch, ToMemOperand(to));
869 MemOperand to_operand = ToMemOperand(to);
870 __ vstr(ToDoubleRegister(from), to_operand.rn(), to_operand.offset());
871 }
872 } else if (to->IsDoubleRegister()) {
873 ASSERT(from->IsDoubleStackSlot());
874 // TODO(regis): Why is vldr not taking a MemOperand?
875 // __ vldr(ToDoubleRegister(to), ToMemOperand(from));
876 MemOperand from_operand = ToMemOperand(from);
877 __ vldr(ToDoubleRegister(to), from_operand.rn(), from_operand.offset());
878 } else {
879 ASSERT(to->IsDoubleStackSlot() && from->IsDoubleStackSlot());
880 // TODO(regis): Why is vldr not taking a MemOperand?
881 // __ vldr(dbl_scratch, ToMemOperand(from));
882 MemOperand from_operand = ToMemOperand(from);
883 __ vldr(dbl_scratch, from_operand.rn(), from_operand.offset());
884 // TODO(regis): Why is vstr not taking a MemOperand?
885 // __ vstr(dbl_scratch, ToMemOperand(to));
886 MemOperand to_operand = ToMemOperand(to);
887 __ vstr(dbl_scratch, to_operand.rn(), to_operand.offset());
888 }
889 }
890
891 if (destroys_core_scratch) {
892 __ ldr(core_scratch, MemOperand(fp, -kPointerSize));
893 }
894
895 LInstruction* next = GetNextInstruction();
896 if (next != NULL && next->IsLazyBailout()) {
897 int pc = masm()->pc_offset();
898 safepoints_.SetPcAfterGap(pc);
899 }
900 } 717 }
901 718
902 719
903 void LCodeGen::DoGap(LGap* gap) { 720 void LCodeGen::DoGap(LGap* gap) {
904 for (int i = LGap::FIRST_INNER_POSITION; 721 for (int i = LGap::FIRST_INNER_POSITION;
905 i <= LGap::LAST_INNER_POSITION; 722 i <= LGap::LAST_INNER_POSITION;
906 i++) { 723 i++) {
907 LGap::InnerPosition inner_pos = static_cast<LGap::InnerPosition>(i); 724 LGap::InnerPosition inner_pos = static_cast<LGap::InnerPosition>(i);
908 LParallelMove* move = gap->GetParallelMove(inner_pos); 725 LParallelMove* move = gap->GetParallelMove(inner_pos);
909 if (move != NULL) DoParallelMove(move); 726 if (move != NULL) DoParallelMove(move);
(...skipping 23 matching lines...) Expand all
933 case CodeStub::RegExpExec: { 750 case CodeStub::RegExpExec: {
934 RegExpExecStub stub; 751 RegExpExecStub stub;
935 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); 752 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
936 break; 753 break;
937 } 754 }
938 case CodeStub::SubString: { 755 case CodeStub::SubString: {
939 SubStringStub stub; 756 SubStringStub stub;
940 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); 757 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
941 break; 758 break;
942 } 759 }
943 case CodeStub::StringCharAt: {
944 StringCharAtStub stub;
945 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
946 break;
947 }
948 case CodeStub::MathPow: {
949 Abort("MathPowStub unimplemented.");
950 break;
951 }
952 case CodeStub::NumberToString: { 760 case CodeStub::NumberToString: {
953 NumberToStringStub stub; 761 NumberToStringStub stub;
954 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); 762 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
955 break; 763 break;
956 } 764 }
957 case CodeStub::StringAdd: { 765 case CodeStub::StringAdd: {
958 StringAddStub stub(NO_STRING_ADD_FLAGS); 766 StringAddStub stub(NO_STRING_ADD_FLAGS);
959 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); 767 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
960 break; 768 break;
961 } 769 }
962 case CodeStub::StringCompare: { 770 case CodeStub::StringCompare: {
963 StringCompareStub stub; 771 StringCompareStub stub;
964 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); 772 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
965 break; 773 break;
966 } 774 }
967 case CodeStub::TranscendentalCache: { 775 case CodeStub::TranscendentalCache: {
968 __ ldr(r0, MemOperand(sp, 0)); 776 __ ldr(r0, MemOperand(sp, 0));
969 TranscendentalCacheStub stub(instr->transcendental_type()); 777 TranscendentalCacheStub stub(instr->transcendental_type(),
778 TranscendentalCacheStub::TAGGED);
970 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); 779 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
971 break; 780 break;
972 } 781 }
973 default: 782 default:
974 UNREACHABLE(); 783 UNREACHABLE();
975 } 784 }
976 } 785 }
977 786
978 787
979 void LCodeGen::DoUnknownOSRValue(LUnknownOSRValue* instr) { 788 void LCodeGen::DoUnknownOSRValue(LUnknownOSRValue* instr) {
980 // Nothing to do. 789 // Nothing to do.
981 } 790 }
982 791
983 792
984 void LCodeGen::DoModI(LModI* instr) { 793 void LCodeGen::DoModI(LModI* instr) {
794 if (instr->hydrogen()->HasPowerOf2Divisor()) {
795 Register dividend = ToRegister(instr->InputAt(0));
796
797 int32_t divisor =
798 HConstant::cast(instr->hydrogen()->right())->Integer32Value();
799
800 if (divisor < 0) divisor = -divisor;
801
802 Label positive_dividend, done;
803 __ tst(dividend, Operand(dividend));
804 __ b(pl, &positive_dividend);
805 __ rsb(dividend, dividend, Operand(0));
806 __ and_(dividend, dividend, Operand(divisor - 1));
807 __ rsb(dividend, dividend, Operand(0), SetCC);
808 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
809 __ b(ne, &done);
810 DeoptimizeIf(al, instr->environment());
811 }
812 __ bind(&positive_dividend);
813 __ and_(dividend, dividend, Operand(divisor - 1));
814 __ bind(&done);
815 return;
816 }
817
985 class DeferredModI: public LDeferredCode { 818 class DeferredModI: public LDeferredCode {
986 public: 819 public:
987 DeferredModI(LCodeGen* codegen, LModI* instr) 820 DeferredModI(LCodeGen* codegen, LModI* instr)
988 : LDeferredCode(codegen), instr_(instr) { } 821 : LDeferredCode(codegen), instr_(instr) { }
989 virtual void Generate() { 822 virtual void Generate() {
990 codegen()->DoDeferredGenericBinaryStub(instr_, Token::MOD); 823 codegen()->DoDeferredBinaryOpStub(instr_, Token::MOD);
991 } 824 }
992 private: 825 private:
993 LModI* instr_; 826 LModI* instr_;
994 }; 827 };
995 // These registers hold untagged 32 bit values. 828 // These registers hold untagged 32 bit values.
996 Register left = ToRegister(instr->InputAt(0)); 829 Register left = ToRegister(instr->InputAt(0));
997 Register right = ToRegister(instr->InputAt(1)); 830 Register right = ToRegister(instr->InputAt(1));
998 Register result = ToRegister(instr->result()); 831 Register result = ToRegister(instr->result());
999 Register scratch = scratch0(); 832 Register scratch = scratch0();
1000 833
1001 Label deoptimize, done; 834 Label deoptimize, done;
1002 // Check for x % 0. 835 // Check for x % 0.
1003 if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) { 836 if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) {
1004 __ tst(right, Operand(right)); 837 __ tst(right, Operand(right));
1005 __ b(eq, &deoptimize); 838 __ b(eq, &deoptimize);
1006 } 839 }
1007 840
1008 // Check for (0 % -x) that will produce negative zero. 841 // Check for (0 % -x) that will produce negative zero.
1009 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 842 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
1010 Label ok; 843 Label ok;
1011 __ tst(left, Operand(left)); 844 __ tst(left, Operand(left));
1012 __ b(ne, &ok); 845 __ b(ne, &ok);
1013 __ tst(right, Operand(right)); 846 __ tst(right, Operand(right));
1014 __ b(pl, &ok); 847 __ b(pl, &ok);
1015 __ b(al, &deoptimize); 848 __ b(al, &deoptimize);
1016 __ bind(&ok); 849 __ bind(&ok);
1017 } 850 }
1018 851
1019 // Try a few common cases before using the generic stub. 852 // Try a few common cases before using the stub.
1020 Label call_stub; 853 Label call_stub;
1021 const int kUnfolds = 3; 854 const int kUnfolds = 3;
1022 // Skip if either side is negative. 855 // Skip if either side is negative.
1023 __ cmp(left, Operand(0)); 856 __ cmp(left, Operand(0));
1024 __ cmp(right, Operand(0), NegateCondition(mi)); 857 __ cmp(right, Operand(0), NegateCondition(mi));
1025 __ b(mi, &call_stub); 858 __ b(mi, &call_stub);
1026 // If the right hand side is smaller than the (nonnegative) 859 // If the right hand side is smaller than the (nonnegative)
1027 // left hand side, it is the result. Else try a few subtractions 860 // left hand side, it is the result. Else try a few subtractions
1028 // of the left hand side. 861 // of the left hand side.
1029 __ mov(scratch, left); 862 __ mov(scratch, left);
1030 for (int i = 0; i < kUnfolds; i++) { 863 for (int i = 0; i < kUnfolds; i++) {
1031 // Check if the left hand side is less or equal than the 864 // Check if the left hand side is less or equal than the
1032 // the right hand side. 865 // the right hand side.
1033 __ cmp(scratch, right); 866 __ cmp(scratch, right);
1034 __ mov(result, scratch, LeaveCC, lt); 867 __ mov(result, scratch, LeaveCC, lt);
1035 __ b(lt, &done); 868 __ b(lt, &done);
1036 // If not, reduce the left hand side by the right hand 869 // If not, reduce the left hand side by the right hand
1037 // side and check again. 870 // side and check again.
1038 if (i < kUnfolds - 1) __ sub(scratch, scratch, right); 871 if (i < kUnfolds - 1) __ sub(scratch, scratch, right);
1039 } 872 }
1040 873
1041 // Check for power of two on the right hand side. 874 // Check for power of two on the right hand side.
1042 __ JumpIfNotPowerOfTwoOrZero(right, scratch, &call_stub); 875 __ JumpIfNotPowerOfTwoOrZero(right, scratch, &call_stub);
1043 // Perform modulo operation (scratch contains right - 1). 876 // Perform modulo operation (scratch contains right - 1).
1044 __ and_(result, scratch, Operand(left)); 877 __ and_(result, scratch, Operand(left));
878 __ b(&done);
1045 879
1046 __ bind(&call_stub); 880 __ bind(&call_stub);
1047 // Call the generic stub. The numbers in r0 and r1 have 881 // Call the stub. The numbers in r0 and r1 have
1048 // to be tagged to Smis. If that is not possible, deoptimize. 882 // to be tagged to Smis. If that is not possible, deoptimize.
1049 DeferredModI* deferred = new DeferredModI(this, instr); 883 DeferredModI* deferred = new DeferredModI(this, instr);
1050 __ TrySmiTag(left, &deoptimize, scratch); 884 __ TrySmiTag(left, &deoptimize, scratch);
1051 __ TrySmiTag(right, &deoptimize, scratch); 885 __ TrySmiTag(right, &deoptimize, scratch);
1052 886
1053 __ b(al, deferred->entry()); 887 __ b(al, deferred->entry());
1054 __ bind(deferred->exit()); 888 __ bind(deferred->exit());
1055 889
1056 // If the result in r0 is a Smi, untag it, else deoptimize. 890 // If the result in r0 is a Smi, untag it, else deoptimize.
1057 __ JumpIfNotSmi(result, &deoptimize); 891 __ JumpIfNotSmi(result, &deoptimize);
1058 __ SmiUntag(result); 892 __ SmiUntag(result);
1059 893
1060 __ b(al, &done); 894 __ b(al, &done);
1061 __ bind(&deoptimize); 895 __ bind(&deoptimize);
1062 DeoptimizeIf(al, instr->environment()); 896 DeoptimizeIf(al, instr->environment());
1063 __ bind(&done); 897 __ bind(&done);
1064 } 898 }
1065 899
1066 900
1067 void LCodeGen::DoDivI(LDivI* instr) { 901 void LCodeGen::DoDivI(LDivI* instr) {
1068 class DeferredDivI: public LDeferredCode { 902 class DeferredDivI: public LDeferredCode {
1069 public: 903 public:
1070 DeferredDivI(LCodeGen* codegen, LDivI* instr) 904 DeferredDivI(LCodeGen* codegen, LDivI* instr)
1071 : LDeferredCode(codegen), instr_(instr) { } 905 : LDeferredCode(codegen), instr_(instr) { }
1072 virtual void Generate() { 906 virtual void Generate() {
1073 codegen()->DoDeferredGenericBinaryStub(instr_, Token::DIV); 907 codegen()->DoDeferredBinaryOpStub(instr_, Token::DIV);
1074 } 908 }
1075 private: 909 private:
1076 LDivI* instr_; 910 LDivI* instr_;
1077 }; 911 };
1078 912
1079 const Register left = ToRegister(instr->InputAt(0)); 913 const Register left = ToRegister(instr->InputAt(0));
1080 const Register right = ToRegister(instr->InputAt(1)); 914 const Register right = ToRegister(instr->InputAt(1));
1081 const Register scratch = scratch0(); 915 const Register scratch = scratch0();
1082 const Register result = ToRegister(instr->result()); 916 const Register result = ToRegister(instr->result());
1083 917
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
1116 __ cmp(right, Operand(2)); 950 __ cmp(right, Operand(2));
1117 __ tst(left, Operand(1), eq); 951 __ tst(left, Operand(1), eq);
1118 __ mov(result, Operand(left, ASR, 1), LeaveCC, eq); 952 __ mov(result, Operand(left, ASR, 1), LeaveCC, eq);
1119 __ b(eq, &done); 953 __ b(eq, &done);
1120 954
1121 __ cmp(right, Operand(4)); 955 __ cmp(right, Operand(4));
1122 __ tst(left, Operand(3), eq); 956 __ tst(left, Operand(3), eq);
1123 __ mov(result, Operand(left, ASR, 2), LeaveCC, eq); 957 __ mov(result, Operand(left, ASR, 2), LeaveCC, eq);
1124 __ b(eq, &done); 958 __ b(eq, &done);
1125 959
1126 // Call the generic stub. The numbers in r0 and r1 have 960 // Call the stub. The numbers in r0 and r1 have
1127 // to be tagged to Smis. If that is not possible, deoptimize. 961 // to be tagged to Smis. If that is not possible, deoptimize.
1128 DeferredDivI* deferred = new DeferredDivI(this, instr); 962 DeferredDivI* deferred = new DeferredDivI(this, instr);
1129 963
1130 __ TrySmiTag(left, &deoptimize, scratch); 964 __ TrySmiTag(left, &deoptimize, scratch);
1131 __ TrySmiTag(right, &deoptimize, scratch); 965 __ TrySmiTag(right, &deoptimize, scratch);
1132 966
1133 __ b(al, deferred->entry()); 967 __ b(al, deferred->entry());
1134 __ bind(deferred->exit()); 968 __ bind(deferred->exit());
1135 969
1136 // If the result in r0 is a Smi, untag it, else deoptimize. 970 // If the result in r0 is a Smi, untag it, else deoptimize.
1137 __ JumpIfNotSmi(result, &deoptimize); 971 __ JumpIfNotSmi(result, &deoptimize);
1138 __ SmiUntag(result); 972 __ SmiUntag(result);
1139 __ b(&done); 973 __ b(&done);
1140 974
1141 __ bind(&deoptimize); 975 __ bind(&deoptimize);
1142 DeoptimizeIf(al, instr->environment()); 976 DeoptimizeIf(al, instr->environment());
1143 __ bind(&done); 977 __ bind(&done);
1144 } 978 }
1145 979
1146 980
1147 template<int T> 981 template<int T>
1148 void LCodeGen::DoDeferredGenericBinaryStub(LTemplateInstruction<1, 2, T>* instr, 982 void LCodeGen::DoDeferredBinaryOpStub(LTemplateInstruction<1, 2, T>* instr,
1149 Token::Value op) { 983 Token::Value op) {
1150 Register left = ToRegister(instr->InputAt(0)); 984 Register left = ToRegister(instr->InputAt(0));
1151 Register right = ToRegister(instr->InputAt(1)); 985 Register right = ToRegister(instr->InputAt(1));
1152 986
1153 __ PushSafepointRegistersAndDoubles(); 987 __ PushSafepointRegistersAndDoubles();
1154 GenericBinaryOpStub stub(op, OVERWRITE_LEFT, left, right); 988 // Move left to r1 and right to r0 for the stub call.
989 if (left.is(r1)) {
990 __ Move(r0, right);
991 } else if (left.is(r0) && right.is(r1)) {
992 __ Swap(r0, r1, r2);
993 } else if (left.is(r0)) {
994 ASSERT(!right.is(r1));
995 __ mov(r1, r0);
996 __ mov(r0, right);
997 } else {
998 ASSERT(!left.is(r0) && !right.is(r0));
999 __ mov(r0, right);
1000 __ mov(r1, left);
1001 }
1002 TypeRecordingBinaryOpStub stub(op, OVERWRITE_LEFT);
1155 __ CallStub(&stub); 1003 __ CallStub(&stub);
1156 RecordSafepointWithRegistersAndDoubles(instr->pointer_map(), 1004 RecordSafepointWithRegistersAndDoubles(instr->pointer_map(),
1157 0, 1005 0,
1158 Safepoint::kNoDeoptimizationIndex); 1006 Safepoint::kNoDeoptimizationIndex);
1159 // Overwrite the stored value of r0 with the result of the stub. 1007 // Overwrite the stored value of r0 with the result of the stub.
1160 __ StoreToSafepointRegistersAndDoublesSlot(r0); 1008 __ StoreToSafepointRegistersAndDoublesSlot(r0, r0);
1161 __ PopSafepointRegistersAndDoubles(); 1009 __ PopSafepointRegistersAndDoubles();
1162 } 1010 }
1163 1011
1164 1012
1165 void LCodeGen::DoMulI(LMulI* instr) { 1013 void LCodeGen::DoMulI(LMulI* instr) {
1166 Register scratch = scratch0(); 1014 Register scratch = scratch0();
1167 Register left = ToRegister(instr->InputAt(0)); 1015 Register left = ToRegister(instr->InputAt(0));
1168 Register right = EmitLoadRegister(instr->InputAt(1), scratch); 1016 Register right = EmitLoadRegister(instr->InputAt(1), scratch);
1169 1017
1170 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero) && 1018 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero) &&
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after
1315 } 1163 }
1316 1164
1317 1165
1318 void LCodeGen::DoJSArrayLength(LJSArrayLength* instr) { 1166 void LCodeGen::DoJSArrayLength(LJSArrayLength* instr) {
1319 Register result = ToRegister(instr->result()); 1167 Register result = ToRegister(instr->result());
1320 Register array = ToRegister(instr->InputAt(0)); 1168 Register array = ToRegister(instr->InputAt(0));
1321 __ ldr(result, FieldMemOperand(array, JSArray::kLengthOffset)); 1169 __ ldr(result, FieldMemOperand(array, JSArray::kLengthOffset));
1322 } 1170 }
1323 1171
1324 1172
1325 void LCodeGen::DoPixelArrayLength(LPixelArrayLength* instr) { 1173 void LCodeGen::DoExternalArrayLength(LExternalArrayLength* instr) {
1326 Register result = ToRegister(instr->result()); 1174 Register result = ToRegister(instr->result());
1327 Register array = ToRegister(instr->InputAt(0)); 1175 Register array = ToRegister(instr->InputAt(0));
1328 __ ldr(result, FieldMemOperand(array, PixelArray::kLengthOffset)); 1176 __ ldr(result, FieldMemOperand(array, ExternalArray::kLengthOffset));
1329 } 1177 }
1330 1178
1331 1179
1332 void LCodeGen::DoFixedArrayLength(LFixedArrayLength* instr) { 1180 void LCodeGen::DoFixedArrayLength(LFixedArrayLength* instr) {
1333 Register result = ToRegister(instr->result()); 1181 Register result = ToRegister(instr->result());
1334 Register array = ToRegister(instr->InputAt(0)); 1182 Register array = ToRegister(instr->InputAt(0));
1335 __ ldr(result, FieldMemOperand(array, FixedArray::kLengthOffset)); 1183 __ ldr(result, FieldMemOperand(array, FixedArray::kLengthOffset));
1336 } 1184 }
1337 1185
1338 1186
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
1406 break; 1254 break;
1407 case Token::MOD: { 1255 case Token::MOD: {
1408 // Save r0-r3 on the stack. 1256 // Save r0-r3 on the stack.
1409 __ stm(db_w, sp, r0.bit() | r1.bit() | r2.bit() | r3.bit()); 1257 __ stm(db_w, sp, r0.bit() | r1.bit() | r2.bit() | r3.bit());
1410 1258
1411 __ PrepareCallCFunction(4, scratch0()); 1259 __ PrepareCallCFunction(4, scratch0());
1412 __ vmov(r0, r1, left); 1260 __ vmov(r0, r1, left);
1413 __ vmov(r2, r3, right); 1261 __ vmov(r2, r3, right);
1414 __ CallCFunction(ExternalReference::double_fp_operation(Token::MOD), 4); 1262 __ CallCFunction(ExternalReference::double_fp_operation(Token::MOD), 4);
1415 // Move the result in the double result register. 1263 // Move the result in the double result register.
1416 __ vmov(ToDoubleRegister(instr->result()), r0, r1); 1264 __ GetCFunctionDoubleResult(ToDoubleRegister(instr->result()));
1417 1265
1418 // Restore r0-r3. 1266 // Restore r0-r3.
1419 __ ldm(ia_w, sp, r0.bit() | r1.bit() | r2.bit() | r3.bit()); 1267 __ ldm(ia_w, sp, r0.bit() | r1.bit() | r2.bit() | r3.bit());
1420 break; 1268 break;
1421 } 1269 }
1422 default: 1270 default:
1423 UNREACHABLE(); 1271 UNREACHABLE();
1424 break; 1272 break;
1425 } 1273 }
1426 } 1274 }
1427 1275
1428 1276
1429 void LCodeGen::DoArithmeticT(LArithmeticT* instr) { 1277 void LCodeGen::DoArithmeticT(LArithmeticT* instr) {
1430 ASSERT(ToRegister(instr->InputAt(0)).is(r1)); 1278 ASSERT(ToRegister(instr->InputAt(0)).is(r1));
1431 ASSERT(ToRegister(instr->InputAt(1)).is(r0)); 1279 ASSERT(ToRegister(instr->InputAt(1)).is(r0));
1432 ASSERT(ToRegister(instr->result()).is(r0)); 1280 ASSERT(ToRegister(instr->result()).is(r0));
1433 1281
1434 // TODO(regis): Implement TypeRecordingBinaryOpStub and replace current 1282 TypeRecordingBinaryOpStub stub(instr->op(), NO_OVERWRITE);
1435 // GenericBinaryOpStub:
1436 // TypeRecordingBinaryOpStub stub(instr->op(), NO_OVERWRITE);
1437 GenericBinaryOpStub stub(instr->op(), NO_OVERWRITE, r1, r0);
1438 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); 1283 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
1439 } 1284 }
1440 1285
1441 1286
1442 int LCodeGen::GetNextEmittedBlock(int block) { 1287 int LCodeGen::GetNextEmittedBlock(int block) {
1443 for (int i = block + 1; i < graph()->blocks()->length(); ++i) { 1288 for (int i = block + 1; i < graph()->blocks()->length(); ++i) {
1444 LLabel* label = chunk_->GetLabel(i); 1289 LLabel* label = chunk_->GetLabel(i);
1445 if (!label->HasReplacement()) return i; 1290 if (!label->HasReplacement()) return i;
1446 } 1291 }
1447 return -1; 1292 return -1;
(...skipping 441 matching lines...) Expand 10 before | Expand all | Expand 10 after
1889 Label* false_label = chunk_->GetAssemblyLabel(false_block); 1734 Label* false_label = chunk_->GetAssemblyLabel(false_block);
1890 1735
1891 __ tst(input, Operand(kSmiTagMask)); 1736 __ tst(input, Operand(kSmiTagMask));
1892 __ b(eq, false_label); 1737 __ b(eq, false_label);
1893 1738
1894 __ CompareObjectType(input, scratch, scratch, TestType(instr->hydrogen())); 1739 __ CompareObjectType(input, scratch, scratch, TestType(instr->hydrogen()));
1895 EmitBranch(true_block, false_block, BranchCondition(instr->hydrogen())); 1740 EmitBranch(true_block, false_block, BranchCondition(instr->hydrogen()));
1896 } 1741 }
1897 1742
1898 1743
1744 void LCodeGen::DoGetCachedArrayIndex(LGetCachedArrayIndex* instr) {
1745 Register input = ToRegister(instr->InputAt(0));
1746 Register result = ToRegister(instr->result());
1747
1748 if (FLAG_debug_code) {
1749 __ AbortIfNotString(input);
1750 }
1751
1752 __ ldr(result, FieldMemOperand(input, String::kHashFieldOffset));
1753 __ IndexFromHash(result, result);
1754 }
1755
1756
1899 void LCodeGen::DoHasCachedArrayIndex(LHasCachedArrayIndex* instr) { 1757 void LCodeGen::DoHasCachedArrayIndex(LHasCachedArrayIndex* instr) {
1900 Register input = ToRegister(instr->InputAt(0)); 1758 Register input = ToRegister(instr->InputAt(0));
1901 Register result = ToRegister(instr->result()); 1759 Register result = ToRegister(instr->result());
1902 Register scratch = scratch0(); 1760 Register scratch = scratch0();
1903 1761
1904 ASSERT(instr->hydrogen()->value()->representation().IsTagged()); 1762 ASSERT(instr->hydrogen()->value()->representation().IsTagged());
1905 __ ldr(scratch, 1763 __ ldr(scratch,
1906 FieldMemOperand(input, String::kContainsCachedArrayIndexMask)); 1764 FieldMemOperand(input, String::kHashFieldOffset));
1907 __ tst(scratch, Operand(String::kContainsCachedArrayIndexMask)); 1765 __ tst(scratch, Operand(String::kContainsCachedArrayIndexMask));
1908 __ LoadRoot(result, Heap::kTrueValueRootIndex, ne); 1766 __ LoadRoot(result, Heap::kTrueValueRootIndex, eq);
1909 __ LoadRoot(result, Heap::kFalseValueRootIndex, eq); 1767 __ LoadRoot(result, Heap::kFalseValueRootIndex, ne);
1910 } 1768 }
1911 1769
1912 1770
1913 void LCodeGen::DoHasCachedArrayIndexAndBranch( 1771 void LCodeGen::DoHasCachedArrayIndexAndBranch(
1914 LHasCachedArrayIndexAndBranch* instr) { 1772 LHasCachedArrayIndexAndBranch* instr) {
1915 Register input = ToRegister(instr->InputAt(0)); 1773 Register input = ToRegister(instr->InputAt(0));
1916 Register scratch = scratch0(); 1774 Register scratch = scratch0();
1917 1775
1918 int true_block = chunk_->LookupDestination(instr->true_block_id()); 1776 int true_block = chunk_->LookupDestination(instr->true_block_id());
1919 int false_block = chunk_->LookupDestination(instr->false_block_id()); 1777 int false_block = chunk_->LookupDestination(instr->false_block_id());
1920 1778
1921 __ ldr(scratch, 1779 __ ldr(scratch,
1922 FieldMemOperand(input, String::kContainsCachedArrayIndexMask)); 1780 FieldMemOperand(input, String::kHashFieldOffset));
1923 __ tst(scratch, Operand(String::kContainsCachedArrayIndexMask)); 1781 __ tst(scratch, Operand(String::kContainsCachedArrayIndexMask));
1924 EmitBranch(true_block, false_block, ne); 1782 EmitBranch(true_block, false_block, eq);
1925 } 1783 }
1926 1784
1927 1785
1928 // Branches to a label or falls through with the answer in flags. Trashes 1786 // Branches to a label or falls through with the answer in flags. Trashes
1929 // the temp registers, but not the input. Only input and temp2 may alias. 1787 // the temp registers, but not the input. Only input and temp2 may alias.
1930 void LCodeGen::EmitClassOfTest(Label* is_true, 1788 void LCodeGen::EmitClassOfTest(Label* is_true,
1931 Label* is_false, 1789 Label* is_false,
1932 Handle<String>class_name, 1790 Handle<String>class_name,
1933 Register input, 1791 Register input,
1934 Register temp, 1792 Register temp,
(...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after
2157 // offset to the location of the map check. 2015 // offset to the location of the map check.
2158 Register temp = ToRegister(instr->TempAt(0)); 2016 Register temp = ToRegister(instr->TempAt(0));
2159 ASSERT(temp.is(r4)); 2017 ASSERT(temp.is(r4));
2160 __ mov(InstanceofStub::right(), Operand(instr->function())); 2018 __ mov(InstanceofStub::right(), Operand(instr->function()));
2161 static const int kAdditionalDelta = 4; 2019 static const int kAdditionalDelta = 4;
2162 int delta = masm_->InstructionsGeneratedSince(map_check) + kAdditionalDelta; 2020 int delta = masm_->InstructionsGeneratedSince(map_check) + kAdditionalDelta;
2163 Label before_push_delta; 2021 Label before_push_delta;
2164 __ bind(&before_push_delta); 2022 __ bind(&before_push_delta);
2165 __ BlockConstPoolFor(kAdditionalDelta); 2023 __ BlockConstPoolFor(kAdditionalDelta);
2166 __ mov(temp, Operand(delta * kPointerSize)); 2024 __ mov(temp, Operand(delta * kPointerSize));
2167 __ StoreToSafepointRegisterSlot(temp); 2025 __ StoreToSafepointRegisterSlot(temp, temp);
2168 __ Call(stub.GetCode(), RelocInfo::CODE_TARGET); 2026 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
2169 ASSERT_EQ(kAdditionalDelta,
2170 masm_->InstructionsGeneratedSince(&before_push_delta));
2171 RecordSafepointWithRegisters(
2172 instr->pointer_map(), 0, Safepoint::kNoDeoptimizationIndex);
2173 // Put the result value into the result register slot and 2027 // Put the result value into the result register slot and
2174 // restore all registers. 2028 // restore all registers.
2175 __ StoreToSafepointRegisterSlot(result); 2029 __ StoreToSafepointRegisterSlot(result, result);
2176 2030
2177 __ PopSafepointRegisters(); 2031 __ PopSafepointRegisters();
2178 } 2032 }
2179 2033
2180 2034
2181 static Condition ComputeCompareCondition(Token::Value op) { 2035 static Condition ComputeCompareCondition(Token::Value op) {
2182 switch (op) { 2036 switch (op) {
2183 case Token::EQ_STRICT: 2037 case Token::EQ_STRICT:
2184 case Token::EQ: 2038 case Token::EQ:
2185 return eq; 2039 return eq;
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
2285 } 2139 }
2286 2140
2287 // Store the value. 2141 // Store the value.
2288 __ str(value, FieldMemOperand(scratch, JSGlobalPropertyCell::kValueOffset)); 2142 __ str(value, FieldMemOperand(scratch, JSGlobalPropertyCell::kValueOffset));
2289 } 2143 }
2290 2144
2291 2145
2292 void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) { 2146 void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) {
2293 Register context = ToRegister(instr->context()); 2147 Register context = ToRegister(instr->context());
2294 Register result = ToRegister(instr->result()); 2148 Register result = ToRegister(instr->result());
2295 __ ldr(result, 2149 __ ldr(result, ContextOperand(context, instr->slot_index()));
2296 MemOperand(context, Context::SlotOffset(Context::FCONTEXT_INDEX)));
2297 __ ldr(result, ContextOperand(result, instr->slot_index()));
2298 } 2150 }
2299 2151
2300 2152
2301 void LCodeGen::DoStoreContextSlot(LStoreContextSlot* instr) { 2153 void LCodeGen::DoStoreContextSlot(LStoreContextSlot* instr) {
2302 Register context = ToRegister(instr->context()); 2154 Register context = ToRegister(instr->context());
2303 Register value = ToRegister(instr->value()); 2155 Register value = ToRegister(instr->value());
2304 __ ldr(context,
2305 MemOperand(context, Context::SlotOffset(Context::FCONTEXT_INDEX)));
2306 __ str(value, ContextOperand(context, instr->slot_index())); 2156 __ str(value, ContextOperand(context, instr->slot_index()));
2307 if (instr->needs_write_barrier()) { 2157 if (instr->needs_write_barrier()) {
2308 int offset = Context::SlotOffset(instr->slot_index()); 2158 int offset = Context::SlotOffset(instr->slot_index());
2309 __ RecordWrite(context, Operand(offset), value, scratch0()); 2159 __ RecordWrite(context, Operand(offset), value, scratch0());
2310 } 2160 }
2311 } 2161 }
2312 2162
2313 2163
2314 void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) { 2164 void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) {
2315 Register object = ToRegister(instr->InputAt(0)); 2165 Register object = ToRegister(instr->InputAt(0));
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
2383 Register input = ToRegister(instr->InputAt(0)); 2233 Register input = ToRegister(instr->InputAt(0));
2384 Register scratch = scratch0(); 2234 Register scratch = scratch0();
2385 2235
2386 __ ldr(result, FieldMemOperand(input, JSObject::kElementsOffset)); 2236 __ ldr(result, FieldMemOperand(input, JSObject::kElementsOffset));
2387 if (FLAG_debug_code) { 2237 if (FLAG_debug_code) {
2388 Label done; 2238 Label done;
2389 __ ldr(scratch, FieldMemOperand(result, HeapObject::kMapOffset)); 2239 __ ldr(scratch, FieldMemOperand(result, HeapObject::kMapOffset));
2390 __ LoadRoot(ip, Heap::kFixedArrayMapRootIndex); 2240 __ LoadRoot(ip, Heap::kFixedArrayMapRootIndex);
2391 __ cmp(scratch, ip); 2241 __ cmp(scratch, ip);
2392 __ b(eq, &done); 2242 __ b(eq, &done);
2393 __ LoadRoot(ip, Heap::kPixelArrayMapRootIndex); 2243 __ LoadRoot(ip, Heap::kExternalPixelArrayMapRootIndex);
2394 __ cmp(scratch, ip); 2244 __ cmp(scratch, ip);
2395 __ b(eq, &done); 2245 __ b(eq, &done);
2396 __ LoadRoot(ip, Heap::kFixedCOWArrayMapRootIndex); 2246 __ LoadRoot(ip, Heap::kFixedCOWArrayMapRootIndex);
2397 __ cmp(scratch, ip); 2247 __ cmp(scratch, ip);
2398 __ Check(eq, "Check for fast elements failed."); 2248 __ Check(eq, "Check for fast elements failed.");
2399 __ bind(&done); 2249 __ bind(&done);
2400 } 2250 }
2401 } 2251 }
2402 2252
2403 2253
2404 void LCodeGen::DoLoadPixelArrayExternalPointer( 2254 void LCodeGen::DoLoadExternalArrayPointer(
2405 LLoadPixelArrayExternalPointer* instr) { 2255 LLoadExternalArrayPointer* instr) {
2406 Register to_reg = ToRegister(instr->result()); 2256 Register to_reg = ToRegister(instr->result());
2407 Register from_reg = ToRegister(instr->InputAt(0)); 2257 Register from_reg = ToRegister(instr->InputAt(0));
2408 __ ldr(to_reg, FieldMemOperand(from_reg, PixelArray::kExternalPointerOffset)); 2258 __ ldr(to_reg, FieldMemOperand(from_reg,
2259 ExternalArray::kExternalPointerOffset));
2409 } 2260 }
2410 2261
2411 2262
2412 void LCodeGen::DoAccessArgumentsAt(LAccessArgumentsAt* instr) { 2263 void LCodeGen::DoAccessArgumentsAt(LAccessArgumentsAt* instr) {
2413 Register arguments = ToRegister(instr->arguments()); 2264 Register arguments = ToRegister(instr->arguments());
2414 Register length = ToRegister(instr->length()); 2265 Register length = ToRegister(instr->length());
2415 Register index = ToRegister(instr->index()); 2266 Register index = ToRegister(instr->index());
2416 Register result = ToRegister(instr->result()); 2267 Register result = ToRegister(instr->result());
2417 2268
2418 // Bailout index is not a valid argument index. Use unsigned check to get 2269 // Bailout index is not a valid argument index. Use unsigned check to get
(...skipping 20 matching lines...) Expand all
2439 __ ldr(result, FieldMemOperand(scratch, FixedArray::kHeaderSize)); 2290 __ ldr(result, FieldMemOperand(scratch, FixedArray::kHeaderSize));
2440 2291
2441 // Check for the hole value. 2292 // Check for the hole value.
2442 __ LoadRoot(scratch, Heap::kTheHoleValueRootIndex); 2293 __ LoadRoot(scratch, Heap::kTheHoleValueRootIndex);
2443 __ cmp(result, scratch); 2294 __ cmp(result, scratch);
2444 DeoptimizeIf(eq, instr->environment()); 2295 DeoptimizeIf(eq, instr->environment());
2445 } 2296 }
2446 2297
2447 2298
2448 void LCodeGen::DoLoadPixelArrayElement(LLoadPixelArrayElement* instr) { 2299 void LCodeGen::DoLoadPixelArrayElement(LLoadPixelArrayElement* instr) {
2449 Register external_elements = ToRegister(instr->external_pointer()); 2300 Register external_pointer = ToRegister(instr->external_pointer());
2450 Register key = ToRegister(instr->key()); 2301 Register key = ToRegister(instr->key());
2451 Register result = ToRegister(instr->result()); 2302 Register result = ToRegister(instr->result());
2452 2303
2453 // Load the result. 2304 // Load the result.
2454 __ ldrb(result, MemOperand(external_elements, key)); 2305 __ ldrb(result, MemOperand(external_pointer, key));
2455 } 2306 }
2456 2307
2457 2308
2458 void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) { 2309 void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) {
2459 ASSERT(ToRegister(instr->object()).is(r1)); 2310 ASSERT(ToRegister(instr->object()).is(r1));
2460 ASSERT(ToRegister(instr->key()).is(r0)); 2311 ASSERT(ToRegister(instr->key()).is(r0));
2461 2312
2462 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); 2313 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
2463 CallCode(ic, RelocInfo::CODE_TARGET, instr); 2314 CallCode(ic, RelocInfo::CODE_TARGET, instr);
2464 } 2315 }
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after
2614 Register result = ToRegister(instr->result()); 2465 Register result = ToRegister(instr->result());
2615 __ ldr(result, FieldMemOperand(global, GlobalObject::kGlobalReceiverOffset)); 2466 __ ldr(result, FieldMemOperand(global, GlobalObject::kGlobalReceiverOffset));
2616 } 2467 }
2617 2468
2618 2469
2619 void LCodeGen::CallKnownFunction(Handle<JSFunction> function, 2470 void LCodeGen::CallKnownFunction(Handle<JSFunction> function,
2620 int arity, 2471 int arity,
2621 LInstruction* instr) { 2472 LInstruction* instr) {
2622 // Change context if needed. 2473 // Change context if needed.
2623 bool change_context = 2474 bool change_context =
2624 (graph()->info()->closure()->context() != function->context()) || 2475 (info()->closure()->context() != function->context()) ||
2625 scope()->contains_with() || 2476 scope()->contains_with() ||
2626 (scope()->num_heap_slots() > 0); 2477 (scope()->num_heap_slots() > 0);
2627 if (change_context) { 2478 if (change_context) {
2628 __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset)); 2479 __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset));
2629 } 2480 }
2630 2481
2631 // Set r0 to arguments count if adaption is not needed. Assumes that r0 2482 // Set r0 to arguments count if adaption is not needed. Assumes that r0
2632 // is available to write to at this point. 2483 // is available to write to at this point.
2633 if (!function->NeedsArgumentsAdaption()) { 2484 if (!function->NeedsArgumentsAdaption()) {
2634 __ mov(r0, Operand(arity)); 2485 __ mov(r0, Operand(arity));
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
2698 2549
2699 // Slow case: Call the runtime system to do the number allocation. 2550 // Slow case: Call the runtime system to do the number allocation.
2700 __ bind(&slow); 2551 __ bind(&slow);
2701 2552
2702 __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber); 2553 __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber);
2703 RecordSafepointWithRegisters( 2554 RecordSafepointWithRegisters(
2704 instr->pointer_map(), 0, Safepoint::kNoDeoptimizationIndex); 2555 instr->pointer_map(), 0, Safepoint::kNoDeoptimizationIndex);
2705 // Set the pointer to the new heap number in tmp. 2556 // Set the pointer to the new heap number in tmp.
2706 if (!tmp1.is(r0)) __ mov(tmp1, Operand(r0)); 2557 if (!tmp1.is(r0)) __ mov(tmp1, Operand(r0));
2707 // Restore input_reg after call to runtime. 2558 // Restore input_reg after call to runtime.
2708 __ LoadFromSafepointRegisterSlot(input); 2559 __ LoadFromSafepointRegisterSlot(input, input);
2709 __ ldr(exponent, FieldMemOperand(input, HeapNumber::kExponentOffset)); 2560 __ ldr(exponent, FieldMemOperand(input, HeapNumber::kExponentOffset));
2710 2561
2711 __ bind(&allocated); 2562 __ bind(&allocated);
2712 // exponent: floating point exponent value. 2563 // exponent: floating point exponent value.
2713 // tmp1: allocated heap number. 2564 // tmp1: allocated heap number.
2714 __ bic(exponent, exponent, Operand(HeapNumber::kSignMask)); 2565 __ bic(exponent, exponent, Operand(HeapNumber::kSignMask));
2715 __ str(exponent, FieldMemOperand(tmp1, HeapNumber::kExponentOffset)); 2566 __ str(exponent, FieldMemOperand(tmp1, HeapNumber::kExponentOffset));
2716 __ ldr(tmp2, FieldMemOperand(input, HeapNumber::kMantissaOffset)); 2567 __ ldr(tmp2, FieldMemOperand(input, HeapNumber::kMantissaOffset));
2717 __ str(tmp2, FieldMemOperand(tmp1, HeapNumber::kMantissaOffset)); 2568 __ str(tmp2, FieldMemOperand(tmp1, HeapNumber::kMantissaOffset));
2718 2569
2719 __ str(tmp1, masm()->SafepointRegisterSlot(input)); 2570 __ StoreToSafepointRegisterSlot(tmp1, input);
2720 __ PopSafepointRegisters(); 2571 __ PopSafepointRegisters();
2721 2572
2722 __ bind(&done); 2573 __ bind(&done);
2723 } 2574 }
2724 2575
2725 2576
2726 void LCodeGen::EmitIntegerMathAbs(LUnaryMathOperation* instr) { 2577 void LCodeGen::EmitIntegerMathAbs(LUnaryMathOperation* instr) {
2727 Register input = ToRegister(instr->InputAt(0)); 2578 Register input = ToRegister(instr->InputAt(0));
2728 __ cmp(input, Operand(0)); 2579 __ cmp(input, Operand(0));
2729 // We can make rsb conditional because the previous cmp instruction 2580 // We can make rsb conditional because the previous cmp instruction
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
2763 Register input = ToRegister(instr->InputAt(0)); 2614 Register input = ToRegister(instr->InputAt(0));
2764 // Smi check. 2615 // Smi check.
2765 __ JumpIfNotSmi(input, deferred->entry()); 2616 __ JumpIfNotSmi(input, deferred->entry());
2766 // If smi, handle it directly. 2617 // If smi, handle it directly.
2767 EmitIntegerMathAbs(instr); 2618 EmitIntegerMathAbs(instr);
2768 __ bind(deferred->exit()); 2619 __ bind(deferred->exit());
2769 } 2620 }
2770 } 2621 }
2771 2622
2772 2623
2773 // Truncates a double using a specific rounding mode.
2774 // Clears the z flag (ne condition) if an overflow occurs.
2775 void LCodeGen::EmitVFPTruncate(VFPRoundingMode rounding_mode,
2776 SwVfpRegister result,
2777 DwVfpRegister double_input,
2778 Register scratch1,
2779 Register scratch2) {
2780 Register prev_fpscr = scratch1;
2781 Register scratch = scratch2;
2782
2783 // Set custom FPCSR:
2784 // - Set rounding mode.
2785 // - Clear vfp cumulative exception flags.
2786 // - Make sure Flush-to-zero mode control bit is unset.
2787 __ vmrs(prev_fpscr);
2788 __ bic(scratch, prev_fpscr, Operand(kVFPExceptionMask |
2789 kVFPRoundingModeMask |
2790 kVFPFlushToZeroMask));
2791 __ orr(scratch, scratch, Operand(rounding_mode));
2792 __ vmsr(scratch);
2793
2794 // Convert the argument to an integer.
2795 __ vcvt_s32_f64(result,
2796 double_input,
2797 kFPSCRRounding);
2798
2799 // Retrieve FPSCR.
2800 __ vmrs(scratch);
2801 // Restore FPSCR.
2802 __ vmsr(prev_fpscr);
2803 // Check for vfp exceptions.
2804 __ tst(scratch, Operand(kVFPExceptionMask));
2805 }
2806
2807
2808 void LCodeGen::DoMathFloor(LUnaryMathOperation* instr) { 2624 void LCodeGen::DoMathFloor(LUnaryMathOperation* instr) {
2809 DoubleRegister input = ToDoubleRegister(instr->InputAt(0)); 2625 DoubleRegister input = ToDoubleRegister(instr->InputAt(0));
2810 Register result = ToRegister(instr->result()); 2626 Register result = ToRegister(instr->result());
2811 SwVfpRegister single_scratch = double_scratch0().low(); 2627 SwVfpRegister single_scratch = double_scratch0().low();
2812 Register scratch1 = scratch0(); 2628 Register scratch1 = scratch0();
2813 Register scratch2 = ToRegister(instr->TempAt(0)); 2629 Register scratch2 = ToRegister(instr->TempAt(0));
2814 2630
2815 EmitVFPTruncate(kRoundToMinusInf, 2631 __ EmitVFPTruncate(kRoundToMinusInf,
2816 single_scratch, 2632 single_scratch,
2817 input, 2633 input,
2818 scratch1, 2634 scratch1,
2819 scratch2); 2635 scratch2);
2820 DeoptimizeIf(ne, instr->environment()); 2636 DeoptimizeIf(ne, instr->environment());
2821 2637
2822 // Move the result back to general purpose register r0. 2638 // Move the result back to general purpose register r0.
2823 __ vmov(result, single_scratch); 2639 __ vmov(result, single_scratch);
2824 2640
2825 // Test for -0. 2641 // Test for -0.
2826 Label done; 2642 Label done;
2827 __ cmp(result, Operand(0)); 2643 __ cmp(result, Operand(0));
2828 __ b(ne, &done); 2644 __ b(ne, &done);
2829 __ vmov(scratch1, input.high()); 2645 __ vmov(scratch1, input.high());
2830 __ tst(scratch1, Operand(HeapNumber::kSignMask)); 2646 __ tst(scratch1, Operand(HeapNumber::kSignMask));
2831 DeoptimizeIf(ne, instr->environment()); 2647 DeoptimizeIf(ne, instr->environment());
2832 __ bind(&done); 2648 __ bind(&done);
2833 } 2649 }
2834 2650
2835 2651
2652 void LCodeGen::DoMathRound(LUnaryMathOperation* instr) {
2653 DoubleRegister input = ToDoubleRegister(instr->InputAt(0));
2654 Register result = ToRegister(instr->result());
2655 Register scratch1 = scratch0();
2656 Register scratch2 = result;
2657 __ EmitVFPTruncate(kRoundToNearest,
2658 double_scratch0().low(),
2659 input,
2660 scratch1,
2661 scratch2);
2662 DeoptimizeIf(ne, instr->environment());
2663 __ vmov(result, double_scratch0().low());
2664
2665 // Test for -0.
2666 Label done;
2667 __ cmp(result, Operand(0));
2668 __ b(ne, &done);
2669 __ vmov(scratch1, input.high());
2670 __ tst(scratch1, Operand(HeapNumber::kSignMask));
2671 DeoptimizeIf(ne, instr->environment());
2672 __ bind(&done);
2673 }
2674
2675
2836 void LCodeGen::DoMathSqrt(LUnaryMathOperation* instr) { 2676 void LCodeGen::DoMathSqrt(LUnaryMathOperation* instr) {
2837 DoubleRegister input = ToDoubleRegister(instr->InputAt(0)); 2677 DoubleRegister input = ToDoubleRegister(instr->InputAt(0));
2838 ASSERT(ToDoubleRegister(instr->result()).is(input)); 2678 ASSERT(ToDoubleRegister(instr->result()).is(input));
2839 __ vsqrt(input, input); 2679 __ vsqrt(input, input);
2840 } 2680 }
2841 2681
2842 2682
2683 void LCodeGen::DoMathPowHalf(LUnaryMathOperation* instr) {
2684 DoubleRegister input = ToDoubleRegister(instr->InputAt(0));
2685 Register scratch = scratch0();
2686 SwVfpRegister single_scratch = double_scratch0().low();
2687 DoubleRegister double_scratch = double_scratch0();
2688 ASSERT(ToDoubleRegister(instr->result()).is(input));
2689
2690 // Add +0 to convert -0 to +0.
2691 __ mov(scratch, Operand(0));
2692 __ vmov(single_scratch, scratch);
2693 __ vcvt_f64_s32(double_scratch, single_scratch);
2694 __ vadd(input, input, double_scratch);
2695 __ vsqrt(input, input);
2696 }
2697
2698
2699 void LCodeGen::DoPower(LPower* instr) {
2700 LOperand* left = instr->InputAt(0);
2701 LOperand* right = instr->InputAt(1);
2702 Register scratch = scratch0();
2703 DoubleRegister result_reg = ToDoubleRegister(instr->result());
2704 Representation exponent_type = instr->hydrogen()->right()->representation();
2705 if (exponent_type.IsDouble()) {
2706 // Prepare arguments and call C function.
2707 __ PrepareCallCFunction(4, scratch);
2708 __ vmov(r0, r1, ToDoubleRegister(left));
2709 __ vmov(r2, r3, ToDoubleRegister(right));
2710 __ CallCFunction(ExternalReference::power_double_double_function(), 4);
2711 } else if (exponent_type.IsInteger32()) {
2712 ASSERT(ToRegister(right).is(r0));
2713 // Prepare arguments and call C function.
2714 __ PrepareCallCFunction(4, scratch);
2715 __ mov(r2, ToRegister(right));
2716 __ vmov(r0, r1, ToDoubleRegister(left));
2717 __ CallCFunction(ExternalReference::power_double_int_function(), 4);
2718 } else {
2719 ASSERT(exponent_type.IsTagged());
2720 ASSERT(instr->hydrogen()->left()->representation().IsDouble());
2721
2722 Register right_reg = ToRegister(right);
2723
2724 // Check for smi on the right hand side.
2725 Label non_smi, call;
2726 __ JumpIfNotSmi(right_reg, &non_smi);
2727
2728 // Untag smi and convert it to a double.
2729 __ SmiUntag(right_reg);
2730 SwVfpRegister single_scratch = double_scratch0().low();
2731 __ vmov(single_scratch, right_reg);
2732 __ vcvt_f64_s32(result_reg, single_scratch);
2733 __ jmp(&call);
2734
2735 // Heap number map check.
2736 __ bind(&non_smi);
2737 __ ldr(scratch, FieldMemOperand(right_reg, HeapObject::kMapOffset));
2738 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex);
2739 __ cmp(scratch, Operand(ip));
2740 DeoptimizeIf(ne, instr->environment());
2741 int32_t value_offset = HeapNumber::kValueOffset - kHeapObjectTag;
2742 __ add(scratch, right_reg, Operand(value_offset));
2743 __ vldr(result_reg, scratch, 0);
2744
2745 // Prepare arguments and call C function.
2746 __ bind(&call);
2747 __ PrepareCallCFunction(4, scratch);
2748 __ vmov(r0, r1, ToDoubleRegister(left));
2749 __ vmov(r2, r3, result_reg);
2750 __ CallCFunction(ExternalReference::power_double_double_function(), 4);
2751 }
2752 // Store the result in the result register.
2753 __ GetCFunctionDoubleResult(result_reg);
2754 }
2755
2756
2757 void LCodeGen::DoMathLog(LUnaryMathOperation* instr) {
2758 ASSERT(ToDoubleRegister(instr->result()).is(d2));
2759 TranscendentalCacheStub stub(TranscendentalCache::LOG,
2760 TranscendentalCacheStub::UNTAGGED);
2761 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
2762 }
2763
2764
2765 void LCodeGen::DoMathCos(LUnaryMathOperation* instr) {
2766 ASSERT(ToDoubleRegister(instr->result()).is(d2));
2767 TranscendentalCacheStub stub(TranscendentalCache::COS,
2768 TranscendentalCacheStub::UNTAGGED);
2769 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
2770 }
2771
2772
2773 void LCodeGen::DoMathSin(LUnaryMathOperation* instr) {
2774 ASSERT(ToDoubleRegister(instr->result()).is(d2));
2775 TranscendentalCacheStub stub(TranscendentalCache::SIN,
2776 TranscendentalCacheStub::UNTAGGED);
2777 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
2778 }
2779
2780
2843 void LCodeGen::DoUnaryMathOperation(LUnaryMathOperation* instr) { 2781 void LCodeGen::DoUnaryMathOperation(LUnaryMathOperation* instr) {
2844 switch (instr->op()) { 2782 switch (instr->op()) {
2845 case kMathAbs: 2783 case kMathAbs:
2846 DoMathAbs(instr); 2784 DoMathAbs(instr);
2847 break; 2785 break;
2848 case kMathFloor: 2786 case kMathFloor:
2849 DoMathFloor(instr); 2787 DoMathFloor(instr);
2850 break; 2788 break;
2789 case kMathRound:
2790 DoMathRound(instr);
2791 break;
2851 case kMathSqrt: 2792 case kMathSqrt:
2852 DoMathSqrt(instr); 2793 DoMathSqrt(instr);
2853 break; 2794 break;
2795 case kMathPowHalf:
2796 DoMathPowHalf(instr);
2797 break;
2798 case kMathCos:
2799 DoMathCos(instr);
2800 break;
2801 case kMathSin:
2802 DoMathSin(instr);
2803 break;
2804 case kMathLog:
2805 DoMathLog(instr);
2806 break;
2854 default: 2807 default:
2855 Abort("Unimplemented type of LUnaryMathOperation."); 2808 Abort("Unimplemented type of LUnaryMathOperation.");
2856 UNREACHABLE(); 2809 UNREACHABLE();
2857 } 2810 }
2858 } 2811 }
2859 2812
2860 2813
2861 void LCodeGen::DoCallKeyed(LCallKeyed* instr) { 2814 void LCodeGen::DoCallKeyed(LCallKeyed* instr) {
2862 ASSERT(ToRegister(instr->result()).is(r0)); 2815 ASSERT(ToRegister(instr->result()).is(r0));
2863 2816
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
2955 } 2908 }
2956 } 2909 }
2957 2910
2958 2911
2959 void LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) { 2912 void LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) {
2960 ASSERT(ToRegister(instr->object()).is(r1)); 2913 ASSERT(ToRegister(instr->object()).is(r1));
2961 ASSERT(ToRegister(instr->value()).is(r0)); 2914 ASSERT(ToRegister(instr->value()).is(r0));
2962 2915
2963 // Name is always in r2. 2916 // Name is always in r2.
2964 __ mov(r2, Operand(instr->name())); 2917 __ mov(r2, Operand(instr->name()));
2965 Handle<Code> ic(Builtins::builtin(info_->is_strict() 2918 Handle<Code> ic(Builtins::builtin(
2966 ? Builtins::StoreIC_Initialize_Strict 2919 info_->is_strict() ? Builtins::StoreIC_Initialize_Strict
2967 : Builtins::StoreIC_Initialize)); 2920 : Builtins::StoreIC_Initialize));
2968 CallCode(ic, RelocInfo::CODE_TARGET, instr); 2921 CallCode(ic, RelocInfo::CODE_TARGET, instr);
2969 } 2922 }
2970 2923
2971 2924
2972 void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) { 2925 void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) {
2973 __ cmp(ToRegister(instr->index()), ToRegister(instr->length())); 2926 __ cmp(ToRegister(instr->index()), ToRegister(instr->length()));
2974 DeoptimizeIf(hs, instr->environment()); 2927 DeoptimizeIf(hs, instr->environment());
2975 } 2928 }
2976 2929
2977 2930
(...skipping 16 matching lines...) Expand all
2994 } 2947 }
2995 2948
2996 if (instr->hydrogen()->NeedsWriteBarrier()) { 2949 if (instr->hydrogen()->NeedsWriteBarrier()) {
2997 // Compute address of modified element and store it into key register. 2950 // Compute address of modified element and store it into key register.
2998 __ add(key, scratch, Operand(FixedArray::kHeaderSize)); 2951 __ add(key, scratch, Operand(FixedArray::kHeaderSize));
2999 __ RecordWrite(elements, key, value); 2952 __ RecordWrite(elements, key, value);
3000 } 2953 }
3001 } 2954 }
3002 2955
3003 2956
2957 void LCodeGen::DoStorePixelArrayElement(LStorePixelArrayElement* instr) {
2958 Register external_pointer = ToRegister(instr->external_pointer());
2959 Register key = ToRegister(instr->key());
2960 Register value = ToRegister(instr->value());
2961
2962 // Clamp the value to [0..255].
2963 __ Usat(value, 8, Operand(value));
2964 __ strb(value, MemOperand(external_pointer, key, LSL, 0));
2965 }
2966
2967
3004 void LCodeGen::DoStoreKeyedGeneric(LStoreKeyedGeneric* instr) { 2968 void LCodeGen::DoStoreKeyedGeneric(LStoreKeyedGeneric* instr) {
3005 ASSERT(ToRegister(instr->object()).is(r2)); 2969 ASSERT(ToRegister(instr->object()).is(r2));
3006 ASSERT(ToRegister(instr->key()).is(r1)); 2970 ASSERT(ToRegister(instr->key()).is(r1));
3007 ASSERT(ToRegister(instr->value()).is(r0)); 2971 ASSERT(ToRegister(instr->value()).is(r0));
3008 2972
3009 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); 2973 Handle<Code> ic(Builtins::builtin(
2974 info_->is_strict() ? Builtins::KeyedStoreIC_Initialize_Strict
2975 : Builtins::KeyedStoreIC_Initialize));
3010 CallCode(ic, RelocInfo::CODE_TARGET, instr); 2976 CallCode(ic, RelocInfo::CODE_TARGET, instr);
3011 } 2977 }
3012 2978
3013 2979
3014 void LCodeGen::DoStringCharCodeAt(LStringCharCodeAt* instr) { 2980 void LCodeGen::DoStringCharCodeAt(LStringCharCodeAt* instr) {
3015 class DeferredStringCharCodeAt: public LDeferredCode { 2981 class DeferredStringCharCodeAt: public LDeferredCode {
3016 public: 2982 public:
3017 DeferredStringCharCodeAt(LCodeGen* codegen, LStringCharCodeAt* instr) 2983 DeferredStringCharCodeAt(LCodeGen* codegen, LStringCharCodeAt* instr)
3018 : LDeferredCode(codegen), instr_(instr) { } 2984 : LDeferredCode(codegen), instr_(instr) { }
3019 virtual void Generate() { codegen()->DoDeferredStringCharCodeAt(instr_); } 2985 virtual void Generate() { codegen()->DoDeferredStringCharCodeAt(instr_); }
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after
3140 __ SmiTag(index); 3106 __ SmiTag(index);
3141 __ push(index); 3107 __ push(index);
3142 } 3108 }
3143 __ CallRuntimeSaveDoubles(Runtime::kStringCharCodeAt); 3109 __ CallRuntimeSaveDoubles(Runtime::kStringCharCodeAt);
3144 RecordSafepointWithRegisters( 3110 RecordSafepointWithRegisters(
3145 instr->pointer_map(), 2, Safepoint::kNoDeoptimizationIndex); 3111 instr->pointer_map(), 2, Safepoint::kNoDeoptimizationIndex);
3146 if (FLAG_debug_code) { 3112 if (FLAG_debug_code) {
3147 __ AbortIfNotSmi(r0); 3113 __ AbortIfNotSmi(r0);
3148 } 3114 }
3149 __ SmiUntag(r0); 3115 __ SmiUntag(r0);
3150 MemOperand result_stack_slot = masm()->SafepointRegisterSlot(result); 3116 __ StoreToSafepointRegisterSlot(r0, result);
3151 __ str(r0, result_stack_slot); 3117 __ PopSafepointRegisters();
3118 }
3119
3120
3121 void LCodeGen::DoStringCharFromCode(LStringCharFromCode* instr) {
3122 class DeferredStringCharFromCode: public LDeferredCode {
3123 public:
3124 DeferredStringCharFromCode(LCodeGen* codegen, LStringCharFromCode* instr)
3125 : LDeferredCode(codegen), instr_(instr) { }
3126 virtual void Generate() { codegen()->DoDeferredStringCharFromCode(instr_); }
3127 private:
3128 LStringCharFromCode* instr_;
3129 };
3130
3131 DeferredStringCharFromCode* deferred =
3132 new DeferredStringCharFromCode(this, instr);
3133
3134 ASSERT(instr->hydrogen()->value()->representation().IsInteger32());
3135 Register char_code = ToRegister(instr->char_code());
3136 Register result = ToRegister(instr->result());
3137 ASSERT(!char_code.is(result));
3138
3139 __ cmp(char_code, Operand(String::kMaxAsciiCharCode));
3140 __ b(hi, deferred->entry());
3141 __ LoadRoot(result, Heap::kSingleCharacterStringCacheRootIndex);
3142 __ add(result, result, Operand(char_code, LSL, kPointerSizeLog2));
3143 __ ldr(result, FieldMemOperand(result, FixedArray::kHeaderSize));
3144 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
3145 __ cmp(result, ip);
3146 __ b(eq, deferred->entry());
3147 __ bind(deferred->exit());
3148 }
3149
3150
3151 void LCodeGen::DoDeferredStringCharFromCode(LStringCharFromCode* instr) {
3152 Register char_code = ToRegister(instr->char_code());
3153 Register result = ToRegister(instr->result());
3154
3155 // TODO(3095996): Get rid of this. For now, we need to make the
3156 // result register contain a valid pointer because it is already
3157 // contained in the register pointer map.
3158 __ mov(result, Operand(0));
3159
3160 __ PushSafepointRegisters();
3161 __ SmiTag(char_code);
3162 __ push(char_code);
3163 __ CallRuntimeSaveDoubles(Runtime::kCharFromCode);
3164 RecordSafepointWithRegisters(
3165 instr->pointer_map(), 1, Safepoint::kNoDeoptimizationIndex);
3166 __ StoreToSafepointRegisterSlot(r0, result);
3152 __ PopSafepointRegisters(); 3167 __ PopSafepointRegisters();
3153 } 3168 }
3154 3169
3155 3170
3156 void LCodeGen::DoStringLength(LStringLength* instr) { 3171 void LCodeGen::DoStringLength(LStringLength* instr) {
3157 Register string = ToRegister(instr->InputAt(0)); 3172 Register string = ToRegister(instr->InputAt(0));
3158 Register result = ToRegister(instr->result()); 3173 Register result = ToRegister(instr->result());
3159 __ ldr(result, FieldMemOperand(string, String::kLengthOffset)); 3174 __ ldr(result, FieldMemOperand(string, String::kLengthOffset));
3160 } 3175 }
3161 3176
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
3222 __ b(&done); 3237 __ b(&done);
3223 } 3238 }
3224 3239
3225 // Slow case: Call the runtime system to do the number allocation. 3240 // Slow case: Call the runtime system to do the number allocation.
3226 __ bind(&slow); 3241 __ bind(&slow);
3227 3242
3228 // TODO(3095996): Put a valid pointer value in the stack slot where the result 3243 // TODO(3095996): Put a valid pointer value in the stack slot where the result
3229 // register is stored, as this register is in the pointer map, but contains an 3244 // register is stored, as this register is in the pointer map, but contains an
3230 // integer value. 3245 // integer value.
3231 __ mov(ip, Operand(0)); 3246 __ mov(ip, Operand(0));
3232 int reg_stack_index = __ SafepointRegisterStackIndex(reg.code()); 3247 __ StoreToSafepointRegisterSlot(ip, reg);
3233 __ str(ip, MemOperand(sp, reg_stack_index * kPointerSize));
3234
3235 __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber); 3248 __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber);
3236 RecordSafepointWithRegisters( 3249 RecordSafepointWithRegisters(
3237 instr->pointer_map(), 0, Safepoint::kNoDeoptimizationIndex); 3250 instr->pointer_map(), 0, Safepoint::kNoDeoptimizationIndex);
3238 if (!reg.is(r0)) __ mov(reg, r0); 3251 if (!reg.is(r0)) __ mov(reg, r0);
3239 3252
3240 // Done. Put the value in dbl_scratch into the value of the allocated heap 3253 // Done. Put the value in dbl_scratch into the value of the allocated heap
3241 // number. 3254 // number.
3242 __ bind(&done); 3255 __ bind(&done);
3243 __ sub(ip, reg, Operand(kHeapObjectTag)); 3256 __ sub(ip, reg, Operand(kHeapObjectTag));
3244 __ vstr(dbl_scratch, ip, HeapNumber::kValueOffset); 3257 __ vstr(dbl_scratch, ip, HeapNumber::kValueOffset);
3245 __ str(reg, MemOperand(sp, reg_stack_index * kPointerSize)); 3258 __ StoreToSafepointRegisterSlot(reg, reg);
3246 __ PopSafepointRegisters(); 3259 __ PopSafepointRegisters();
3247 } 3260 }
3248 3261
3249 3262
3250 void LCodeGen::DoNumberTagD(LNumberTagD* instr) { 3263 void LCodeGen::DoNumberTagD(LNumberTagD* instr) {
3251 class DeferredNumberTagD: public LDeferredCode { 3264 class DeferredNumberTagD: public LDeferredCode {
3252 public: 3265 public:
3253 DeferredNumberTagD(LCodeGen* codegen, LNumberTagD* instr) 3266 DeferredNumberTagD(LCodeGen* codegen, LNumberTagD* instr)
3254 : LDeferredCode(codegen), instr_(instr) { } 3267 : LDeferredCode(codegen), instr_(instr) { }
3255 virtual void Generate() { codegen()->DoDeferredNumberTagD(instr_); } 3268 virtual void Generate() { codegen()->DoDeferredNumberTagD(instr_); }
(...skipping 24 matching lines...) Expand all
3280 // TODO(3095996): Get rid of this. For now, we need to make the 3293 // TODO(3095996): Get rid of this. For now, we need to make the
3281 // result register contain a valid pointer because it is already 3294 // result register contain a valid pointer because it is already
3282 // contained in the register pointer map. 3295 // contained in the register pointer map.
3283 Register reg = ToRegister(instr->result()); 3296 Register reg = ToRegister(instr->result());
3284 __ mov(reg, Operand(0)); 3297 __ mov(reg, Operand(0));
3285 3298
3286 __ PushSafepointRegisters(); 3299 __ PushSafepointRegisters();
3287 __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber); 3300 __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber);
3288 RecordSafepointWithRegisters( 3301 RecordSafepointWithRegisters(
3289 instr->pointer_map(), 0, Safepoint::kNoDeoptimizationIndex); 3302 instr->pointer_map(), 0, Safepoint::kNoDeoptimizationIndex);
3290 int reg_stack_index = __ SafepointRegisterStackIndex(reg.code()); 3303 __ StoreToSafepointRegisterSlot(r0, reg);
3291 __ str(r0, MemOperand(sp, reg_stack_index * kPointerSize));
3292 __ PopSafepointRegisters(); 3304 __ PopSafepointRegisters();
3293 } 3305 }
3294 3306
3295 3307
3296 void LCodeGen::DoSmiTag(LSmiTag* instr) { 3308 void LCodeGen::DoSmiTag(LSmiTag* instr) {
3297 LOperand* input = instr->InputAt(0); 3309 LOperand* input = instr->InputAt(0);
3298 ASSERT(input->IsRegister() && input->Equals(instr->result())); 3310 ASSERT(input->IsRegister() && input->Equals(instr->result()));
3299 ASSERT(!instr->hydrogen_value()->CheckFlag(HValue::kCanOverflow)); 3311 ASSERT(!instr->hydrogen_value()->CheckFlag(HValue::kCanOverflow));
3300 __ SmiTag(ToRegister(input)); 3312 __ SmiTag(ToRegister(input));
3301 } 3313 }
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
3361 public: 3373 public:
3362 DeferredTaggedToI(LCodeGen* codegen, LTaggedToI* instr) 3374 DeferredTaggedToI(LCodeGen* codegen, LTaggedToI* instr)
3363 : LDeferredCode(codegen), instr_(instr) { } 3375 : LDeferredCode(codegen), instr_(instr) { }
3364 virtual void Generate() { codegen()->DoDeferredTaggedToI(instr_); } 3376 virtual void Generate() { codegen()->DoDeferredTaggedToI(instr_); }
3365 private: 3377 private:
3366 LTaggedToI* instr_; 3378 LTaggedToI* instr_;
3367 }; 3379 };
3368 3380
3369 3381
3370 void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) { 3382 void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) {
3383 Register input_reg = ToRegister(instr->InputAt(0));
3384 Register scratch1 = scratch0();
3385 Register scratch2 = ToRegister(instr->TempAt(0));
3386 DwVfpRegister double_scratch = double_scratch0();
3387 SwVfpRegister single_scratch = double_scratch.low();
3388
3389 ASSERT(!scratch1.is(input_reg) && !scratch1.is(scratch2));
3390 ASSERT(!scratch2.is(input_reg) && !scratch2.is(scratch1));
3391
3371 Label done; 3392 Label done;
3372 Register input_reg = ToRegister(instr->InputAt(0));
3373 Register scratch = scratch0();
3374 DoubleRegister dbl_scratch = d0;
3375 SwVfpRegister flt_scratch = s0;
3376 DoubleRegister dbl_tmp = ToDoubleRegister(instr->TempAt(0));
3377 3393
3378 // Heap number map check. 3394 // Heap number map check.
3379 __ ldr(scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset)); 3395 __ ldr(scratch1, FieldMemOperand(input_reg, HeapObject::kMapOffset));
3380 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex); 3396 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex);
3381 __ cmp(scratch, Operand(ip)); 3397 __ cmp(scratch1, Operand(ip));
3382 3398
3383 if (instr->truncating()) { 3399 if (instr->truncating()) {
3400 Register scratch3 = ToRegister(instr->TempAt(1));
3401 DwVfpRegister double_scratch2 = ToDoubleRegister(instr->TempAt(2));
3402 ASSERT(!scratch3.is(input_reg) &&
3403 !scratch3.is(scratch1) &&
3404 !scratch3.is(scratch2));
3405 // Performs a truncating conversion of a floating point number as used by
3406 // the JS bitwise operations.
3384 Label heap_number; 3407 Label heap_number;
3385 __ b(eq, &heap_number); 3408 __ b(eq, &heap_number);
3386 // Check for undefined. Undefined is converted to zero for truncating 3409 // Check for undefined. Undefined is converted to zero for truncating
3387 // conversions. 3410 // conversions.
3388 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); 3411 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
3389 __ cmp(input_reg, Operand(ip)); 3412 __ cmp(input_reg, Operand(ip));
3390 DeoptimizeIf(ne, instr->environment()); 3413 DeoptimizeIf(ne, instr->environment());
3391 __ mov(input_reg, Operand(0)); 3414 __ mov(input_reg, Operand(0));
3392 __ b(&done); 3415 __ b(&done);
3393 3416
3394 __ bind(&heap_number); 3417 __ bind(&heap_number);
3395 __ sub(ip, input_reg, Operand(kHeapObjectTag)); 3418 __ sub(scratch1, input_reg, Operand(kHeapObjectTag));
3396 __ vldr(dbl_tmp, ip, HeapNumber::kValueOffset); 3419 __ vldr(double_scratch2, scratch1, HeapNumber::kValueOffset);
3397 __ vcmp(dbl_tmp, 0.0); // Sets overflow bit in FPSCR flags if NaN. 3420
3398 __ vcvt_s32_f64(flt_scratch, dbl_tmp); 3421 __ EmitECMATruncate(input_reg,
3399 __ vmov(input_reg, flt_scratch); // 32-bit result of conversion. 3422 double_scratch2,
3400 __ vmrs(pc); // Move vector status bits to normal status bits. 3423 single_scratch,
3401 // Overflow bit is set if dbl_tmp is Nan. 3424 scratch1,
3402 __ cmn(input_reg, Operand(1), vc); // 0x7fffffff + 1 -> overflow. 3425 scratch2,
3403 __ cmp(input_reg, Operand(1), vc); // 0x80000000 - 1 -> overflow. 3426 scratch3);
3404 DeoptimizeIf(vs, instr->environment()); // Saturation may have occured.
3405 3427
3406 } else { 3428 } else {
3429 CpuFeatures::Scope scope(VFP3);
3407 // Deoptimize if we don't have a heap number. 3430 // Deoptimize if we don't have a heap number.
3408 DeoptimizeIf(ne, instr->environment()); 3431 DeoptimizeIf(ne, instr->environment());
3409 3432
3410 __ sub(ip, input_reg, Operand(kHeapObjectTag)); 3433 __ sub(ip, input_reg, Operand(kHeapObjectTag));
3411 __ vldr(dbl_tmp, ip, HeapNumber::kValueOffset); 3434 __ vldr(double_scratch, ip, HeapNumber::kValueOffset);
3412 __ vcvt_s32_f64(flt_scratch, dbl_tmp); 3435 __ EmitVFPTruncate(kRoundToZero,
3413 __ vmov(input_reg, flt_scratch); // 32-bit result of conversion. 3436 single_scratch,
3414 // Non-truncating conversion means that we cannot lose bits, so we convert 3437 double_scratch,
3415 // back to check; note that using non-overlapping s and d regs would be 3438 scratch1,
3416 // slightly faster. 3439 scratch2,
3417 __ vcvt_f64_s32(dbl_scratch, flt_scratch); 3440 kCheckForInexactConversion);
3418 __ VFPCompareAndSetFlags(dbl_scratch, dbl_tmp); 3441 DeoptimizeIf(ne, instr->environment());
3419 DeoptimizeIf(ne, instr->environment()); // Not equal or unordered. 3442 // Load the result.
3443 __ vmov(input_reg, single_scratch);
3444
3420 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 3445 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
3421 __ tst(input_reg, Operand(input_reg)); 3446 __ cmp(input_reg, Operand(0));
3422 __ b(ne, &done); 3447 __ b(ne, &done);
3423 __ vmov(lr, ip, dbl_tmp); 3448 __ vmov(scratch1, double_scratch.high());
3424 __ tst(ip, Operand(1 << 31)); // Test sign bit. 3449 __ tst(scratch1, Operand(HeapNumber::kSignMask));
3425 DeoptimizeIf(ne, instr->environment()); 3450 DeoptimizeIf(ne, instr->environment());
3426 } 3451 }
3427 } 3452 }
3428 __ bind(&done); 3453 __ bind(&done);
3429 } 3454 }
3430 3455
3431 3456
3432 void LCodeGen::DoTaggedToI(LTaggedToI* instr) { 3457 void LCodeGen::DoTaggedToI(LTaggedToI* instr) {
3433 LOperand* input = instr->InputAt(0); 3458 LOperand* input = instr->InputAt(0);
3434 ASSERT(input->IsRegister()); 3459 ASSERT(input->IsRegister());
(...skipping 21 matching lines...) Expand all
3456 ASSERT(result->IsDoubleRegister()); 3481 ASSERT(result->IsDoubleRegister());
3457 3482
3458 Register input_reg = ToRegister(input); 3483 Register input_reg = ToRegister(input);
3459 DoubleRegister result_reg = ToDoubleRegister(result); 3484 DoubleRegister result_reg = ToDoubleRegister(result);
3460 3485
3461 EmitNumberUntagD(input_reg, result_reg, instr->environment()); 3486 EmitNumberUntagD(input_reg, result_reg, instr->environment());
3462 } 3487 }
3463 3488
3464 3489
3465 void LCodeGen::DoDoubleToI(LDoubleToI* instr) { 3490 void LCodeGen::DoDoubleToI(LDoubleToI* instr) {
3466 LOperand* input = instr->InputAt(0); 3491 Register result_reg = ToRegister(instr->result());
3467 ASSERT(input->IsDoubleRegister());
3468 LOperand* result = instr->result();
3469 ASSERT(result->IsRegister());
3470
3471 DoubleRegister double_input = ToDoubleRegister(input);
3472 Register result_reg = ToRegister(result);
3473 SwVfpRegister single_scratch = double_scratch0().low();
3474 Register scratch1 = scratch0(); 3492 Register scratch1 = scratch0();
3475 Register scratch2 = ToRegister(instr->TempAt(0)); 3493 Register scratch2 = ToRegister(instr->TempAt(0));
3494 DwVfpRegister double_input = ToDoubleRegister(instr->InputAt(0));
3495 DwVfpRegister double_scratch = double_scratch0();
3496 SwVfpRegister single_scratch = double_scratch0().low();
3476 3497
3477 VFPRoundingMode rounding_mode = instr->truncating() ? kRoundToMinusInf 3498 Label done;
3478 : kRoundToNearest;
3479 3499
3480 EmitVFPTruncate(rounding_mode, 3500 if (instr->truncating()) {
3481 single_scratch, 3501 Register scratch3 = ToRegister(instr->TempAt(1));
3482 double_input, 3502 __ EmitECMATruncate(result_reg,
3483 scratch1, 3503 double_input,
3484 scratch2); 3504 single_scratch,
3485 // Deoptimize if we had a vfp invalid exception. 3505 scratch1,
3486 DeoptimizeIf(ne, instr->environment()); 3506 scratch2,
3487 // Retrieve the result. 3507 scratch3);
3488 __ vmov(result_reg, single_scratch); 3508 } else {
3489 3509 VFPRoundingMode rounding_mode = kRoundToMinusInf;
3490 if (instr->truncating() && 3510 __ EmitVFPTruncate(rounding_mode,
3491 instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 3511 single_scratch,
3492 Label done; 3512 double_input,
3493 __ cmp(result_reg, Operand(0)); 3513 scratch1,
3494 __ b(ne, &done); 3514 scratch2,
3495 // Check for -0. 3515 kCheckForInexactConversion);
3496 __ vmov(scratch1, double_input.high()); 3516 // Deoptimize if we had a vfp invalid exception,
3497 __ tst(scratch1, Operand(HeapNumber::kSignMask)); 3517 // including inexact operation.
3498 DeoptimizeIf(ne, instr->environment()); 3518 DeoptimizeIf(ne, instr->environment());
3499 3519 // Retrieve the result.
3520 __ vmov(result_reg, single_scratch);
3521 }
3500 __ bind(&done); 3522 __ bind(&done);
3501 }
3502 } 3523 }
3503 3524
3504 3525
3505 void LCodeGen::DoCheckSmi(LCheckSmi* instr) { 3526 void LCodeGen::DoCheckSmi(LCheckSmi* instr) {
3506 LOperand* input = instr->InputAt(0); 3527 LOperand* input = instr->InputAt(0);
3507 ASSERT(input->IsRegister()); 3528 ASSERT(input->IsRegister());
3508 __ tst(ToRegister(input), Operand(kSmiTagMask)); 3529 __ tst(ToRegister(input), Operand(kSmiTagMask));
3509 DeoptimizeIf(instr->condition(), instr->environment()); 3530 DeoptimizeIf(instr->condition(), instr->environment());
3510 } 3531 }
3511 3532
(...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after
3761 } 3782 }
3762 3783
3763 3784
3764 Condition LCodeGen::EmitTypeofIs(Label* true_label, 3785 Condition LCodeGen::EmitTypeofIs(Label* true_label,
3765 Label* false_label, 3786 Label* false_label,
3766 Register input, 3787 Register input,
3767 Handle<String> type_name) { 3788 Handle<String> type_name) {
3768 Condition final_branch_condition = kNoCondition; 3789 Condition final_branch_condition = kNoCondition;
3769 Register scratch = scratch0(); 3790 Register scratch = scratch0();
3770 if (type_name->Equals(Heap::number_symbol())) { 3791 if (type_name->Equals(Heap::number_symbol())) {
3771 __ tst(input, Operand(kSmiTagMask)); 3792 __ JumpIfSmi(input, true_label);
3772 __ b(eq, true_label);
3773 __ ldr(input, FieldMemOperand(input, HeapObject::kMapOffset)); 3793 __ ldr(input, FieldMemOperand(input, HeapObject::kMapOffset));
3774 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex); 3794 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex);
3775 __ cmp(input, Operand(ip)); 3795 __ cmp(input, Operand(ip));
3776 final_branch_condition = eq; 3796 final_branch_condition = eq;
3777 3797
3778 } else if (type_name->Equals(Heap::string_symbol())) { 3798 } else if (type_name->Equals(Heap::string_symbol())) {
3779 __ tst(input, Operand(kSmiTagMask)); 3799 __ JumpIfSmi(input, false_label);
3780 __ b(eq, false_label); 3800 __ CompareObjectType(input, input, scratch, FIRST_NONSTRING_TYPE);
3781 __ ldr(input, FieldMemOperand(input, HeapObject::kMapOffset)); 3801 __ b(ge, false_label);
3782 __ ldrb(ip, FieldMemOperand(input, Map::kBitFieldOffset)); 3802 __ ldrb(ip, FieldMemOperand(input, Map::kBitFieldOffset));
3783 __ tst(ip, Operand(1 << Map::kIsUndetectable)); 3803 __ tst(ip, Operand(1 << Map::kIsUndetectable));
3784 __ b(ne, false_label); 3804 final_branch_condition = eq;
3785 __ CompareInstanceType(input, scratch, FIRST_NONSTRING_TYPE);
3786 final_branch_condition = lo;
3787 3805
3788 } else if (type_name->Equals(Heap::boolean_symbol())) { 3806 } else if (type_name->Equals(Heap::boolean_symbol())) {
3789 __ LoadRoot(ip, Heap::kTrueValueRootIndex); 3807 __ CompareRoot(input, Heap::kTrueValueRootIndex);
3790 __ cmp(input, ip);
3791 __ b(eq, true_label); 3808 __ b(eq, true_label);
3792 __ LoadRoot(ip, Heap::kFalseValueRootIndex); 3809 __ CompareRoot(input, Heap::kFalseValueRootIndex);
3793 __ cmp(input, ip);
3794 final_branch_condition = eq; 3810 final_branch_condition = eq;
3795 3811
3796 } else if (type_name->Equals(Heap::undefined_symbol())) { 3812 } else if (type_name->Equals(Heap::undefined_symbol())) {
3797 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); 3813 __ CompareRoot(input, Heap::kUndefinedValueRootIndex);
3798 __ cmp(input, ip);
3799 __ b(eq, true_label); 3814 __ b(eq, true_label);
3800 __ tst(input, Operand(kSmiTagMask)); 3815 __ JumpIfSmi(input, false_label);
3801 __ b(eq, false_label);
3802 // Check for undetectable objects => true. 3816 // Check for undetectable objects => true.
3803 __ ldr(input, FieldMemOperand(input, HeapObject::kMapOffset)); 3817 __ ldr(input, FieldMemOperand(input, HeapObject::kMapOffset));
3804 __ ldrb(ip, FieldMemOperand(input, Map::kBitFieldOffset)); 3818 __ ldrb(ip, FieldMemOperand(input, Map::kBitFieldOffset));
3805 __ tst(ip, Operand(1 << Map::kIsUndetectable)); 3819 __ tst(ip, Operand(1 << Map::kIsUndetectable));
3806 final_branch_condition = ne; 3820 final_branch_condition = ne;
3807 3821
3808 } else if (type_name->Equals(Heap::function_symbol())) { 3822 } else if (type_name->Equals(Heap::function_symbol())) {
3809 __ tst(input, Operand(kSmiTagMask)); 3823 __ JumpIfSmi(input, false_label);
3810 __ b(eq, false_label); 3824 __ CompareObjectType(input, input, scratch, FIRST_FUNCTION_CLASS_TYPE);
3811 __ CompareObjectType(input, input, scratch, JS_FUNCTION_TYPE); 3825 final_branch_condition = ge;
3812 __ b(eq, true_label);
3813 // Regular expressions => 'function' (they are callable).
3814 __ CompareInstanceType(input, scratch, JS_REGEXP_TYPE);
3815 final_branch_condition = eq;
3816 3826
3817 } else if (type_name->Equals(Heap::object_symbol())) { 3827 } else if (type_name->Equals(Heap::object_symbol())) {
3818 __ tst(input, Operand(kSmiTagMask)); 3828 __ JumpIfSmi(input, false_label);
3819 __ b(eq, false_label); 3829 __ CompareRoot(input, Heap::kNullValueRootIndex);
3820 __ LoadRoot(ip, Heap::kNullValueRootIndex);
3821 __ cmp(input, ip);
3822 __ b(eq, true_label); 3830 __ b(eq, true_label);
3823 // Regular expressions => 'function', not 'object'. 3831 __ CompareObjectType(input, input, scratch, FIRST_JS_OBJECT_TYPE);
3824 __ CompareObjectType(input, input, scratch, JS_REGEXP_TYPE); 3832 __ b(lo, false_label);
3825 __ b(eq, false_label); 3833 __ CompareInstanceType(input, scratch, FIRST_FUNCTION_CLASS_TYPE);
3834 __ b(hs, false_label);
3826 // Check for undetectable objects => false. 3835 // Check for undetectable objects => false.
3827 __ ldrb(ip, FieldMemOperand(input, Map::kBitFieldOffset)); 3836 __ ldrb(ip, FieldMemOperand(input, Map::kBitFieldOffset));
3828 __ tst(ip, Operand(1 << Map::kIsUndetectable)); 3837 __ tst(ip, Operand(1 << Map::kIsUndetectable));
3829 __ b(ne, false_label); 3838 final_branch_condition = eq;
3830 // Check for JS objects => true.
3831 __ CompareInstanceType(input, scratch, FIRST_JS_OBJECT_TYPE);
3832 __ b(lo, false_label);
3833 __ CompareInstanceType(input, scratch, LAST_JS_OBJECT_TYPE);
3834 final_branch_condition = ls;
3835 3839
3836 } else { 3840 } else {
3837 final_branch_condition = ne; 3841 final_branch_condition = ne;
3838 __ b(false_label); 3842 __ b(false_label);
3839 // A dead branch instruction will be generated after this point. 3843 // A dead branch instruction will be generated after this point.
3840 } 3844 }
3841 3845
3842 return final_branch_condition; 3846 return final_branch_condition;
3843 } 3847 }
3844 3848
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
3946 ASSERT(!environment->HasBeenRegistered()); 3950 ASSERT(!environment->HasBeenRegistered());
3947 RegisterEnvironmentForDeoptimization(environment); 3951 RegisterEnvironmentForDeoptimization(environment);
3948 ASSERT(osr_pc_offset_ == -1); 3952 ASSERT(osr_pc_offset_ == -1);
3949 osr_pc_offset_ = masm()->pc_offset(); 3953 osr_pc_offset_ = masm()->pc_offset();
3950 } 3954 }
3951 3955
3952 3956
3953 #undef __ 3957 #undef __
3954 3958
3955 } } // namespace v8::internal 3959 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/arm/lithium-codegen-arm.h ('k') | src/arm/lithium-gap-resolver-arm.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698