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

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

Issue 6597029: [Isolates] Merge r 6300:6500 from bleeding_edge to isolates. (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/isolates/
Patch Set: Created 9 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/arm/lithium-codegen-arm.h ('k') | src/arm/macro-assembler-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
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
47 codegen_->RecordSafepoint(pointers_, deoptimization_index_); 47 codegen_->RecordSafepoint(pointers_, deoptimization_index_);
48 } 48 }
49 49
50 private: 50 private:
51 LCodeGen* codegen_; 51 LCodeGen* codegen_;
52 LPointerMap* pointers_; 52 LPointerMap* pointers_;
53 int deoptimization_index_; 53 int deoptimization_index_;
54 }; 54 };
55 55
56 56
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
57 #define __ masm()-> 208 #define __ masm()->
58 209
59 bool LCodeGen::GenerateCode() { 210 bool LCodeGen::GenerateCode() {
60 HPhase phase("Code generation", chunk()); 211 HPhase phase("Code generation", chunk());
61 ASSERT(is_unused()); 212 ASSERT(is_unused());
62 status_ = GENERATING; 213 status_ = GENERATING;
63 CpuFeatures::Scope scope1(VFP3); 214 CpuFeatures::Scope scope1(VFP3);
64 CpuFeatures::Scope scope2(ARMv7); 215 CpuFeatures::Scope scope2(ARMv7);
65 return GeneratePrologue() && 216 return GeneratePrologue() &&
66 GenerateBody() && 217 GenerateBody() &&
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after
183 334
184 bool LCodeGen::GenerateDeferredCode() { 335 bool LCodeGen::GenerateDeferredCode() {
185 ASSERT(is_generating()); 336 ASSERT(is_generating());
186 for (int i = 0; !is_aborted() && i < deferred_.length(); i++) { 337 for (int i = 0; !is_aborted() && i < deferred_.length(); i++) {
187 LDeferredCode* code = deferred_[i]; 338 LDeferredCode* code = deferred_[i];
188 __ bind(code->entry()); 339 __ bind(code->entry());
189 code->Generate(); 340 code->Generate();
190 __ jmp(code->exit()); 341 __ jmp(code->exit());
191 } 342 }
192 343
344 // Force constant pool emission at the end of deferred code to make
345 // sure that no constant pools are emitted after the official end of
346 // the instruction sequence.
347 masm()->CheckConstPool(true, false);
348
193 // Deferred code is the last part of the instruction sequence. Mark 349 // Deferred code is the last part of the instruction sequence. Mark
194 // the generated code as done unless we bailed out. 350 // the generated code as done unless we bailed out.
195 if (!is_aborted()) status_ = DONE; 351 if (!is_aborted()) status_ = DONE;
196 return !is_aborted(); 352 return !is_aborted();
197 } 353 }
198 354
199 355
200 bool LCodeGen::GenerateSafepointTable() { 356 bool LCodeGen::GenerateSafepointTable() {
201 ASSERT(is_done()); 357 ASSERT(is_done());
202 safepoints_.Emit(masm(), StackSlotCount()); 358 safepoints_.Emit(masm(), StackSlotCount());
(...skipping 295 matching lines...) Expand 10 before | Expand all | Expand 10 after
498 } 654 }
499 655
500 ASSERT(FLAG_deopt_every_n_times < 2); // Other values not supported on ARM. 656 ASSERT(FLAG_deopt_every_n_times < 2); // Other values not supported on ARM.
501 657
502 if (FLAG_deopt_every_n_times == 1 && 658 if (FLAG_deopt_every_n_times == 1 &&
503 info_->shared_info()->opt_count() == id) { 659 info_->shared_info()->opt_count() == id) {
504 __ Jump(entry, RelocInfo::RUNTIME_ENTRY); 660 __ Jump(entry, RelocInfo::RUNTIME_ENTRY);
505 return; 661 return;
506 } 662 }
507 663
508 if (cc == no_condition) { 664 if (cc == kNoCondition) {
509 if (FLAG_trap_on_deopt) __ stop("trap_on_deopt"); 665 if (FLAG_trap_on_deopt) __ stop("trap_on_deopt");
510 __ Jump(entry, RelocInfo::RUNTIME_ENTRY); 666 __ Jump(entry, RelocInfo::RUNTIME_ENTRY);
511 } else { 667 } else {
512 if (FLAG_trap_on_deopt) { 668 if (FLAG_trap_on_deopt) {
513 Label done; 669 Label done;
514 __ b(&done, NegateCondition(cc)); 670 __ b(&done, NegateCondition(cc));
515 __ stop("trap_on_deopt"); 671 __ stop("trap_on_deopt");
516 __ Jump(entry, RelocInfo::RUNTIME_ENTRY); 672 __ Jump(entry, RelocInfo::RUNTIME_ENTRY);
517 __ bind(&done); 673 __ bind(&done);
518 } else { 674 } else {
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
607 safepoint.DefinePointerSlot(pointer->index()); 763 safepoint.DefinePointerSlot(pointer->index());
608 } else if (pointer->IsRegister()) { 764 } else if (pointer->IsRegister()) {
609 safepoint.DefinePointerRegister(ToRegister(pointer)); 765 safepoint.DefinePointerRegister(ToRegister(pointer));
610 } 766 }
611 } 767 }
612 // Register cp always contains a pointer to the context. 768 // Register cp always contains a pointer to the context.
613 safepoint.DefinePointerRegister(cp); 769 safepoint.DefinePointerRegister(cp);
614 } 770 }
615 771
616 772
773 void LCodeGen::RecordSafepointWithRegistersAndDoubles(
774 LPointerMap* pointers,
775 int arguments,
776 int deoptimization_index) {
777 const ZoneList<LOperand*>* operands = pointers->operands();
778 Safepoint safepoint =
779 safepoints_.DefineSafepointWithRegistersAndDoubles(
780 masm(), arguments, deoptimization_index);
781 for (int i = 0; i < operands->length(); i++) {
782 LOperand* pointer = operands->at(i);
783 if (pointer->IsStackSlot()) {
784 safepoint.DefinePointerSlot(pointer->index());
785 } else if (pointer->IsRegister()) {
786 safepoint.DefinePointerRegister(ToRegister(pointer));
787 }
788 }
789 // Register cp always contains a pointer to the context.
790 safepoint.DefinePointerRegister(cp);
791 }
792
793
617 void LCodeGen::RecordPosition(int position) { 794 void LCodeGen::RecordPosition(int position) {
618 if (!FLAG_debug_info || position == RelocInfo::kNoPosition) return; 795 if (!FLAG_debug_info || position == RelocInfo::kNoPosition) return;
619 masm()->positions_recorder()->RecordPosition(position); 796 masm()->positions_recorder()->RecordPosition(position);
620 } 797 }
621 798
622 799
623 void LCodeGen::DoLabel(LLabel* label) { 800 void LCodeGen::DoLabel(LLabel* label) {
624 if (label->is_loop_header()) { 801 if (label->is_loop_header()) {
625 Comment(";;; B%d - LOOP entry", label->block_id()); 802 Comment(";;; B%d - LOOP entry", label->block_id());
626 } else { 803 } else {
(...skipping 10 matching lines...) Expand all
637 DoubleRegister dbl_scratch = d0; 814 DoubleRegister dbl_scratch = d0;
638 LUnallocated marker_operand(LUnallocated::NONE); 815 LUnallocated marker_operand(LUnallocated::NONE);
639 816
640 Register core_scratch = scratch0(); 817 Register core_scratch = scratch0();
641 bool destroys_core_scratch = false; 818 bool destroys_core_scratch = false;
642 819
643 const ZoneList<LMoveOperands>* moves = 820 const ZoneList<LMoveOperands>* moves =
644 resolver_.Resolve(move->move_operands(), &marker_operand); 821 resolver_.Resolve(move->move_operands(), &marker_operand);
645 for (int i = moves->length() - 1; i >= 0; --i) { 822 for (int i = moves->length() - 1; i >= 0; --i) {
646 LMoveOperands move = moves->at(i); 823 LMoveOperands move = moves->at(i);
647 LOperand* from = move.from(); 824 LOperand* from = move.source();
648 LOperand* to = move.to(); 825 LOperand* to = move.destination();
649 ASSERT(!from->IsDoubleRegister() || 826 ASSERT(!from->IsDoubleRegister() ||
650 !ToDoubleRegister(from).is(dbl_scratch)); 827 !ToDoubleRegister(from).is(dbl_scratch));
651 ASSERT(!to->IsDoubleRegister() || !ToDoubleRegister(to).is(dbl_scratch)); 828 ASSERT(!to->IsDoubleRegister() || !ToDoubleRegister(to).is(dbl_scratch));
652 ASSERT(!from->IsRegister() || !ToRegister(from).is(core_scratch)); 829 ASSERT(!from->IsRegister() || !ToRegister(from).is(core_scratch));
653 ASSERT(!to->IsRegister() || !ToRegister(to).is(core_scratch)); 830 ASSERT(!to->IsRegister() || !ToRegister(to).is(core_scratch));
654 if (from == &marker_operand) { 831 if (from == &marker_operand) {
655 if (to->IsRegister()) { 832 if (to->IsRegister()) {
656 __ mov(ToRegister(to), core_scratch); 833 __ mov(ToRegister(to), core_scratch);
657 ASSERT(destroys_core_scratch); 834 ASSERT(destroys_core_scratch);
658 } else if (to->IsStackSlot()) { 835 } else if (to->IsStackSlot()) {
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after
780 RegExpExecStub stub; 957 RegExpExecStub stub;
781 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); 958 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
782 break; 959 break;
783 } 960 }
784 case CodeStub::SubString: { 961 case CodeStub::SubString: {
785 SubStringStub stub; 962 SubStringStub stub;
786 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); 963 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
787 break; 964 break;
788 } 965 }
789 case CodeStub::StringCharAt: { 966 case CodeStub::StringCharAt: {
790 Abort("StringCharAtStub unimplemented."); 967 StringCharAtStub stub;
968 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
791 break; 969 break;
792 } 970 }
793 case CodeStub::MathPow: { 971 case CodeStub::MathPow: {
794 Abort("MathPowStub unimplemented."); 972 Abort("MathPowStub unimplemented.");
795 break; 973 break;
796 } 974 }
797 case CodeStub::NumberToString: { 975 case CodeStub::NumberToString: {
798 NumberToStringStub stub; 976 NumberToStringStub stub;
799 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); 977 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
800 break; 978 break;
(...skipping 19 matching lines...) Expand all
820 } 998 }
821 } 999 }
822 1000
823 1001
824 void LCodeGen::DoUnknownOSRValue(LUnknownOSRValue* instr) { 1002 void LCodeGen::DoUnknownOSRValue(LUnknownOSRValue* instr) {
825 // Nothing to do. 1003 // Nothing to do.
826 } 1004 }
827 1005
828 1006
829 void LCodeGen::DoModI(LModI* instr) { 1007 void LCodeGen::DoModI(LModI* instr) {
830 Abort("DoModI unimplemented."); 1008 class DeferredModI: public LDeferredCode {
1009 public:
1010 DeferredModI(LCodeGen* codegen, LModI* instr)
1011 : LDeferredCode(codegen), instr_(instr) { }
1012 virtual void Generate() {
1013 codegen()->DoDeferredGenericBinaryStub(instr_, Token::MOD);
1014 }
1015 private:
1016 LModI* instr_;
1017 };
1018 // These registers hold untagged 32 bit values.
1019 Register left = ToRegister(instr->InputAt(0));
1020 Register right = ToRegister(instr->InputAt(1));
1021 Register result = ToRegister(instr->result());
1022 Register scratch = scratch0();
1023
1024 Label deoptimize, done;
1025 // Check for x % 0.
1026 if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) {
1027 __ tst(right, Operand(right));
1028 __ b(eq, &deoptimize);
1029 }
1030
1031 // Check for (0 % -x) that will produce negative zero.
1032 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
1033 Label ok;
1034 __ tst(left, Operand(left));
1035 __ b(ne, &ok);
1036 __ tst(right, Operand(right));
1037 __ b(pl, &ok);
1038 __ b(al, &deoptimize);
1039 __ bind(&ok);
1040 }
1041
1042 // Try a few common cases before using the generic stub.
1043 Label call_stub;
1044 const int kUnfolds = 3;
1045 // Skip if either side is negative.
1046 __ cmp(left, Operand(0));
1047 __ cmp(right, Operand(0), NegateCondition(mi));
1048 __ b(mi, &call_stub);
1049 // If the right hand side is smaller than the (nonnegative)
1050 // left hand side, it is the result. Else try a few subtractions
1051 // of the left hand side.
1052 __ mov(scratch, left);
1053 for (int i = 0; i < kUnfolds; i++) {
1054 // Check if the left hand side is less or equal than the
1055 // the right hand side.
1056 __ cmp(scratch, right);
1057 __ mov(result, scratch, LeaveCC, lt);
1058 __ b(lt, &done);
1059 // If not, reduce the left hand side by the right hand
1060 // side and check again.
1061 if (i < kUnfolds - 1) __ sub(scratch, scratch, right);
1062 }
1063
1064 // Check for power of two on the right hand side.
1065 __ sub(scratch, right, Operand(1), SetCC);
1066 __ b(mi, &call_stub);
1067 __ tst(scratch, right);
1068 __ b(ne, &call_stub);
1069 // Perform modulo operation.
1070 __ and_(result, scratch, Operand(left));
1071
1072 __ bind(&call_stub);
1073 // Call the generic stub. The numbers in r0 and r1 have
1074 // to be tagged to Smis. If that is not possible, deoptimize.
1075 DeferredModI* deferred = new DeferredModI(this, instr);
1076 __ TrySmiTag(left, &deoptimize, scratch);
1077 __ TrySmiTag(right, &deoptimize, scratch);
1078
1079 __ b(al, deferred->entry());
1080 __ bind(deferred->exit());
1081
1082 // If the result in r0 is a Smi, untag it, else deoptimize.
1083 __ JumpIfNotSmi(result, &deoptimize);
1084 __ SmiUntag(result);
1085
1086 __ b(al, &done);
1087 __ bind(&deoptimize);
1088 DeoptimizeIf(al, instr->environment());
1089 __ bind(&done);
831 } 1090 }
832 1091
833 1092
834 void LCodeGen::DoDivI(LDivI* instr) { 1093 void LCodeGen::DoDivI(LDivI* instr) {
835 Abort("DoDivI unimplemented."); 1094 class DeferredDivI: public LDeferredCode {
1095 public:
1096 DeferredDivI(LCodeGen* codegen, LDivI* instr)
1097 : LDeferredCode(codegen), instr_(instr) { }
1098 virtual void Generate() {
1099 codegen()->DoDeferredGenericBinaryStub(instr_, Token::DIV);
1100 }
1101 private:
1102 LDivI* instr_;
1103 };
1104
1105 const Register left = ToRegister(instr->InputAt(0));
1106 const Register right = ToRegister(instr->InputAt(1));
1107 const Register scratch = scratch0();
1108 const Register result = ToRegister(instr->result());
1109
1110 // Check for x / 0.
1111 if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) {
1112 __ tst(right, right);
1113 DeoptimizeIf(eq, instr->environment());
1114 }
1115
1116 // Check for (0 / -x) that will produce negative zero.
1117 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
1118 Label left_not_zero;
1119 __ tst(left, Operand(left));
1120 __ b(ne, &left_not_zero);
1121 __ tst(right, Operand(right));
1122 DeoptimizeIf(mi, instr->environment());
1123 __ bind(&left_not_zero);
1124 }
1125
1126 // Check for (-kMinInt / -1).
1127 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) {
1128 Label left_not_min_int;
1129 __ cmp(left, Operand(kMinInt));
1130 __ b(ne, &left_not_min_int);
1131 __ cmp(right, Operand(-1));
1132 DeoptimizeIf(eq, instr->environment());
1133 __ bind(&left_not_min_int);
1134 }
1135
1136 Label done, deoptimize;
1137 // Test for a few common cases first.
1138 __ cmp(right, Operand(1));
1139 __ mov(result, left, LeaveCC, eq);
1140 __ b(eq, &done);
1141
1142 __ cmp(right, Operand(2));
1143 __ tst(left, Operand(1), eq);
1144 __ mov(result, Operand(left, ASR, 1), LeaveCC, eq);
1145 __ b(eq, &done);
1146
1147 __ cmp(right, Operand(4));
1148 __ tst(left, Operand(3), eq);
1149 __ mov(result, Operand(left, ASR, 2), LeaveCC, eq);
1150 __ b(eq, &done);
1151
1152 // Call the generic stub. The numbers in r0 and r1 have
1153 // to be tagged to Smis. If that is not possible, deoptimize.
1154 DeferredDivI* deferred = new DeferredDivI(this, instr);
1155
1156 __ TrySmiTag(left, &deoptimize, scratch);
1157 __ TrySmiTag(right, &deoptimize, scratch);
1158
1159 __ b(al, deferred->entry());
1160 __ bind(deferred->exit());
1161
1162 // If the result in r0 is a Smi, untag it, else deoptimize.
1163 __ JumpIfNotSmi(result, &deoptimize);
1164 __ SmiUntag(result);
1165 __ b(&done);
1166
1167 __ bind(&deoptimize);
1168 DeoptimizeIf(al, instr->environment());
1169 __ bind(&done);
1170 }
1171
1172
1173 template<int T>
1174 void LCodeGen::DoDeferredGenericBinaryStub(LTemplateInstruction<1, 2, T>* instr,
1175 Token::Value op) {
1176 Register left = ToRegister(instr->InputAt(0));
1177 Register right = ToRegister(instr->InputAt(1));
1178
1179 __ PushSafepointRegistersAndDoubles();
1180 GenericBinaryOpStub stub(op, OVERWRITE_LEFT, left, right);
1181 __ CallStub(&stub);
1182 RecordSafepointWithRegistersAndDoubles(instr->pointer_map(),
1183 0,
1184 Safepoint::kNoDeoptimizationIndex);
1185 // Overwrite the stored value of r0 with the result of the stub.
1186 __ str(r0, MemOperand(sp, DwVfpRegister::kNumAllocatableRegisters *
1187 kDoubleSize));
1188 __ PopSafepointRegistersAndDoubles();
836 } 1189 }
837 1190
838 1191
839 void LCodeGen::DoMulI(LMulI* instr) { 1192 void LCodeGen::DoMulI(LMulI* instr) {
840 Register scratch = scratch0(); 1193 Register scratch = scratch0();
841 Register left = ToRegister(instr->left()); 1194 Register left = ToRegister(instr->InputAt(0));
842 Register right = EmitLoadRegister(instr->right(), scratch); 1195 Register right = EmitLoadRegister(instr->InputAt(1), scratch);
843 1196
844 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero) && 1197 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero) &&
845 !instr->right()->IsConstantOperand()) { 1198 !instr->InputAt(1)->IsConstantOperand()) {
846 __ orr(ToRegister(instr->temp()), left, right); 1199 __ orr(ToRegister(instr->TempAt(0)), left, right);
847 } 1200 }
848 1201
849 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { 1202 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) {
850 // scratch:left = left * right. 1203 // scratch:left = left * right.
851 __ smull(scratch, left, left, right); 1204 __ smull(scratch, left, left, right);
852 __ mov(ip, Operand(left, ASR, 31)); 1205 __ mov(ip, Operand(left, ASR, 31));
853 __ cmp(ip, Operand(scratch)); 1206 __ cmp(ip, Operand(scratch));
854 DeoptimizeIf(ne, instr->environment()); 1207 DeoptimizeIf(ne, instr->environment());
855 } else { 1208 } else {
856 __ mul(left, left, right); 1209 __ mul(left, left, right);
857 } 1210 }
858 1211
859 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 1212 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
860 // Bail out if the result is supposed to be negative zero. 1213 // Bail out if the result is supposed to be negative zero.
861 Label done; 1214 Label done;
862 __ tst(left, Operand(left)); 1215 __ tst(left, Operand(left));
863 __ b(ne, &done); 1216 __ b(ne, &done);
864 if (instr->right()->IsConstantOperand()) { 1217 if (instr->InputAt(1)->IsConstantOperand()) {
865 if (ToInteger32(LConstantOperand::cast(instr->right())) < 0) { 1218 if (ToInteger32(LConstantOperand::cast(instr->InputAt(1))) < 0) {
866 DeoptimizeIf(no_condition, instr->environment()); 1219 DeoptimizeIf(kNoCondition, instr->environment());
867 } 1220 }
868 } else { 1221 } else {
869 // Test the non-zero operand for negative sign. 1222 // Test the non-zero operand for negative sign.
870 __ cmp(ToRegister(instr->temp()), Operand(0)); 1223 __ cmp(ToRegister(instr->TempAt(0)), Operand(0));
871 DeoptimizeIf(mi, instr->environment()); 1224 DeoptimizeIf(mi, instr->environment());
872 } 1225 }
873 __ bind(&done); 1226 __ bind(&done);
874 } 1227 }
875 } 1228 }
876 1229
877 1230
878 void LCodeGen::DoBitI(LBitI* instr) { 1231 void LCodeGen::DoBitI(LBitI* instr) {
879 LOperand* left = instr->left(); 1232 LOperand* left = instr->InputAt(0);
880 LOperand* right = instr->right(); 1233 LOperand* right = instr->InputAt(1);
881 ASSERT(left->Equals(instr->result())); 1234 ASSERT(left->Equals(instr->result()));
882 ASSERT(left->IsRegister()); 1235 ASSERT(left->IsRegister());
883 Register result = ToRegister(left); 1236 Register result = ToRegister(left);
884 Register right_reg = EmitLoadRegister(right, ip); 1237 Register right_reg = EmitLoadRegister(right, ip);
885 switch (instr->op()) { 1238 switch (instr->op()) {
886 case Token::BIT_AND: 1239 case Token::BIT_AND:
887 __ and_(result, ToRegister(left), Operand(right_reg)); 1240 __ and_(result, ToRegister(left), Operand(right_reg));
888 break; 1241 break;
889 case Token::BIT_OR: 1242 case Token::BIT_OR:
890 __ orr(result, ToRegister(left), Operand(right_reg)); 1243 __ orr(result, ToRegister(left), Operand(right_reg));
891 break; 1244 break;
892 case Token::BIT_XOR: 1245 case Token::BIT_XOR:
893 __ eor(result, ToRegister(left), Operand(right_reg)); 1246 __ eor(result, ToRegister(left), Operand(right_reg));
894 break; 1247 break;
895 default: 1248 default:
896 UNREACHABLE(); 1249 UNREACHABLE();
897 break; 1250 break;
898 } 1251 }
899 } 1252 }
900 1253
901 1254
902 void LCodeGen::DoShiftI(LShiftI* instr) { 1255 void LCodeGen::DoShiftI(LShiftI* instr) {
903 Register scratch = scratch0(); 1256 Register scratch = scratch0();
904 LOperand* left = instr->left(); 1257 LOperand* left = instr->InputAt(0);
905 LOperand* right = instr->right(); 1258 LOperand* right = instr->InputAt(1);
906 ASSERT(left->Equals(instr->result())); 1259 ASSERT(left->Equals(instr->result()));
907 ASSERT(left->IsRegister()); 1260 ASSERT(left->IsRegister());
908 Register result = ToRegister(left); 1261 Register result = ToRegister(left);
909 if (right->IsRegister()) { 1262 if (right->IsRegister()) {
910 // Mask the right operand. 1263 // Mask the right operand.
911 __ and_(scratch, ToRegister(right), Operand(0x1F)); 1264 __ and_(scratch, ToRegister(right), Operand(0x1F));
912 switch (instr->op()) { 1265 switch (instr->op()) {
913 case Token::SAR: 1266 case Token::SAR:
914 __ mov(result, Operand(result, ASR, scratch)); 1267 __ mov(result, Operand(result, ASR, scratch));
915 break; 1268 break;
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
952 break; 1305 break;
953 default: 1306 default:
954 UNREACHABLE(); 1307 UNREACHABLE();
955 break; 1308 break;
956 } 1309 }
957 } 1310 }
958 } 1311 }
959 1312
960 1313
961 void LCodeGen::DoSubI(LSubI* instr) { 1314 void LCodeGen::DoSubI(LSubI* instr) {
962 Register left = ToRegister(instr->left()); 1315 Register left = ToRegister(instr->InputAt(0));
963 Register right = EmitLoadRegister(instr->right(), ip); 1316 Register right = EmitLoadRegister(instr->InputAt(1), ip);
964 ASSERT(instr->left()->Equals(instr->result())); 1317 ASSERT(instr->InputAt(0)->Equals(instr->result()));
965 __ sub(left, left, right, SetCC); 1318 __ sub(left, left, right, SetCC);
966 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { 1319 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) {
967 DeoptimizeIf(vs, instr->environment()); 1320 DeoptimizeIf(vs, instr->environment());
968 } 1321 }
969 } 1322 }
970 1323
971 1324
972 void LCodeGen::DoConstantI(LConstantI* instr) { 1325 void LCodeGen::DoConstantI(LConstantI* instr) {
973 ASSERT(instr->result()->IsRegister()); 1326 ASSERT(instr->result()->IsRegister());
974 __ mov(ToRegister(instr->result()), Operand(instr->value())); 1327 __ mov(ToRegister(instr->result()), Operand(instr->value()));
975 } 1328 }
976 1329
977 1330
978 void LCodeGen::DoConstantD(LConstantD* instr) { 1331 void LCodeGen::DoConstantD(LConstantD* instr) {
979 Abort("DoConstantD unimplemented."); 1332 ASSERT(instr->result()->IsDoubleRegister());
1333 DwVfpRegister result = ToDoubleRegister(instr->result());
1334 double v = instr->value();
1335 __ vmov(result, v);
980 } 1336 }
981 1337
982 1338
983 void LCodeGen::DoConstantT(LConstantT* instr) { 1339 void LCodeGen::DoConstantT(LConstantT* instr) {
984 ASSERT(instr->result()->IsRegister()); 1340 ASSERT(instr->result()->IsRegister());
985 __ mov(ToRegister(instr->result()), Operand(instr->value())); 1341 __ mov(ToRegister(instr->result()), Operand(instr->value()));
986 } 1342 }
987 1343
988 1344
989 void LCodeGen::DoJSArrayLength(LJSArrayLength* instr) { 1345 void LCodeGen::DoJSArrayLength(LJSArrayLength* instr) {
990 Register result = ToRegister(instr->result()); 1346 Register result = ToRegister(instr->result());
991 Register array = ToRegister(instr->input()); 1347 Register array = ToRegister(instr->InputAt(0));
992 __ ldr(result, FieldMemOperand(array, JSArray::kLengthOffset)); 1348 __ ldr(result, FieldMemOperand(array, JSArray::kLengthOffset));
993 } 1349 }
994 1350
995 1351
996 void LCodeGen::DoFixedArrayLength(LFixedArrayLength* instr) { 1352 void LCodeGen::DoFixedArrayLength(LFixedArrayLength* instr) {
997 Register result = ToRegister(instr->result()); 1353 Register result = ToRegister(instr->result());
998 Register array = ToRegister(instr->input()); 1354 Register array = ToRegister(instr->InputAt(0));
999 __ ldr(result, FieldMemOperand(array, FixedArray::kLengthOffset)); 1355 __ ldr(result, FieldMemOperand(array, FixedArray::kLengthOffset));
1000 } 1356 }
1001 1357
1002 1358
1003 void LCodeGen::DoValueOf(LValueOf* instr) { 1359 void LCodeGen::DoValueOf(LValueOf* instr) {
1004 Register input = ToRegister(instr->input()); 1360 Register input = ToRegister(instr->InputAt(0));
1005 Register result = ToRegister(instr->result()); 1361 Register result = ToRegister(instr->result());
1006 Register map = ToRegister(instr->temporary()); 1362 Register map = ToRegister(instr->TempAt(0));
1007 ASSERT(input.is(result)); 1363 ASSERT(input.is(result));
1008 Label done; 1364 Label done;
1009 1365
1010 // If the object is a smi return the object. 1366 // If the object is a smi return the object.
1011 __ tst(input, Operand(kSmiTagMask)); 1367 __ tst(input, Operand(kSmiTagMask));
1012 __ b(eq, &done); 1368 __ b(eq, &done);
1013 1369
1014 // If the object is not a value type, return the object. 1370 // If the object is not a value type, return the object.
1015 __ CompareObjectType(input, map, map, JS_VALUE_TYPE); 1371 __ CompareObjectType(input, map, map, JS_VALUE_TYPE);
1016 __ b(ne, &done); 1372 __ b(ne, &done);
1017 __ ldr(result, FieldMemOperand(input, JSValue::kValueOffset)); 1373 __ ldr(result, FieldMemOperand(input, JSValue::kValueOffset));
1018 1374
1019 __ bind(&done); 1375 __ bind(&done);
1020 } 1376 }
1021 1377
1022 1378
1023 void LCodeGen::DoBitNotI(LBitNotI* instr) { 1379 void LCodeGen::DoBitNotI(LBitNotI* instr) {
1024 LOperand* input = instr->input(); 1380 LOperand* input = instr->InputAt(0);
1025 ASSERT(input->Equals(instr->result())); 1381 ASSERT(input->Equals(instr->result()));
1026 __ mvn(ToRegister(input), Operand(ToRegister(input))); 1382 __ mvn(ToRegister(input), Operand(ToRegister(input)));
1027 } 1383 }
1028 1384
1029 1385
1030 void LCodeGen::DoThrow(LThrow* instr) { 1386 void LCodeGen::DoThrow(LThrow* instr) {
1031 Register input_reg = EmitLoadRegister(instr->input(), ip); 1387 Register input_reg = EmitLoadRegister(instr->InputAt(0), ip);
1032 __ push(input_reg); 1388 __ push(input_reg);
1033 CallRuntime(Runtime::kThrow, 1, instr); 1389 CallRuntime(Runtime::kThrow, 1, instr);
1034 1390
1035 if (FLAG_debug_code) { 1391 if (FLAG_debug_code) {
1036 __ stop("Unreachable code."); 1392 __ stop("Unreachable code.");
1037 } 1393 }
1038 } 1394 }
1039 1395
1040 1396
1041 void LCodeGen::DoAddI(LAddI* instr) { 1397 void LCodeGen::DoAddI(LAddI* instr) {
1042 LOperand* left = instr->left(); 1398 LOperand* left = instr->InputAt(0);
1043 LOperand* right = instr->right(); 1399 LOperand* right = instr->InputAt(1);
1044 ASSERT(left->Equals(instr->result())); 1400 ASSERT(left->Equals(instr->result()));
1045 1401
1046 Register right_reg = EmitLoadRegister(right, ip); 1402 Register right_reg = EmitLoadRegister(right, ip);
1047 __ add(ToRegister(left), ToRegister(left), Operand(right_reg), SetCC); 1403 __ add(ToRegister(left), ToRegister(left), Operand(right_reg), SetCC);
1048 1404
1049 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { 1405 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) {
1050 DeoptimizeIf(vs, instr->environment()); 1406 DeoptimizeIf(vs, instr->environment());
1051 } 1407 }
1052 } 1408 }
1053 1409
1054 1410
1055 void LCodeGen::DoArithmeticD(LArithmeticD* instr) { 1411 void LCodeGen::DoArithmeticD(LArithmeticD* instr) {
1056 DoubleRegister left = ToDoubleRegister(instr->left()); 1412 DoubleRegister left = ToDoubleRegister(instr->InputAt(0));
1057 DoubleRegister right = ToDoubleRegister(instr->right()); 1413 DoubleRegister right = ToDoubleRegister(instr->InputAt(1));
1058 switch (instr->op()) { 1414 switch (instr->op()) {
1059 case Token::ADD: 1415 case Token::ADD:
1060 __ vadd(left, left, right); 1416 __ vadd(left, left, right);
1061 break; 1417 break;
1062 case Token::SUB: 1418 case Token::SUB:
1063 __ vsub(left, left, right); 1419 __ vsub(left, left, right);
1064 break; 1420 break;
1065 case Token::MUL: 1421 case Token::MUL:
1066 __ vmul(left, left, right); 1422 __ vmul(left, left, right);
1067 break; 1423 break;
1068 case Token::DIV: 1424 case Token::DIV:
1069 __ vdiv(left, left, right); 1425 __ vdiv(left, left, right);
1070 break; 1426 break;
1071 case Token::MOD: { 1427 case Token::MOD: {
1072 Abort("DoArithmeticD unimplemented for MOD."); 1428 Abort("DoArithmeticD unimplemented for MOD.");
1073 break; 1429 break;
1074 } 1430 }
1075 default: 1431 default:
1076 UNREACHABLE(); 1432 UNREACHABLE();
1077 break; 1433 break;
1078 } 1434 }
1079 } 1435 }
1080 1436
1081 1437
1082 void LCodeGen::DoArithmeticT(LArithmeticT* instr) { 1438 void LCodeGen::DoArithmeticT(LArithmeticT* instr) {
1083 ASSERT(ToRegister(instr->left()).is(r1)); 1439 ASSERT(ToRegister(instr->InputAt(0)).is(r1));
1084 ASSERT(ToRegister(instr->right()).is(r0)); 1440 ASSERT(ToRegister(instr->InputAt(1)).is(r0));
1085 ASSERT(ToRegister(instr->result()).is(r0)); 1441 ASSERT(ToRegister(instr->result()).is(r0));
1086 1442
1087 // TODO(regis): Implement TypeRecordingBinaryOpStub and replace current 1443 // TODO(regis): Implement TypeRecordingBinaryOpStub and replace current
1088 // GenericBinaryOpStub: 1444 // GenericBinaryOpStub:
1089 // TypeRecordingBinaryOpStub stub(instr->op(), NO_OVERWRITE); 1445 // TypeRecordingBinaryOpStub stub(instr->op(), NO_OVERWRITE);
1090 GenericBinaryOpStub stub(instr->op(), NO_OVERWRITE, r1, r0); 1446 GenericBinaryOpStub stub(instr->op(), NO_OVERWRITE, r1, r0);
1091 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); 1447 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
1092 } 1448 }
1093 1449
1094 1450
(...skipping 23 matching lines...) Expand all
1118 } 1474 }
1119 } 1475 }
1120 1476
1121 1477
1122 void LCodeGen::DoBranch(LBranch* instr) { 1478 void LCodeGen::DoBranch(LBranch* instr) {
1123 int true_block = chunk_->LookupDestination(instr->true_block_id()); 1479 int true_block = chunk_->LookupDestination(instr->true_block_id());
1124 int false_block = chunk_->LookupDestination(instr->false_block_id()); 1480 int false_block = chunk_->LookupDestination(instr->false_block_id());
1125 1481
1126 Representation r = instr->hydrogen()->representation(); 1482 Representation r = instr->hydrogen()->representation();
1127 if (r.IsInteger32()) { 1483 if (r.IsInteger32()) {
1128 Register reg = ToRegister(instr->input()); 1484 Register reg = ToRegister(instr->InputAt(0));
1129 __ cmp(reg, Operand(0)); 1485 __ cmp(reg, Operand(0));
1130 EmitBranch(true_block, false_block, nz); 1486 EmitBranch(true_block, false_block, ne);
1131 } else if (r.IsDouble()) { 1487 } else if (r.IsDouble()) {
1132 DoubleRegister reg = ToDoubleRegister(instr->input()); 1488 DoubleRegister reg = ToDoubleRegister(instr->InputAt(0));
1133 Register scratch = scratch0(); 1489 Register scratch = scratch0();
1134 1490
1135 // Test the double value. Zero and NaN are false. 1491 // Test the double value. Zero and NaN are false.
1136 __ VFPCompareAndLoadFlags(reg, 0.0, scratch); 1492 __ VFPCompareAndLoadFlags(reg, 0.0, scratch);
1137 __ tst(scratch, Operand(kVFPZConditionFlagBit | kVFPVConditionFlagBit)); 1493 __ tst(scratch, Operand(kVFPZConditionFlagBit | kVFPVConditionFlagBit));
1138 EmitBranch(true_block, false_block, ne); 1494 EmitBranch(true_block, false_block, ne);
1139 } else { 1495 } else {
1140 ASSERT(r.IsTagged()); 1496 ASSERT(r.IsTagged());
1141 Register reg = ToRegister(instr->input()); 1497 Register reg = ToRegister(instr->InputAt(0));
1142 if (instr->hydrogen()->type().IsBoolean()) { 1498 if (instr->hydrogen()->type().IsBoolean()) {
1143 __ LoadRoot(ip, Heap::kTrueValueRootIndex); 1499 __ LoadRoot(ip, Heap::kTrueValueRootIndex);
1144 __ cmp(reg, ip); 1500 __ cmp(reg, ip);
1145 EmitBranch(true_block, false_block, eq); 1501 EmitBranch(true_block, false_block, eq);
1146 } else { 1502 } else {
1147 Label* true_label = chunk_->GetAssemblyLabel(true_block); 1503 Label* true_label = chunk_->GetAssemblyLabel(true_block);
1148 Label* false_label = chunk_->GetAssemblyLabel(false_block); 1504 Label* false_label = chunk_->GetAssemblyLabel(false_block);
1149 1505
1150 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); 1506 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
1151 __ cmp(reg, ip); 1507 __ cmp(reg, ip);
(...skipping 26 matching lines...) Expand all
1178 1534
1179 // The conversion stub doesn't cause garbage collections so it's 1535 // The conversion stub doesn't cause garbage collections so it's
1180 // safe to not record a safepoint after the call. 1536 // safe to not record a safepoint after the call.
1181 __ bind(&call_stub); 1537 __ bind(&call_stub);
1182 ToBooleanStub stub(reg); 1538 ToBooleanStub stub(reg);
1183 RegList saved_regs = kJSCallerSaved | kCalleeSaved; 1539 RegList saved_regs = kJSCallerSaved | kCalleeSaved;
1184 __ stm(db_w, sp, saved_regs); 1540 __ stm(db_w, sp, saved_regs);
1185 __ CallStub(&stub); 1541 __ CallStub(&stub);
1186 __ cmp(reg, Operand(0)); 1542 __ cmp(reg, Operand(0));
1187 __ ldm(ia_w, sp, saved_regs); 1543 __ ldm(ia_w, sp, saved_regs);
1188 EmitBranch(true_block, false_block, nz); 1544 EmitBranch(true_block, false_block, ne);
1189 } 1545 }
1190 } 1546 }
1191 } 1547 }
1192 1548
1193 1549
1194 void LCodeGen::EmitGoto(int block, LDeferredCode* deferred_stack_check) { 1550 void LCodeGen::EmitGoto(int block, LDeferredCode* deferred_stack_check) {
1195 block = chunk_->LookupDestination(block); 1551 block = chunk_->LookupDestination(block);
1196 int next_block = GetNextEmittedBlock(current_block_); 1552 int next_block = GetNextEmittedBlock(current_block_);
1197 if (block != next_block) { 1553 if (block != next_block) {
1198 // Perform stack overflow check if this goto needs it before jumping. 1554 // Perform stack overflow check if this goto needs it before jumping.
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
1230 1586
1231 DeferredStackCheck* deferred = NULL; 1587 DeferredStackCheck* deferred = NULL;
1232 if (instr->include_stack_check()) { 1588 if (instr->include_stack_check()) {
1233 deferred = new DeferredStackCheck(this, instr); 1589 deferred = new DeferredStackCheck(this, instr);
1234 } 1590 }
1235 EmitGoto(instr->block_id(), deferred); 1591 EmitGoto(instr->block_id(), deferred);
1236 } 1592 }
1237 1593
1238 1594
1239 Condition LCodeGen::TokenToCondition(Token::Value op, bool is_unsigned) { 1595 Condition LCodeGen::TokenToCondition(Token::Value op, bool is_unsigned) {
1240 Condition cond = no_condition; 1596 Condition cond = kNoCondition;
1241 switch (op) { 1597 switch (op) {
1242 case Token::EQ: 1598 case Token::EQ:
1243 case Token::EQ_STRICT: 1599 case Token::EQ_STRICT:
1244 cond = eq; 1600 cond = eq;
1245 break; 1601 break;
1246 case Token::LT: 1602 case Token::LT:
1247 cond = is_unsigned ? lo : lt; 1603 cond = is_unsigned ? lo : lt;
1248 break; 1604 break;
1249 case Token::GT: 1605 case Token::GT:
1250 cond = is_unsigned ? hi : gt; 1606 cond = is_unsigned ? hi : gt;
(...skipping 23 matching lines...) Expand all
1274 Abort("DoCmpID unimplemented."); 1630 Abort("DoCmpID unimplemented.");
1275 } 1631 }
1276 1632
1277 1633
1278 void LCodeGen::DoCmpIDAndBranch(LCmpIDAndBranch* instr) { 1634 void LCodeGen::DoCmpIDAndBranch(LCmpIDAndBranch* instr) {
1279 Abort("DoCmpIDAndBranch unimplemented."); 1635 Abort("DoCmpIDAndBranch unimplemented.");
1280 } 1636 }
1281 1637
1282 1638
1283 void LCodeGen::DoCmpJSObjectEq(LCmpJSObjectEq* instr) { 1639 void LCodeGen::DoCmpJSObjectEq(LCmpJSObjectEq* instr) {
1284 Register left = ToRegister(instr->left()); 1640 Register left = ToRegister(instr->InputAt(0));
1285 Register right = ToRegister(instr->right()); 1641 Register right = ToRegister(instr->InputAt(1));
1286 Register result = ToRegister(instr->result()); 1642 Register result = ToRegister(instr->result());
1287 1643
1288 __ cmp(left, Operand(right)); 1644 __ cmp(left, Operand(right));
1289 __ LoadRoot(result, Heap::kTrueValueRootIndex, eq); 1645 __ LoadRoot(result, Heap::kTrueValueRootIndex, eq);
1290 __ LoadRoot(result, Heap::kFalseValueRootIndex, ne); 1646 __ LoadRoot(result, Heap::kFalseValueRootIndex, ne);
1291 Abort("DoCmpJSObjectEq untested.");
1292 } 1647 }
1293 1648
1294 1649
1295 void LCodeGen::DoCmpJSObjectEqAndBranch(LCmpJSObjectEqAndBranch* instr) { 1650 void LCodeGen::DoCmpJSObjectEqAndBranch(LCmpJSObjectEqAndBranch* instr) {
1296 Abort("DoCmpJSObjectEqAndBranch unimplemented."); 1651 Register left = ToRegister(instr->InputAt(0));
1652 Register right = ToRegister(instr->InputAt(1));
1653 int false_block = chunk_->LookupDestination(instr->false_block_id());
1654 int true_block = chunk_->LookupDestination(instr->true_block_id());
1655
1656 __ cmp(left, Operand(right));
1657 EmitBranch(true_block, false_block, eq);
1297 } 1658 }
1298 1659
1299 1660
1300 void LCodeGen::DoIsNull(LIsNull* instr) { 1661 void LCodeGen::DoIsNull(LIsNull* instr) {
1301 Register reg = ToRegister(instr->input()); 1662 Register reg = ToRegister(instr->InputAt(0));
1302 Register result = ToRegister(instr->result()); 1663 Register result = ToRegister(instr->result());
1303 1664
1304 __ LoadRoot(ip, Heap::kNullValueRootIndex); 1665 __ LoadRoot(ip, Heap::kNullValueRootIndex);
1305 __ cmp(reg, ip); 1666 __ cmp(reg, ip);
1306 if (instr->is_strict()) { 1667 if (instr->is_strict()) {
1307 __ LoadRoot(result, Heap::kTrueValueRootIndex, eq); 1668 __ LoadRoot(result, Heap::kTrueValueRootIndex, eq);
1308 __ LoadRoot(result, Heap::kFalseValueRootIndex, ne); 1669 __ LoadRoot(result, Heap::kFalseValueRootIndex, ne);
1309 } else { 1670 } else {
1310 Label true_value, false_value, done; 1671 Label true_value, false_value, done;
1311 __ b(eq, &true_value); 1672 __ b(eq, &true_value);
(...skipping 14 matching lines...) Expand all
1326 __ jmp(&done); 1687 __ jmp(&done);
1327 __ bind(&true_value); 1688 __ bind(&true_value);
1328 __ LoadRoot(result, Heap::kTrueValueRootIndex); 1689 __ LoadRoot(result, Heap::kTrueValueRootIndex);
1329 __ bind(&done); 1690 __ bind(&done);
1330 } 1691 }
1331 } 1692 }
1332 1693
1333 1694
1334 void LCodeGen::DoIsNullAndBranch(LIsNullAndBranch* instr) { 1695 void LCodeGen::DoIsNullAndBranch(LIsNullAndBranch* instr) {
1335 Register scratch = scratch0(); 1696 Register scratch = scratch0();
1336 Register reg = ToRegister(instr->input()); 1697 Register reg = ToRegister(instr->InputAt(0));
1337 1698
1338 // TODO(fsc): If the expression is known to be a smi, then it's 1699 // TODO(fsc): If the expression is known to be a smi, then it's
1339 // definitely not null. Jump to the false block. 1700 // definitely not null. Jump to the false block.
1340 1701
1341 int true_block = chunk_->LookupDestination(instr->true_block_id()); 1702 int true_block = chunk_->LookupDestination(instr->true_block_id());
1342 int false_block = chunk_->LookupDestination(instr->false_block_id()); 1703 int false_block = chunk_->LookupDestination(instr->false_block_id());
1343 1704
1344 __ LoadRoot(ip, Heap::kNullValueRootIndex); 1705 __ LoadRoot(ip, Heap::kNullValueRootIndex);
1345 __ cmp(reg, ip); 1706 __ cmp(reg, ip);
1346 if (instr->is_strict()) { 1707 if (instr->is_strict()) {
(...skipping 15 matching lines...) Expand all
1362 EmitBranch(true_block, false_block, ne); 1723 EmitBranch(true_block, false_block, ne);
1363 } 1724 }
1364 } 1725 }
1365 1726
1366 1727
1367 Condition LCodeGen::EmitIsObject(Register input, 1728 Condition LCodeGen::EmitIsObject(Register input,
1368 Register temp1, 1729 Register temp1,
1369 Register temp2, 1730 Register temp2,
1370 Label* is_not_object, 1731 Label* is_not_object,
1371 Label* is_object) { 1732 Label* is_object) {
1372 Abort("EmitIsObject unimplemented."); 1733 __ JumpIfSmi(input, is_not_object);
1373 return ne; 1734
1735 __ LoadRoot(temp1, Heap::kNullValueRootIndex);
1736 __ cmp(input, temp1);
1737 __ b(eq, is_object);
1738
1739 // Load map.
1740 __ ldr(temp1, FieldMemOperand(input, HeapObject::kMapOffset));
1741 // Undetectable objects behave like undefined.
1742 __ ldrb(temp2, FieldMemOperand(temp1, Map::kBitFieldOffset));
1743 __ tst(temp2, Operand(1 << Map::kIsUndetectable));
1744 __ b(ne, is_not_object);
1745
1746 // Load instance type and check that it is in object type range.
1747 __ ldrb(temp2, FieldMemOperand(temp1, Map::kInstanceTypeOffset));
1748 __ cmp(temp2, Operand(FIRST_JS_OBJECT_TYPE));
1749 __ b(lt, is_not_object);
1750 __ cmp(temp2, Operand(LAST_JS_OBJECT_TYPE));
1751 return le;
1374 } 1752 }
1375 1753
1376 1754
1377 void LCodeGen::DoIsObject(LIsObject* instr) { 1755 void LCodeGen::DoIsObject(LIsObject* instr) {
1378 Abort("DoIsObject unimplemented."); 1756 Register reg = ToRegister(instr->InputAt(0));
1757 Register result = ToRegister(instr->result());
1758 Register temp = scratch0();
1759 Label is_false, is_true, done;
1760
1761 Condition true_cond = EmitIsObject(reg, result, temp, &is_false, &is_true);
1762 __ b(true_cond, &is_true);
1763
1764 __ bind(&is_false);
1765 __ LoadRoot(result, Heap::kFalseValueRootIndex);
1766 __ b(&done);
1767
1768 __ bind(&is_true);
1769 __ LoadRoot(result, Heap::kTrueValueRootIndex);
1770
1771 __ bind(&done);
1379 } 1772 }
1380 1773
1381 1774
1382 void LCodeGen::DoIsObjectAndBranch(LIsObjectAndBranch* instr) { 1775 void LCodeGen::DoIsObjectAndBranch(LIsObjectAndBranch* instr) {
1383 Abort("DoIsObjectAndBranch unimplemented."); 1776 Register reg = ToRegister(instr->InputAt(0));
1777 Register temp1 = ToRegister(instr->TempAt(0));
1778 Register temp2 = scratch0();
1779
1780 int true_block = chunk_->LookupDestination(instr->true_block_id());
1781 int false_block = chunk_->LookupDestination(instr->false_block_id());
1782 Label* true_label = chunk_->GetAssemblyLabel(true_block);
1783 Label* false_label = chunk_->GetAssemblyLabel(false_block);
1784
1785 Condition true_cond =
1786 EmitIsObject(reg, temp1, temp2, false_label, true_label);
1787
1788 EmitBranch(true_block, false_block, true_cond);
1384 } 1789 }
1385 1790
1386 1791
1387 void LCodeGen::DoIsSmi(LIsSmi* instr) { 1792 void LCodeGen::DoIsSmi(LIsSmi* instr) {
1388 ASSERT(instr->hydrogen()->value()->representation().IsTagged()); 1793 ASSERT(instr->hydrogen()->value()->representation().IsTagged());
1389 Register result = ToRegister(instr->result()); 1794 Register result = ToRegister(instr->result());
1390 Register input_reg = EmitLoadRegister(instr->input(), ip); 1795 Register input_reg = EmitLoadRegister(instr->InputAt(0), ip);
1391 __ tst(input_reg, Operand(kSmiTagMask)); 1796 __ tst(input_reg, Operand(kSmiTagMask));
1392 __ LoadRoot(result, Heap::kTrueValueRootIndex); 1797 __ LoadRoot(result, Heap::kTrueValueRootIndex);
1393 Label done; 1798 Label done;
1394 __ b(eq, &done); 1799 __ b(eq, &done);
1395 __ LoadRoot(result, Heap::kFalseValueRootIndex); 1800 __ LoadRoot(result, Heap::kFalseValueRootIndex);
1396 __ bind(&done); 1801 __ bind(&done);
1397 } 1802 }
1398 1803
1399 1804
1400 void LCodeGen::DoIsSmiAndBranch(LIsSmiAndBranch* instr) { 1805 void LCodeGen::DoIsSmiAndBranch(LIsSmiAndBranch* instr) {
1401 int true_block = chunk_->LookupDestination(instr->true_block_id()); 1806 int true_block = chunk_->LookupDestination(instr->true_block_id());
1402 int false_block = chunk_->LookupDestination(instr->false_block_id()); 1807 int false_block = chunk_->LookupDestination(instr->false_block_id());
1403 1808
1404 Register input_reg = EmitLoadRegister(instr->input(), ip); 1809 Register input_reg = EmitLoadRegister(instr->InputAt(0), ip);
1405 __ tst(input_reg, Operand(kSmiTagMask)); 1810 __ tst(input_reg, Operand(kSmiTagMask));
1406 EmitBranch(true_block, false_block, eq); 1811 EmitBranch(true_block, false_block, eq);
1407 } 1812 }
1408 1813
1409 1814
1410 InstanceType LHasInstanceType::TestType() { 1815 static InstanceType TestType(HHasInstanceType* instr) {
1411 InstanceType from = hydrogen()->from(); 1816 InstanceType from = instr->from();
1412 InstanceType to = hydrogen()->to(); 1817 InstanceType to = instr->to();
1413 if (from == FIRST_TYPE) return to; 1818 if (from == FIRST_TYPE) return to;
1414 ASSERT(from == to || to == LAST_TYPE); 1819 ASSERT(from == to || to == LAST_TYPE);
1415 return from; 1820 return from;
1416 } 1821 }
1417 1822
1418 1823
1419 Condition LHasInstanceType::BranchCondition() { 1824 static Condition BranchCondition(HHasInstanceType* instr) {
1420 InstanceType from = hydrogen()->from(); 1825 InstanceType from = instr->from();
1421 InstanceType to = hydrogen()->to(); 1826 InstanceType to = instr->to();
1422 if (from == to) return eq; 1827 if (from == to) return eq;
1423 if (to == LAST_TYPE) return hs; 1828 if (to == LAST_TYPE) return hs;
1424 if (from == FIRST_TYPE) return ls; 1829 if (from == FIRST_TYPE) return ls;
1425 UNREACHABLE(); 1830 UNREACHABLE();
1426 return eq; 1831 return eq;
1427 } 1832 }
1428 1833
1429 1834
1430 void LCodeGen::DoHasInstanceType(LHasInstanceType* instr) { 1835 void LCodeGen::DoHasInstanceType(LHasInstanceType* instr) {
1431 Abort("DoHasInstanceType unimplemented."); 1836 Register input = ToRegister(instr->InputAt(0));
1837 Register result = ToRegister(instr->result());
1838
1839 ASSERT(instr->hydrogen()->value()->representation().IsTagged());
1840 Label done;
1841 __ tst(input, Operand(kSmiTagMask));
1842 __ LoadRoot(result, Heap::kFalseValueRootIndex, eq);
1843 __ b(eq, &done);
1844 __ CompareObjectType(input, result, result, TestType(instr->hydrogen()));
1845 Condition cond = BranchCondition(instr->hydrogen());
1846 __ LoadRoot(result, Heap::kTrueValueRootIndex, cond);
1847 __ LoadRoot(result, Heap::kFalseValueRootIndex, NegateCondition(cond));
1848 __ bind(&done);
1432 } 1849 }
1433 1850
1434 1851
1435 void LCodeGen::DoHasInstanceTypeAndBranch(LHasInstanceTypeAndBranch* instr) { 1852 void LCodeGen::DoHasInstanceTypeAndBranch(LHasInstanceTypeAndBranch* instr) {
1436 Register scratch = scratch0(); 1853 Register scratch = scratch0();
1437 Register input = ToRegister(instr->input()); 1854 Register input = ToRegister(instr->InputAt(0));
1438 1855
1439 int true_block = chunk_->LookupDestination(instr->true_block_id()); 1856 int true_block = chunk_->LookupDestination(instr->true_block_id());
1440 int false_block = chunk_->LookupDestination(instr->false_block_id()); 1857 int false_block = chunk_->LookupDestination(instr->false_block_id());
1441 1858
1442 Label* false_label = chunk_->GetAssemblyLabel(false_block); 1859 Label* false_label = chunk_->GetAssemblyLabel(false_block);
1443 1860
1444 __ tst(input, Operand(kSmiTagMask)); 1861 __ tst(input, Operand(kSmiTagMask));
1445 __ b(eq, false_label); 1862 __ b(eq, false_label);
1446 1863
1447 __ CompareObjectType(input, scratch, scratch, instr->TestType()); 1864 __ CompareObjectType(input, scratch, scratch, TestType(instr->hydrogen()));
1448 EmitBranch(true_block, false_block, instr->BranchCondition()); 1865 EmitBranch(true_block, false_block, BranchCondition(instr->hydrogen()));
1449 } 1866 }
1450 1867
1451 1868
1452 void LCodeGen::DoHasCachedArrayIndex(LHasCachedArrayIndex* instr) { 1869 void LCodeGen::DoHasCachedArrayIndex(LHasCachedArrayIndex* instr) {
1453 Abort("DoHasCachedArrayIndex unimplemented."); 1870 Abort("DoHasCachedArrayIndex unimplemented.");
1454 } 1871 }
1455 1872
1456 1873
1457 void LCodeGen::DoHasCachedArrayIndexAndBranch( 1874 void LCodeGen::DoHasCachedArrayIndexAndBranch(
1458 LHasCachedArrayIndexAndBranch* instr) { 1875 LHasCachedArrayIndexAndBranch* instr) {
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
1511 // booted. This routine isn't expected to work for random API-created 1928 // booted. This routine isn't expected to work for random API-created
1512 // classes and it doesn't have to because you can't access it with natives 1929 // classes and it doesn't have to because you can't access it with natives
1513 // syntax. Since both sides are symbols it is sufficient to use an identity 1930 // syntax. Since both sides are symbols it is sufficient to use an identity
1514 // comparison. 1931 // comparison.
1515 __ cmp(temp, Operand(class_name)); 1932 __ cmp(temp, Operand(class_name));
1516 // End with the answer in flags. 1933 // End with the answer in flags.
1517 } 1934 }
1518 1935
1519 1936
1520 void LCodeGen::DoClassOfTest(LClassOfTest* instr) { 1937 void LCodeGen::DoClassOfTest(LClassOfTest* instr) {
1521 Register input = ToRegister(instr->input()); 1938 Register input = ToRegister(instr->InputAt(0));
1522 Register result = ToRegister(instr->result()); 1939 Register result = ToRegister(instr->result());
1523 ASSERT(input.is(result)); 1940 ASSERT(input.is(result));
1524 Handle<String> class_name = instr->hydrogen()->class_name(); 1941 Handle<String> class_name = instr->hydrogen()->class_name();
1525 1942
1526 Label done, is_true, is_false; 1943 Label done, is_true, is_false;
1527 1944
1528 EmitClassOfTest(&is_true, &is_false, class_name, input, scratch0(), input); 1945 EmitClassOfTest(&is_true, &is_false, class_name, input, scratch0(), input);
1529 __ b(ne, &is_false); 1946 __ b(ne, &is_false);
1530 1947
1531 __ bind(&is_true); 1948 __ bind(&is_true);
1532 __ LoadRoot(result, Heap::kTrueValueRootIndex); 1949 __ LoadRoot(result, Heap::kTrueValueRootIndex);
1533 __ jmp(&done); 1950 __ jmp(&done);
1534 1951
1535 __ bind(&is_false); 1952 __ bind(&is_false);
1536 __ LoadRoot(result, Heap::kFalseValueRootIndex); 1953 __ LoadRoot(result, Heap::kFalseValueRootIndex);
1537 __ bind(&done); 1954 __ bind(&done);
1538 } 1955 }
1539 1956
1540 1957
1541 void LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) { 1958 void LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) {
1542 Register input = ToRegister(instr->input()); 1959 Register input = ToRegister(instr->InputAt(0));
1543 Register temp = scratch0(); 1960 Register temp = scratch0();
1544 Register temp2 = ToRegister(instr->temporary()); 1961 Register temp2 = ToRegister(instr->TempAt(0));
1545 Handle<String> class_name = instr->hydrogen()->class_name(); 1962 Handle<String> class_name = instr->hydrogen()->class_name();
1546 1963
1547 int true_block = chunk_->LookupDestination(instr->true_block_id()); 1964 int true_block = chunk_->LookupDestination(instr->true_block_id());
1548 int false_block = chunk_->LookupDestination(instr->false_block_id()); 1965 int false_block = chunk_->LookupDestination(instr->false_block_id());
1549 1966
1550 Label* true_label = chunk_->GetAssemblyLabel(true_block); 1967 Label* true_label = chunk_->GetAssemblyLabel(true_block);
1551 Label* false_label = chunk_->GetAssemblyLabel(false_block); 1968 Label* false_label = chunk_->GetAssemblyLabel(false_block);
1552 1969
1553 EmitClassOfTest(true_label, false_label, class_name, input, temp, temp2); 1970 EmitClassOfTest(true_label, false_label, class_name, input, temp, temp2);
1554 1971
1555 EmitBranch(true_block, false_block, eq); 1972 EmitBranch(true_block, false_block, eq);
1556 } 1973 }
1557 1974
1558 1975
1559 void LCodeGen::DoCmpMapAndBranch(LCmpMapAndBranch* instr) { 1976 void LCodeGen::DoCmpMapAndBranch(LCmpMapAndBranch* instr) {
1560 Register reg = ToRegister(instr->input()); 1977 Register reg = ToRegister(instr->InputAt(0));
1561 Register temp = ToRegister(instr->temp()); 1978 Register temp = ToRegister(instr->TempAt(0));
1562 int true_block = instr->true_block_id(); 1979 int true_block = instr->true_block_id();
1563 int false_block = instr->false_block_id(); 1980 int false_block = instr->false_block_id();
1564 1981
1565 __ ldr(temp, FieldMemOperand(reg, HeapObject::kMapOffset)); 1982 __ ldr(temp, FieldMemOperand(reg, HeapObject::kMapOffset));
1566 __ cmp(temp, Operand(instr->map())); 1983 __ cmp(temp, Operand(instr->map()));
1567 EmitBranch(true_block, false_block, eq); 1984 EmitBranch(true_block, false_block, eq);
1568 } 1985 }
1569 1986
1570 1987
1571 void LCodeGen::DoInstanceOf(LInstanceOf* instr) { 1988 void LCodeGen::DoInstanceOf(LInstanceOf* instr) {
1572 ASSERT(ToRegister(instr->left()).is(r0)); // Object is in r0. 1989 ASSERT(ToRegister(instr->InputAt(0)).is(r0)); // Object is in r0.
1573 ASSERT(ToRegister(instr->right()).is(r1)); // Function is in r1. 1990 ASSERT(ToRegister(instr->InputAt(1)).is(r1)); // Function is in r1.
1574 1991
1575 InstanceofStub stub(InstanceofStub::kArgsInRegisters); 1992 InstanceofStub stub(InstanceofStub::kArgsInRegisters);
1576 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); 1993 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
1577 1994
1578 Label true_value, done; 1995 Label true_value, done;
1579 __ tst(r0, r0); 1996 __ tst(r0, r0);
1580 __ mov(r0, Operand(FACTORY->false_value()), LeaveCC, ne); 1997 __ mov(r0, Operand(FACTORY->false_value()), LeaveCC, ne);
1581 __ mov(r0, Operand(FACTORY->true_value()), LeaveCC, eq); 1998 __ mov(r0, Operand(FACTORY->true_value()), LeaveCC, eq);
1582 } 1999 }
1583 2000
1584 2001
1585 void LCodeGen::DoInstanceOfAndBranch(LInstanceOfAndBranch* instr) { 2002 void LCodeGen::DoInstanceOfAndBranch(LInstanceOfAndBranch* instr) {
1586 Abort("DoInstanceOfAndBranch unimplemented."); 2003 Abort("DoInstanceOfAndBranch unimplemented.");
1587 } 2004 }
1588 2005
1589 2006
1590 void LCodeGen::DoInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr) { 2007 void LCodeGen::DoInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr) {
1591 Abort("DoInstanceOfKnownGlobal unimplemented."); 2008 class DeferredInstanceOfKnownGlobal: public LDeferredCode {
2009 public:
2010 DeferredInstanceOfKnownGlobal(LCodeGen* codegen,
2011 LInstanceOfKnownGlobal* instr)
2012 : LDeferredCode(codegen), instr_(instr) { }
2013 virtual void Generate() {
2014 codegen()->DoDeferredLInstanceOfKnownGlobal(instr_, &map_check_);
2015 }
2016
2017 Label* map_check() { return &map_check_; }
2018
2019 private:
2020 LInstanceOfKnownGlobal* instr_;
2021 Label map_check_;
2022 };
2023
2024 DeferredInstanceOfKnownGlobal* deferred;
2025 deferred = new DeferredInstanceOfKnownGlobal(this, instr);
2026
2027 Label done, false_result;
2028 Register object = ToRegister(instr->InputAt(0));
2029 Register temp = ToRegister(instr->TempAt(0));
2030 Register result = ToRegister(instr->result());
2031
2032 ASSERT(object.is(r0));
2033 ASSERT(result.is(r0));
2034
2035 // A Smi is not instance of anything.
2036 __ JumpIfSmi(object, &false_result);
2037
2038 // This is the inlined call site instanceof cache. The two occurences of the
2039 // hole value will be patched to the last map/result pair generated by the
2040 // instanceof stub.
2041 Label cache_miss;
2042 Register map = temp;
2043 __ ldr(map, FieldMemOperand(object, HeapObject::kMapOffset));
2044 __ bind(deferred->map_check()); // Label for calculating code patching.
2045 // We use Factory::the_hole_value() on purpose instead of loading from the
2046 // root array to force relocation to be able to later patch with
2047 // the cached map.
2048 __ mov(ip, Operand(FACTORY->the_hole_value()));
2049 __ cmp(map, Operand(ip));
2050 __ b(ne, &cache_miss);
2051 // We use Factory::the_hole_value() on purpose instead of loading from the
2052 // root array to force relocation to be able to later patch
2053 // with true or false.
2054 __ mov(result, Operand(FACTORY->the_hole_value()));
2055 __ b(&done);
2056
2057 // The inlined call site cache did not match. Check null and string before
2058 // calling the deferred code.
2059 __ bind(&cache_miss);
2060 // Null is not instance of anything.
2061 __ LoadRoot(ip, Heap::kNullValueRootIndex);
2062 __ cmp(object, Operand(ip));
2063 __ b(eq, &false_result);
2064
2065 // String values is not instance of anything.
2066 Condition is_string = masm_->IsObjectStringType(object, temp);
2067 __ b(is_string, &false_result);
2068
2069 // Go to the deferred code.
2070 __ b(deferred->entry());
2071
2072 __ bind(&false_result);
2073 __ LoadRoot(result, Heap::kFalseValueRootIndex);
2074
2075 // Here result has either true or false. Deferred code also produces true or
2076 // false object.
2077 __ bind(deferred->exit());
2078 __ bind(&done);
2079 }
2080
2081
2082 void LCodeGen::DoDeferredLInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr,
2083 Label* map_check) {
2084 Register result = ToRegister(instr->result());
2085 ASSERT(result.is(r0));
2086
2087 InstanceofStub::Flags flags = InstanceofStub::kNoFlags;
2088 flags = static_cast<InstanceofStub::Flags>(
2089 flags | InstanceofStub::kArgsInRegisters);
2090 flags = static_cast<InstanceofStub::Flags>(
2091 flags | InstanceofStub::kCallSiteInlineCheck);
2092 flags = static_cast<InstanceofStub::Flags>(
2093 flags | InstanceofStub::kReturnTrueFalseObject);
2094 InstanceofStub stub(flags);
2095
2096 __ PushSafepointRegisters();
2097
2098 // Get the temp register reserved by the instruction. This needs to be r4 as
2099 // its slot of the pushing of safepoint registers is used to communicate the
2100 // offset to the location of the map check.
2101 Register temp = ToRegister(instr->TempAt(0));
2102 ASSERT(temp.is(r4));
2103 __ mov(InstanceofStub::right(), Operand(instr->function()));
2104 static const int kAdditionalDelta = 4;
2105 int delta = masm_->InstructionsGeneratedSince(map_check) + kAdditionalDelta;
2106 Label before_push_delta;
2107 __ bind(&before_push_delta);
2108 __ BlockConstPoolFor(kAdditionalDelta);
2109 __ mov(temp, Operand(delta * kPointerSize));
2110 __ StoreToSafepointRegisterSlot(temp);
2111 __ Call(stub.GetCode(), RelocInfo::CODE_TARGET);
2112 ASSERT_EQ(kAdditionalDelta,
2113 masm_->InstructionsGeneratedSince(&before_push_delta));
2114 RecordSafepointWithRegisters(
2115 instr->pointer_map(), 0, Safepoint::kNoDeoptimizationIndex);
2116 // Put the result value into the result register slot and
2117 // restore all registers.
2118 __ StoreToSafepointRegisterSlot(result);
2119
2120 __ PopSafepointRegisters();
1592 } 2121 }
1593 2122
1594 2123
1595 static Condition ComputeCompareCondition(Token::Value op) { 2124 static Condition ComputeCompareCondition(Token::Value op) {
1596 switch (op) { 2125 switch (op) {
1597 case Token::EQ_STRICT: 2126 case Token::EQ_STRICT:
1598 case Token::EQ: 2127 case Token::EQ:
1599 return eq; 2128 return eq;
1600 case Token::LT: 2129 case Token::LT:
1601 return lt; 2130 return lt;
1602 case Token::GT: 2131 case Token::GT:
1603 return gt; 2132 return gt;
1604 case Token::LTE: 2133 case Token::LTE:
1605 return le; 2134 return le;
1606 case Token::GTE: 2135 case Token::GTE:
1607 return ge; 2136 return ge;
1608 default: 2137 default:
1609 UNREACHABLE(); 2138 UNREACHABLE();
1610 return no_condition; 2139 return kNoCondition;
1611 } 2140 }
1612 } 2141 }
1613 2142
1614 2143
1615 void LCodeGen::DoCmpT(LCmpT* instr) { 2144 void LCodeGen::DoCmpT(LCmpT* instr) {
1616 Token::Value op = instr->op(); 2145 Token::Value op = instr->op();
1617 2146
1618 Handle<Code> ic = CompareIC::GetUninitialized(op); 2147 Handle<Code> ic = CompareIC::GetUninitialized(op);
1619 CallCode(ic, RelocInfo::CODE_TARGET, instr); 2148 CallCode(ic, RelocInfo::CODE_TARGET, instr);
1620 2149
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
1658 __ ldr(result, FieldMemOperand(ip, JSGlobalPropertyCell::kValueOffset)); 2187 __ ldr(result, FieldMemOperand(ip, JSGlobalPropertyCell::kValueOffset));
1659 if (instr->hydrogen()->check_hole_value()) { 2188 if (instr->hydrogen()->check_hole_value()) {
1660 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); 2189 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
1661 __ cmp(result, ip); 2190 __ cmp(result, ip);
1662 DeoptimizeIf(eq, instr->environment()); 2191 DeoptimizeIf(eq, instr->environment());
1663 } 2192 }
1664 } 2193 }
1665 2194
1666 2195
1667 void LCodeGen::DoStoreGlobal(LStoreGlobal* instr) { 2196 void LCodeGen::DoStoreGlobal(LStoreGlobal* instr) {
1668 Register value = ToRegister(instr->input()); 2197 Register value = ToRegister(instr->InputAt(0));
1669 __ mov(ip, Operand(Handle<Object>(instr->hydrogen()->cell()))); 2198 __ mov(ip, Operand(Handle<Object>(instr->hydrogen()->cell())));
1670 __ str(value, FieldMemOperand(ip, JSGlobalPropertyCell::kValueOffset)); 2199 __ str(value, FieldMemOperand(ip, JSGlobalPropertyCell::kValueOffset));
1671 } 2200 }
1672 2201
1673 2202
2203 void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) {
2204 // TODO(antonm): load a context with a separate instruction.
2205 Register result = ToRegister(instr->result());
2206 __ LoadContext(result, instr->context_chain_length());
2207 __ ldr(result, ContextOperand(result, instr->slot_index()));
2208 }
2209
2210
1674 void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) { 2211 void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) {
1675 Register object = ToRegister(instr->input()); 2212 Register object = ToRegister(instr->InputAt(0));
1676 Register result = ToRegister(instr->result()); 2213 Register result = ToRegister(instr->result());
1677 if (instr->hydrogen()->is_in_object()) { 2214 if (instr->hydrogen()->is_in_object()) {
1678 __ ldr(result, FieldMemOperand(object, instr->hydrogen()->offset())); 2215 __ ldr(result, FieldMemOperand(object, instr->hydrogen()->offset()));
1679 } else { 2216 } else {
1680 __ ldr(result, FieldMemOperand(object, JSObject::kPropertiesOffset)); 2217 __ ldr(result, FieldMemOperand(object, JSObject::kPropertiesOffset));
1681 __ ldr(result, FieldMemOperand(result, instr->hydrogen()->offset())); 2218 __ ldr(result, FieldMemOperand(result, instr->hydrogen()->offset()));
1682 } 2219 }
1683 } 2220 }
1684 2221
1685 2222
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
1733 // in initial map. 2270 // in initial map.
1734 __ bind(&non_instance); 2271 __ bind(&non_instance);
1735 __ ldr(result, FieldMemOperand(result, Map::kConstructorOffset)); 2272 __ ldr(result, FieldMemOperand(result, Map::kConstructorOffset));
1736 2273
1737 // All done. 2274 // All done.
1738 __ bind(&done); 2275 __ bind(&done);
1739 } 2276 }
1740 2277
1741 2278
1742 void LCodeGen::DoLoadElements(LLoadElements* instr) { 2279 void LCodeGen::DoLoadElements(LLoadElements* instr) {
1743 ASSERT(instr->result()->Equals(instr->input())); 2280 ASSERT(instr->result()->Equals(instr->InputAt(0)));
1744 Register reg = ToRegister(instr->input()); 2281 Register reg = ToRegister(instr->InputAt(0));
1745 Register scratch = scratch0(); 2282 Register scratch = scratch0();
1746 2283
1747 __ ldr(reg, FieldMemOperand(reg, JSObject::kElementsOffset)); 2284 __ ldr(reg, FieldMemOperand(reg, JSObject::kElementsOffset));
1748 if (FLAG_debug_code) { 2285 if (FLAG_debug_code) {
1749 Label done; 2286 Label done;
1750 __ ldr(scratch, FieldMemOperand(reg, HeapObject::kMapOffset)); 2287 __ ldr(scratch, FieldMemOperand(reg, HeapObject::kMapOffset));
1751 __ LoadRoot(ip, Heap::kFixedArrayMapRootIndex); 2288 __ LoadRoot(ip, Heap::kFixedArrayMapRootIndex);
1752 __ cmp(scratch, ip); 2289 __ cmp(scratch, ip);
1753 __ b(eq, &done); 2290 __ b(eq, &done);
1754 __ LoadRoot(ip, Heap::kFixedCOWArrayMapRootIndex); 2291 __ LoadRoot(ip, Heap::kFixedCOWArrayMapRootIndex);
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
1816 __ cmp(result, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); 2353 __ cmp(result, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
1817 2354
1818 // Result is the frame pointer for the frame if not adapted and for the real 2355 // Result is the frame pointer for the frame if not adapted and for the real
1819 // frame below the adaptor frame if adapted. 2356 // frame below the adaptor frame if adapted.
1820 __ mov(result, fp, LeaveCC, ne); 2357 __ mov(result, fp, LeaveCC, ne);
1821 __ mov(result, scratch, LeaveCC, eq); 2358 __ mov(result, scratch, LeaveCC, eq);
1822 } 2359 }
1823 2360
1824 2361
1825 void LCodeGen::DoArgumentsLength(LArgumentsLength* instr) { 2362 void LCodeGen::DoArgumentsLength(LArgumentsLength* instr) {
1826 Register elem = ToRegister(instr->input()); 2363 Register elem = ToRegister(instr->InputAt(0));
1827 Register result = ToRegister(instr->result()); 2364 Register result = ToRegister(instr->result());
1828 2365
1829 Label done; 2366 Label done;
1830 2367
1831 // If no arguments adaptor frame the number of arguments is fixed. 2368 // If no arguments adaptor frame the number of arguments is fixed.
1832 __ cmp(fp, elem); 2369 __ cmp(fp, elem);
1833 __ mov(result, Operand(scope()->num_parameters())); 2370 __ mov(result, Operand(scope()->num_parameters()));
1834 __ b(eq, &done); 2371 __ b(eq, &done);
1835 2372
1836 // Arguments adaptor frame present. Get argument length from there. 2373 // Arguments adaptor frame present. Get argument length from there.
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
1901 // which is r0, as expected by InvokeFunction. 2438 // which is r0, as expected by InvokeFunction.
1902 v8::internal::ParameterCount actual(receiver); 2439 v8::internal::ParameterCount actual(receiver);
1903 SafepointGenerator safepoint_generator(this, 2440 SafepointGenerator safepoint_generator(this,
1904 instr->pointer_map(), 2441 instr->pointer_map(),
1905 Safepoint::kNoDeoptimizationIndex); 2442 Safepoint::kNoDeoptimizationIndex);
1906 __ InvokeFunction(function, actual, CALL_FUNCTION, &safepoint_generator); 2443 __ InvokeFunction(function, actual, CALL_FUNCTION, &safepoint_generator);
1907 } 2444 }
1908 2445
1909 2446
1910 void LCodeGen::DoPushArgument(LPushArgument* instr) { 2447 void LCodeGen::DoPushArgument(LPushArgument* instr) {
1911 LOperand* argument = instr->input(); 2448 LOperand* argument = instr->InputAt(0);
1912 if (argument->IsDoubleRegister() || argument->IsDoubleStackSlot()) { 2449 if (argument->IsDoubleRegister() || argument->IsDoubleStackSlot()) {
1913 Abort("DoPushArgument not implemented for double type."); 2450 Abort("DoPushArgument not implemented for double type.");
1914 } else { 2451 } else {
1915 Register argument_reg = EmitLoadRegister(argument, ip); 2452 Register argument_reg = EmitLoadRegister(argument, ip);
1916 __ push(argument_reg); 2453 __ push(argument_reg);
1917 } 2454 }
1918 } 2455 }
1919 2456
1920 2457
1921 void LCodeGen::DoGlobalObject(LGlobalObject* instr) { 2458 void LCodeGen::DoGlobalObject(LGlobalObject* instr) {
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
1965 2502
1966 2503
1967 void LCodeGen::DoCallConstantFunction(LCallConstantFunction* instr) { 2504 void LCodeGen::DoCallConstantFunction(LCallConstantFunction* instr) {
1968 ASSERT(ToRegister(instr->result()).is(r0)); 2505 ASSERT(ToRegister(instr->result()).is(r0));
1969 __ mov(r1, Operand(instr->function())); 2506 __ mov(r1, Operand(instr->function()));
1970 CallKnownFunction(instr->function(), instr->arity(), instr); 2507 CallKnownFunction(instr->function(), instr->arity(), instr);
1971 } 2508 }
1972 2509
1973 2510
1974 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LUnaryMathOperation* instr) { 2511 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LUnaryMathOperation* instr) {
1975 Abort("DoDeferredMathAbsTaggedHeapNumber unimplemented."); 2512 Register input = ToRegister(instr->InputAt(0));
2513 Register scratch = scratch0();
2514
2515 // Deoptimize if not a heap number.
2516 __ ldr(scratch, FieldMemOperand(input, HeapObject::kMapOffset));
2517 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex);
2518 __ cmp(scratch, Operand(ip));
2519 DeoptimizeIf(ne, instr->environment());
2520
2521 Label done;
2522
2523 Label negative;
2524 __ ldr(scratch, FieldMemOperand(input, HeapNumber::kExponentOffset));
2525 // Check the sign of the argument. If the argument is positive, just
2526 // return it. We do not need to patch the stack since |input| and
2527 // |result| are the same register and |input| will be restored
2528 // unchanged by popping safepoint registers.
2529 __ tst(scratch, Operand(HeapNumber::kSignMask));
2530 __ b(ne, &negative);
2531 __ jmp(&done);
2532
2533 __ bind(&negative);
2534 // Preserve the value of all registers.
2535 __ PushSafepointRegisters();
2536
2537 Register tmp = input.is(r0) ? r1 : r0;
2538 Register tmp2 = input.is(r2) ? r3 : r2;
2539 Register tmp3 = input.is(r4) ? r5 : r4;
2540
2541 Label allocated, slow;
2542 __ LoadRoot(scratch, Heap::kHeapNumberMapRootIndex);
2543 __ AllocateHeapNumber(tmp, tmp2, tmp3, scratch, &slow);
2544 __ b(&allocated);
2545
2546 // Slow case: Call the runtime system to do the number allocation.
2547 __ bind(&slow);
2548
2549 __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber);
2550 RecordSafepointWithRegisters(
2551 instr->pointer_map(), 0, Safepoint::kNoDeoptimizationIndex);
2552 // Set the pointer to the new heap number in tmp.
2553 if (!tmp.is(r0)) __ mov(tmp, Operand(r0));
2554
2555 // Restore input_reg after call to runtime.
2556 MemOperand input_register_slot = masm()->SafepointRegisterSlot(input);
2557 __ ldr(input, input_register_slot);
2558
2559 __ bind(&allocated);
2560 __ ldr(tmp2, FieldMemOperand(input, HeapNumber::kExponentOffset));
2561 __ bic(tmp2, tmp2, Operand(HeapNumber::kSignMask));
2562 __ str(tmp2, FieldMemOperand(tmp, HeapNumber::kExponentOffset));
2563 __ ldr(tmp2, FieldMemOperand(input, HeapNumber::kMantissaOffset));
2564 __ str(tmp2, FieldMemOperand(tmp, HeapNumber::kMantissaOffset));
2565
2566 __ str(tmp, input_register_slot);
2567 __ PopSafepointRegisters();
2568
2569 __ bind(&done);
2570 }
2571
2572
2573 void LCodeGen::EmitIntegerMathAbs(LUnaryMathOperation* instr) {
2574 Label is_positive;
2575 uint32_t kSignMask = 0x80000000u;
2576 Register input = ToRegister(instr->InputAt(0));
2577 __ tst(input, Operand(kSignMask));
2578 __ b(eq, &is_positive);
2579 __ rsb(input, input, Operand(0), SetCC);
2580 // Deoptimize on overflow.
2581 DeoptimizeIf(vs, instr->environment());
2582 __ bind(&is_positive);
1976 } 2583 }
1977 2584
1978 2585
1979 void LCodeGen::DoMathAbs(LUnaryMathOperation* instr) { 2586 void LCodeGen::DoMathAbs(LUnaryMathOperation* instr) {
1980 Abort("DoMathAbs unimplemented."); 2587 // Class for deferred case.
2588 class DeferredMathAbsTaggedHeapNumber: public LDeferredCode {
2589 public:
2590 DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen,
2591 LUnaryMathOperation* instr)
2592 : LDeferredCode(codegen), instr_(instr) { }
2593 virtual void Generate() {
2594 codegen()->DoDeferredMathAbsTaggedHeapNumber(instr_);
2595 }
2596 private:
2597 LUnaryMathOperation* instr_;
2598 };
2599
2600 ASSERT(instr->InputAt(0)->Equals(instr->result()));
2601 Representation r = instr->hydrogen()->value()->representation();
2602 if (r.IsDouble()) {
2603 DwVfpRegister input = ToDoubleRegister(instr->InputAt(0));
2604 // __ vabs(input, input);
2605 Abort("Double DoMathAbs unimplemented");
2606 } else if (r.IsInteger32()) {
2607 EmitIntegerMathAbs(instr);
2608 } else {
2609 // Representation is tagged.
2610 DeferredMathAbsTaggedHeapNumber* deferred =
2611 new DeferredMathAbsTaggedHeapNumber(this, instr);
2612 Register input = ToRegister(instr->InputAt(0));
2613 // Smi check.
2614 __ JumpIfNotSmi(input, deferred->entry());
2615 // If smi, handle it directly.
2616 EmitIntegerMathAbs(instr);
2617 __ bind(deferred->exit());
2618 }
1981 } 2619 }
1982 2620
1983 2621
1984 void LCodeGen::DoMathFloor(LUnaryMathOperation* instr) { 2622 void LCodeGen::DoMathFloor(LUnaryMathOperation* instr) {
1985 DoubleRegister input = ToDoubleRegister(instr->input()); 2623 DoubleRegister input = ToDoubleRegister(instr->InputAt(0));
1986 Register result = ToRegister(instr->result()); 2624 Register result = ToRegister(instr->result());
1987 Register prev_fpscr = ToRegister(instr->temp()); 2625 Register prev_fpscr = ToRegister(instr->TempAt(0));
1988 SwVfpRegister single_scratch = single_scratch0(); 2626 SwVfpRegister single_scratch = double_scratch0().low();
1989 Register scratch = scratch0(); 2627 Register scratch = scratch0();
1990 2628
1991 // Set custom FPCSR: 2629 // Set custom FPCSR:
1992 // - Set rounding mode to "Round towards Minus Infinity". 2630 // - Set rounding mode to "Round towards Minus Infinity".
1993 // - Clear vfp cumulative exception flags. 2631 // - Clear vfp cumulative exception flags.
1994 // - Make sure Flush-to-zero mode control bit is unset. 2632 // - Make sure Flush-to-zero mode control bit is unset.
1995 __ vmrs(prev_fpscr); 2633 __ vmrs(prev_fpscr);
1996 __ bic(scratch, prev_fpscr, 2634 __ bic(scratch, prev_fpscr,
1997 Operand(kVFPExceptionMask | kVFPRoundingModeMask | kVFPFlushToZeroMask)); 2635 Operand(kVFPExceptionMask | kVFPRoundingModeMask | kVFPFlushToZeroMask));
1998 __ orr(scratch, scratch, Operand(kVFPRoundToMinusInfinityBits)); 2636 __ orr(scratch, scratch, Operand(kVFPRoundToMinusInfinityBits));
1999 __ vmsr(scratch); 2637 __ vmsr(scratch);
2000 2638
2001 // Convert the argument to an integer. 2639 // Convert the argument to an integer.
2002 __ vcvt_s32_f64(single_scratch, 2640 __ vcvt_s32_f64(single_scratch,
2003 input, 2641 input,
2004 Assembler::FPSCRRounding, 2642 Assembler::FPSCRRounding,
2005 al); 2643 al);
2006 2644
2007 // Retrieve FPSCR and check for vfp exceptions. 2645 // Retrieve FPSCR and check for vfp exceptions.
2008 __ vmrs(scratch); 2646 __ vmrs(scratch);
2009 // Restore FPSCR 2647 // Restore FPSCR
2010 __ vmsr(prev_fpscr); 2648 __ vmsr(prev_fpscr);
2011 __ tst(scratch, Operand(kVFPExceptionMask)); 2649 __ tst(scratch, Operand(kVFPExceptionMask));
2012 DeoptimizeIf(ne, instr->environment()); 2650 DeoptimizeIf(ne, instr->environment());
2013 2651
2014 // Move the result back to general purpose register r0. 2652 // Move the result back to general purpose register r0.
2015 __ vmov(result, single_scratch); 2653 __ vmov(result, single_scratch);
2654
2655 // Test for -0.
2656 Label done;
2657 __ cmp(result, Operand(0));
2658 __ b(ne, &done);
2659 __ vmov(scratch, input.high());
2660 __ tst(scratch, Operand(HeapNumber::kSignMask));
2661 DeoptimizeIf(ne, instr->environment());
2662 __ bind(&done);
2016 } 2663 }
2017 2664
2018 2665
2019 void LCodeGen::DoMathSqrt(LUnaryMathOperation* instr) { 2666 void LCodeGen::DoMathSqrt(LUnaryMathOperation* instr) {
2020 DoubleRegister input = ToDoubleRegister(instr->input()); 2667 DoubleRegister input = ToDoubleRegister(instr->InputAt(0));
2021 ASSERT(ToDoubleRegister(instr->result()).is(input)); 2668 ASSERT(ToDoubleRegister(instr->result()).is(input));
2022 __ vsqrt(input, input); 2669 __ vsqrt(input, input);
2023 } 2670 }
2024 2671
2025 2672
2026 void LCodeGen::DoUnaryMathOperation(LUnaryMathOperation* instr) { 2673 void LCodeGen::DoUnaryMathOperation(LUnaryMathOperation* instr) {
2027 switch (instr->op()) { 2674 switch (instr->op()) {
2028 case kMathAbs: 2675 case kMathAbs:
2029 DoMathAbs(instr); 2676 DoMathAbs(instr);
2030 break; 2677 break;
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
2091 2738
2092 2739
2093 void LCodeGen::DoCallKnownGlobal(LCallKnownGlobal* instr) { 2740 void LCodeGen::DoCallKnownGlobal(LCallKnownGlobal* instr) {
2094 ASSERT(ToRegister(instr->result()).is(r0)); 2741 ASSERT(ToRegister(instr->result()).is(r0));
2095 __ mov(r1, Operand(instr->target())); 2742 __ mov(r1, Operand(instr->target()));
2096 CallKnownFunction(instr->target(), instr->arity(), instr); 2743 CallKnownFunction(instr->target(), instr->arity(), instr);
2097 } 2744 }
2098 2745
2099 2746
2100 void LCodeGen::DoCallNew(LCallNew* instr) { 2747 void LCodeGen::DoCallNew(LCallNew* instr) {
2101 ASSERT(ToRegister(instr->input()).is(r1)); 2748 ASSERT(ToRegister(instr->InputAt(0)).is(r1));
2102 ASSERT(ToRegister(instr->result()).is(r0)); 2749 ASSERT(ToRegister(instr->result()).is(r0));
2103 2750
2104 Handle<Code> builtin(Isolate::Current()->builtins()-> 2751 Handle<Code> builtin(Isolate::Current()->builtins()->
2105 builtin(Builtins::JSConstructCall)); 2752 builtin(Builtins::JSConstructCall));
2106 __ mov(r0, Operand(instr->arity())); 2753 __ mov(r0, Operand(instr->arity()));
2107 CallCode(builtin, RelocInfo::CONSTRUCT_CALL, instr); 2754 CallCode(builtin, RelocInfo::CONSTRUCT_CALL, instr);
2108 } 2755 }
2109 2756
2110 2757
2111 void LCodeGen::DoCallRuntime(LCallRuntime* instr) { 2758 void LCodeGen::DoCallRuntime(LCallRuntime* instr) {
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
2193 ASSERT(ToRegister(instr->object()).is(r2)); 2840 ASSERT(ToRegister(instr->object()).is(r2));
2194 ASSERT(ToRegister(instr->key()).is(r1)); 2841 ASSERT(ToRegister(instr->key()).is(r1));
2195 ASSERT(ToRegister(instr->value()).is(r0)); 2842 ASSERT(ToRegister(instr->value()).is(r0));
2196 2843
2197 Handle<Code> ic(Isolate::Current()->builtins()-> 2844 Handle<Code> ic(Isolate::Current()->builtins()->
2198 builtin(Builtins::KeyedStoreIC_Initialize)); 2845 builtin(Builtins::KeyedStoreIC_Initialize));
2199 CallCode(ic, RelocInfo::CODE_TARGET, instr); 2846 CallCode(ic, RelocInfo::CODE_TARGET, instr);
2200 } 2847 }
2201 2848
2202 2849
2850 void LCodeGen::DoStringCharCodeAt(LStringCharCodeAt* instr) {
2851 class DeferredStringCharCodeAt: public LDeferredCode {
2852 public:
2853 DeferredStringCharCodeAt(LCodeGen* codegen, LStringCharCodeAt* instr)
2854 : LDeferredCode(codegen), instr_(instr) { }
2855 virtual void Generate() { codegen()->DoDeferredStringCharCodeAt(instr_); }
2856 private:
2857 LStringCharCodeAt* instr_;
2858 };
2859
2860 Register scratch = scratch0();
2861 Register string = ToRegister(instr->string());
2862 Register index = no_reg;
2863 int const_index = -1;
2864 if (instr->index()->IsConstantOperand()) {
2865 const_index = ToInteger32(LConstantOperand::cast(instr->index()));
2866 STATIC_ASSERT(String::kMaxLength <= Smi::kMaxValue);
2867 if (!Smi::IsValid(const_index)) {
2868 // Guaranteed to be out of bounds because of the assert above.
2869 // So the bounds check that must dominate this instruction must
2870 // have deoptimized already.
2871 if (FLAG_debug_code) {
2872 __ Abort("StringCharCodeAt: out of bounds index.");
2873 }
2874 // No code needs to be generated.
2875 return;
2876 }
2877 } else {
2878 index = ToRegister(instr->index());
2879 }
2880 Register result = ToRegister(instr->result());
2881
2882 DeferredStringCharCodeAt* deferred =
2883 new DeferredStringCharCodeAt(this, instr);
2884
2885 Label flat_string, ascii_string, done;
2886
2887 // Fetch the instance type of the receiver into result register.
2888 __ ldr(result, FieldMemOperand(string, HeapObject::kMapOffset));
2889 __ ldrb(result, FieldMemOperand(result, Map::kInstanceTypeOffset));
2890
2891 // We need special handling for non-flat strings.
2892 STATIC_ASSERT(kSeqStringTag == 0);
2893 __ tst(result, Operand(kStringRepresentationMask));
2894 __ b(eq, &flat_string);
2895
2896 // Handle non-flat strings.
2897 __ tst(result, Operand(kIsConsStringMask));
2898 __ b(eq, deferred->entry());
2899
2900 // ConsString.
2901 // Check whether the right hand side is the empty string (i.e. if
2902 // this is really a flat string in a cons string). If that is not
2903 // the case we would rather go to the runtime system now to flatten
2904 // the string.
2905 __ ldr(scratch, FieldMemOperand(string, ConsString::kSecondOffset));
2906 __ LoadRoot(ip, Heap::kEmptyStringRootIndex);
2907 __ cmp(scratch, ip);
2908 __ b(ne, deferred->entry());
2909 // Get the first of the two strings and load its instance type.
2910 __ ldr(string, FieldMemOperand(string, ConsString::kFirstOffset));
2911 __ ldr(result, FieldMemOperand(string, HeapObject::kMapOffset));
2912 __ ldrb(result, FieldMemOperand(result, Map::kInstanceTypeOffset));
2913 // If the first cons component is also non-flat, then go to runtime.
2914 STATIC_ASSERT(kSeqStringTag == 0);
2915 __ tst(result, Operand(kStringRepresentationMask));
2916 __ b(ne, deferred->entry());
2917
2918 // Check for 1-byte or 2-byte string.
2919 __ bind(&flat_string);
2920 STATIC_ASSERT(kAsciiStringTag != 0);
2921 __ tst(result, Operand(kStringEncodingMask));
2922 __ b(ne, &ascii_string);
2923
2924 // 2-byte string.
2925 // Load the 2-byte character code into the result register.
2926 STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize == 1);
2927 if (instr->index()->IsConstantOperand()) {
2928 __ ldrh(result,
2929 FieldMemOperand(string,
2930 SeqTwoByteString::kHeaderSize + 2 * const_index));
2931 } else {
2932 __ add(scratch,
2933 string,
2934 Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
2935 __ ldrh(result, MemOperand(scratch, index, LSL, 1));
2936 }
2937 __ jmp(&done);
2938
2939 // ASCII string.
2940 // Load the byte into the result register.
2941 __ bind(&ascii_string);
2942 if (instr->index()->IsConstantOperand()) {
2943 __ ldrb(result, FieldMemOperand(string,
2944 SeqAsciiString::kHeaderSize + const_index));
2945 } else {
2946 __ add(scratch,
2947 string,
2948 Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag));
2949 __ ldrb(result, MemOperand(scratch, index));
2950 }
2951 __ bind(&done);
2952 __ bind(deferred->exit());
2953 }
2954
2955
2956 void LCodeGen::DoDeferredStringCharCodeAt(LStringCharCodeAt* instr) {
2957 Register string = ToRegister(instr->string());
2958 Register result = ToRegister(instr->result());
2959 Register scratch = scratch0();
2960
2961 // TODO(3095996): Get rid of this. For now, we need to make the
2962 // result register contain a valid pointer because it is already
2963 // contained in the register pointer map.
2964 __ mov(result, Operand(0));
2965
2966 __ PushSafepointRegisters();
2967 __ push(string);
2968 // Push the index as a smi. This is safe because of the checks in
2969 // DoStringCharCodeAt above.
2970 if (instr->index()->IsConstantOperand()) {
2971 int const_index = ToInteger32(LConstantOperand::cast(instr->index()));
2972 __ mov(scratch, Operand(Smi::FromInt(const_index)));
2973 __ push(scratch);
2974 } else {
2975 Register index = ToRegister(instr->index());
2976 __ SmiTag(index);
2977 __ push(index);
2978 }
2979 __ CallRuntimeSaveDoubles(Runtime::kStringCharCodeAt);
2980 RecordSafepointWithRegisters(
2981 instr->pointer_map(), 2, Safepoint::kNoDeoptimizationIndex);
2982 if (FLAG_debug_code) {
2983 __ AbortIfNotSmi(r0);
2984 }
2985 __ SmiUntag(r0);
2986 MemOperand result_stack_slot = masm()->SafepointRegisterSlot(result);
2987 __ str(r0, result_stack_slot);
2988 __ PopSafepointRegisters();
2989 }
2990
2991
2992 void LCodeGen::DoStringLength(LStringLength* instr) {
2993 Register string = ToRegister(instr->InputAt(0));
2994 Register result = ToRegister(instr->result());
2995 __ ldr(result, FieldMemOperand(string, String::kLengthOffset));
2996 }
2997
2998
2203 void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) { 2999 void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) {
2204 Abort("DoInteger32ToDouble unimplemented."); 3000 LOperand* input = instr->InputAt(0);
3001 ASSERT(input->IsRegister() || input->IsStackSlot());
3002 LOperand* output = instr->result();
3003 ASSERT(output->IsDoubleRegister());
3004 SwVfpRegister single_scratch = double_scratch0().low();
3005 if (input->IsStackSlot()) {
3006 Register scratch = scratch0();
3007 __ ldr(scratch, ToMemOperand(input));
3008 __ vmov(single_scratch, scratch);
3009 } else {
3010 __ vmov(single_scratch, ToRegister(input));
3011 }
3012 __ vcvt_f64_s32(ToDoubleRegister(output), single_scratch);
2205 } 3013 }
2206 3014
2207 3015
2208 void LCodeGen::DoNumberTagI(LNumberTagI* instr) { 3016 void LCodeGen::DoNumberTagI(LNumberTagI* instr) {
2209 class DeferredNumberTagI: public LDeferredCode { 3017 class DeferredNumberTagI: public LDeferredCode {
2210 public: 3018 public:
2211 DeferredNumberTagI(LCodeGen* codegen, LNumberTagI* instr) 3019 DeferredNumberTagI(LCodeGen* codegen, LNumberTagI* instr)
2212 : LDeferredCode(codegen), instr_(instr) { } 3020 : LDeferredCode(codegen), instr_(instr) { }
2213 virtual void Generate() { codegen()->DoDeferredNumberTagI(instr_); } 3021 virtual void Generate() { codegen()->DoDeferredNumberTagI(instr_); }
2214 private: 3022 private:
2215 LNumberTagI* instr_; 3023 LNumberTagI* instr_;
2216 }; 3024 };
2217 3025
2218 LOperand* input = instr->input(); 3026 LOperand* input = instr->InputAt(0);
2219 ASSERT(input->IsRegister() && input->Equals(instr->result())); 3027 ASSERT(input->IsRegister() && input->Equals(instr->result()));
2220 Register reg = ToRegister(input); 3028 Register reg = ToRegister(input);
2221 3029
2222 DeferredNumberTagI* deferred = new DeferredNumberTagI(this, instr); 3030 DeferredNumberTagI* deferred = new DeferredNumberTagI(this, instr);
2223 __ SmiTag(reg, SetCC); 3031 __ SmiTag(reg, SetCC);
2224 __ b(vs, deferred->entry()); 3032 __ b(vs, deferred->entry());
2225 __ bind(deferred->exit()); 3033 __ bind(deferred->exit());
2226 } 3034 }
2227 3035
2228 3036
2229 void LCodeGen::DoDeferredNumberTagI(LNumberTagI* instr) { 3037 void LCodeGen::DoDeferredNumberTagI(LNumberTagI* instr) {
2230 Label slow; 3038 Label slow;
2231 Register reg = ToRegister(instr->input()); 3039 Register reg = ToRegister(instr->InputAt(0));
2232 DoubleRegister dbl_scratch = d0; 3040 DoubleRegister dbl_scratch = d0;
2233 SwVfpRegister flt_scratch = s0; 3041 SwVfpRegister flt_scratch = s0;
2234 3042
2235 // Preserve the value of all registers. 3043 // Preserve the value of all registers.
2236 __ PushSafepointRegisters(); 3044 __ PushSafepointRegisters();
2237 3045
2238 // There was overflow, so bits 30 and 31 of the original integer 3046 // There was overflow, so bits 30 and 31 of the original integer
2239 // disagree. Try to allocate a heap number in new space and store 3047 // disagree. Try to allocate a heap number in new space and store
2240 // the value in there. If that fails, call the runtime system. 3048 // the value in there. If that fails, call the runtime system.
2241 Label done; 3049 Label done;
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
2278 void LCodeGen::DoNumberTagD(LNumberTagD* instr) { 3086 void LCodeGen::DoNumberTagD(LNumberTagD* instr) {
2279 class DeferredNumberTagD: public LDeferredCode { 3087 class DeferredNumberTagD: public LDeferredCode {
2280 public: 3088 public:
2281 DeferredNumberTagD(LCodeGen* codegen, LNumberTagD* instr) 3089 DeferredNumberTagD(LCodeGen* codegen, LNumberTagD* instr)
2282 : LDeferredCode(codegen), instr_(instr) { } 3090 : LDeferredCode(codegen), instr_(instr) { }
2283 virtual void Generate() { codegen()->DoDeferredNumberTagD(instr_); } 3091 virtual void Generate() { codegen()->DoDeferredNumberTagD(instr_); }
2284 private: 3092 private:
2285 LNumberTagD* instr_; 3093 LNumberTagD* instr_;
2286 }; 3094 };
2287 3095
2288 DoubleRegister input_reg = ToDoubleRegister(instr->input()); 3096 DoubleRegister input_reg = ToDoubleRegister(instr->InputAt(0));
2289 Register scratch = scratch0(); 3097 Register scratch = scratch0();
2290 Register reg = ToRegister(instr->result()); 3098 Register reg = ToRegister(instr->result());
2291 Register temp1 = ToRegister(instr->temp1()); 3099 Register temp1 = ToRegister(instr->TempAt(0));
2292 Register temp2 = ToRegister(instr->temp2()); 3100 Register temp2 = ToRegister(instr->TempAt(1));
2293 3101
2294 DeferredNumberTagD* deferred = new DeferredNumberTagD(this, instr); 3102 DeferredNumberTagD* deferred = new DeferredNumberTagD(this, instr);
2295 if (FLAG_inline_new) { 3103 if (FLAG_inline_new) {
2296 __ LoadRoot(scratch, Heap::kHeapNumberMapRootIndex); 3104 __ LoadRoot(scratch, Heap::kHeapNumberMapRootIndex);
2297 __ AllocateHeapNumber(reg, temp1, temp2, scratch, deferred->entry()); 3105 __ AllocateHeapNumber(reg, temp1, temp2, scratch, deferred->entry());
2298 } else { 3106 } else {
2299 __ jmp(deferred->entry()); 3107 __ jmp(deferred->entry());
2300 } 3108 }
2301 __ bind(deferred->exit()); 3109 __ bind(deferred->exit());
2302 __ sub(ip, reg, Operand(kHeapObjectTag)); 3110 __ sub(ip, reg, Operand(kHeapObjectTag));
(...skipping 12 matching lines...) Expand all
2315 __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber); 3123 __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber);
2316 RecordSafepointWithRegisters( 3124 RecordSafepointWithRegisters(
2317 instr->pointer_map(), 0, Safepoint::kNoDeoptimizationIndex); 3125 instr->pointer_map(), 0, Safepoint::kNoDeoptimizationIndex);
2318 int reg_stack_index = __ SafepointRegisterStackIndex(reg.code()); 3126 int reg_stack_index = __ SafepointRegisterStackIndex(reg.code());
2319 __ str(r0, MemOperand(sp, reg_stack_index * kPointerSize)); 3127 __ str(r0, MemOperand(sp, reg_stack_index * kPointerSize));
2320 __ PopSafepointRegisters(); 3128 __ PopSafepointRegisters();
2321 } 3129 }
2322 3130
2323 3131
2324 void LCodeGen::DoSmiTag(LSmiTag* instr) { 3132 void LCodeGen::DoSmiTag(LSmiTag* instr) {
2325 LOperand* input = instr->input(); 3133 LOperand* input = instr->InputAt(0);
2326 ASSERT(input->IsRegister() && input->Equals(instr->result())); 3134 ASSERT(input->IsRegister() && input->Equals(instr->result()));
2327 ASSERT(!instr->hydrogen_value()->CheckFlag(HValue::kCanOverflow)); 3135 ASSERT(!instr->hydrogen_value()->CheckFlag(HValue::kCanOverflow));
2328 __ SmiTag(ToRegister(input)); 3136 __ SmiTag(ToRegister(input));
2329 } 3137 }
2330 3138
2331 3139
2332 void LCodeGen::DoSmiUntag(LSmiUntag* instr) { 3140 void LCodeGen::DoSmiUntag(LSmiUntag* instr) {
2333 LOperand* input = instr->input(); 3141 LOperand* input = instr->InputAt(0);
2334 ASSERT(input->IsRegister() && input->Equals(instr->result())); 3142 ASSERT(input->IsRegister() && input->Equals(instr->result()));
2335 if (instr->needs_check()) { 3143 if (instr->needs_check()) {
2336 __ tst(ToRegister(input), Operand(kSmiTagMask)); 3144 __ tst(ToRegister(input), Operand(kSmiTagMask));
2337 DeoptimizeIf(ne, instr->environment()); 3145 DeoptimizeIf(ne, instr->environment());
2338 } 3146 }
2339 __ SmiUntag(ToRegister(input)); 3147 __ SmiUntag(ToRegister(input));
2340 } 3148 }
2341 3149
2342 3150
2343 void LCodeGen::EmitNumberUntagD(Register input_reg, 3151 void LCodeGen::EmitNumberUntagD(Register input_reg,
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
2390 DeferredTaggedToI(LCodeGen* codegen, LTaggedToI* instr) 3198 DeferredTaggedToI(LCodeGen* codegen, LTaggedToI* instr)
2391 : LDeferredCode(codegen), instr_(instr) { } 3199 : LDeferredCode(codegen), instr_(instr) { }
2392 virtual void Generate() { codegen()->DoDeferredTaggedToI(instr_); } 3200 virtual void Generate() { codegen()->DoDeferredTaggedToI(instr_); }
2393 private: 3201 private:
2394 LTaggedToI* instr_; 3202 LTaggedToI* instr_;
2395 }; 3203 };
2396 3204
2397 3205
2398 void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) { 3206 void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) {
2399 Label done; 3207 Label done;
2400 Register input_reg = ToRegister(instr->input()); 3208 Register input_reg = ToRegister(instr->InputAt(0));
2401 Register scratch = scratch0(); 3209 Register scratch = scratch0();
2402 DoubleRegister dbl_scratch = d0; 3210 DoubleRegister dbl_scratch = d0;
2403 SwVfpRegister flt_scratch = s0; 3211 SwVfpRegister flt_scratch = s0;
2404 DoubleRegister dbl_tmp = ToDoubleRegister(instr->temp()); 3212 DoubleRegister dbl_tmp = ToDoubleRegister(instr->TempAt(0));
2405 3213
2406 // Heap number map check. 3214 // Heap number map check.
2407 __ ldr(scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset)); 3215 __ ldr(scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset));
2408 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex); 3216 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex);
2409 __ cmp(scratch, Operand(ip)); 3217 __ cmp(scratch, Operand(ip));
2410 3218
2411 if (instr->truncating()) { 3219 if (instr->truncating()) {
2412 Label heap_number; 3220 Label heap_number;
2413 __ b(eq, &heap_number); 3221 __ b(eq, &heap_number);
2414 // Check for undefined. Undefined is converted to zero for truncating 3222 // Check for undefined. Undefined is converted to zero for truncating
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
2451 __ vmov(lr, ip, dbl_tmp); 3259 __ vmov(lr, ip, dbl_tmp);
2452 __ tst(ip, Operand(1 << 31)); // Test sign bit. 3260 __ tst(ip, Operand(1 << 31)); // Test sign bit.
2453 DeoptimizeIf(ne, instr->environment()); 3261 DeoptimizeIf(ne, instr->environment());
2454 } 3262 }
2455 } 3263 }
2456 __ bind(&done); 3264 __ bind(&done);
2457 } 3265 }
2458 3266
2459 3267
2460 void LCodeGen::DoTaggedToI(LTaggedToI* instr) { 3268 void LCodeGen::DoTaggedToI(LTaggedToI* instr) {
2461 LOperand* input = instr->input(); 3269 LOperand* input = instr->InputAt(0);
2462 ASSERT(input->IsRegister()); 3270 ASSERT(input->IsRegister());
2463 ASSERT(input->Equals(instr->result())); 3271 ASSERT(input->Equals(instr->result()));
2464 3272
2465 Register input_reg = ToRegister(input); 3273 Register input_reg = ToRegister(input);
2466 3274
2467 DeferredTaggedToI* deferred = new DeferredTaggedToI(this, instr); 3275 DeferredTaggedToI* deferred = new DeferredTaggedToI(this, instr);
2468 3276
2469 // Smi check. 3277 // Smi check.
2470 __ tst(input_reg, Operand(kSmiTagMask)); 3278 __ tst(input_reg, Operand(kSmiTagMask));
2471 __ b(ne, deferred->entry()); 3279 __ b(ne, deferred->entry());
2472 3280
2473 // Smi to int32 conversion 3281 // Smi to int32 conversion
2474 __ SmiUntag(input_reg); // Untag smi. 3282 __ SmiUntag(input_reg); // Untag smi.
2475 3283
2476 __ bind(deferred->exit()); 3284 __ bind(deferred->exit());
2477 } 3285 }
2478 3286
2479 3287
2480 void LCodeGen::DoNumberUntagD(LNumberUntagD* instr) { 3288 void LCodeGen::DoNumberUntagD(LNumberUntagD* instr) {
2481 LOperand* input = instr->input(); 3289 LOperand* input = instr->InputAt(0);
2482 ASSERT(input->IsRegister()); 3290 ASSERT(input->IsRegister());
2483 LOperand* result = instr->result(); 3291 LOperand* result = instr->result();
2484 ASSERT(result->IsDoubleRegister()); 3292 ASSERT(result->IsDoubleRegister());
2485 3293
2486 Register input_reg = ToRegister(input); 3294 Register input_reg = ToRegister(input);
2487 DoubleRegister result_reg = ToDoubleRegister(result); 3295 DoubleRegister result_reg = ToDoubleRegister(result);
2488 3296
2489 EmitNumberUntagD(input_reg, result_reg, instr->environment()); 3297 EmitNumberUntagD(input_reg, result_reg, instr->environment());
2490 } 3298 }
2491 3299
2492 3300
2493 void LCodeGen::DoDoubleToI(LDoubleToI* instr) { 3301 void LCodeGen::DoDoubleToI(LDoubleToI* instr) {
2494 Abort("DoDoubleToI unimplemented."); 3302 Abort("DoDoubleToI unimplemented.");
2495 } 3303 }
2496 3304
2497 3305
2498 void LCodeGen::DoCheckSmi(LCheckSmi* instr) { 3306 void LCodeGen::DoCheckSmi(LCheckSmi* instr) {
2499 LOperand* input = instr->input(); 3307 LOperand* input = instr->InputAt(0);
2500 ASSERT(input->IsRegister()); 3308 ASSERT(input->IsRegister());
2501 __ tst(ToRegister(input), Operand(kSmiTagMask)); 3309 __ tst(ToRegister(input), Operand(kSmiTagMask));
2502 DeoptimizeIf(instr->condition(), instr->environment()); 3310 DeoptimizeIf(instr->condition(), instr->environment());
2503 } 3311 }
2504 3312
2505 3313
2506 void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) { 3314 void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) {
2507 Register input = ToRegister(instr->input()); 3315 Register input = ToRegister(instr->InputAt(0));
2508 Register scratch = scratch0(); 3316 Register scratch = scratch0();
2509 InstanceType first = instr->hydrogen()->first(); 3317 InstanceType first = instr->hydrogen()->first();
2510 InstanceType last = instr->hydrogen()->last(); 3318 InstanceType last = instr->hydrogen()->last();
2511 3319
2512 __ ldr(scratch, FieldMemOperand(input, HeapObject::kMapOffset)); 3320 __ ldr(scratch, FieldMemOperand(input, HeapObject::kMapOffset));
2513 __ ldrb(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset)); 3321 __ ldrb(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset));
2514 __ cmp(scratch, Operand(first)); 3322 __ cmp(scratch, Operand(first));
2515 3323
2516 // If there is only one type in the interval check for equality. 3324 // If there is only one type in the interval check for equality.
2517 if (first == last) { 3325 if (first == last) {
2518 DeoptimizeIf(ne, instr->environment()); 3326 DeoptimizeIf(ne, instr->environment());
2519 } else { 3327 } else {
2520 DeoptimizeIf(lo, instr->environment()); 3328 DeoptimizeIf(lo, instr->environment());
2521 // Omit check for the last type. 3329 // Omit check for the last type.
2522 if (last != LAST_TYPE) { 3330 if (last != LAST_TYPE) {
2523 __ cmp(scratch, Operand(last)); 3331 __ cmp(scratch, Operand(last));
2524 DeoptimizeIf(hi, instr->environment()); 3332 DeoptimizeIf(hi, instr->environment());
2525 } 3333 }
2526 } 3334 }
2527 } 3335 }
2528 3336
2529 3337
2530 void LCodeGen::DoCheckFunction(LCheckFunction* instr) { 3338 void LCodeGen::DoCheckFunction(LCheckFunction* instr) {
2531 ASSERT(instr->input()->IsRegister()); 3339 ASSERT(instr->InputAt(0)->IsRegister());
2532 Register reg = ToRegister(instr->input()); 3340 Register reg = ToRegister(instr->InputAt(0));
2533 __ cmp(reg, Operand(instr->hydrogen()->target())); 3341 __ cmp(reg, Operand(instr->hydrogen()->target()));
2534 DeoptimizeIf(ne, instr->environment()); 3342 DeoptimizeIf(ne, instr->environment());
2535 } 3343 }
2536 3344
2537 3345
2538 void LCodeGen::DoCheckMap(LCheckMap* instr) { 3346 void LCodeGen::DoCheckMap(LCheckMap* instr) {
2539 Register scratch = scratch0(); 3347 Register scratch = scratch0();
2540 LOperand* input = instr->input(); 3348 LOperand* input = instr->InputAt(0);
2541 ASSERT(input->IsRegister()); 3349 ASSERT(input->IsRegister());
2542 Register reg = ToRegister(input); 3350 Register reg = ToRegister(input);
2543 __ ldr(scratch, FieldMemOperand(reg, HeapObject::kMapOffset)); 3351 __ ldr(scratch, FieldMemOperand(reg, HeapObject::kMapOffset));
2544 __ cmp(scratch, Operand(instr->hydrogen()->map())); 3352 __ cmp(scratch, Operand(instr->hydrogen()->map()));
2545 DeoptimizeIf(ne, instr->environment()); 3353 DeoptimizeIf(ne, instr->environment());
2546 } 3354 }
2547 3355
2548 3356
2549 void LCodeGen::LoadPrototype(Register result, 3357 void LCodeGen::LoadHeapObject(Register result,
2550 Handle<JSObject> prototype) { 3358 Handle<HeapObject> object) {
2551 if (HEAP->InNewSpace(*prototype)) { 3359 if (HEAP->InNewSpace(*object)) {
2552 Handle<JSGlobalPropertyCell> cell = 3360 Handle<JSGlobalPropertyCell> cell =
2553 FACTORY->NewJSGlobalPropertyCell(prototype); 3361 FACTORY->NewJSGlobalPropertyCell(object);
2554 __ mov(result, Operand(cell)); 3362 __ mov(result, Operand(cell));
2555 __ ldr(result, FieldMemOperand(result, JSGlobalPropertyCell::kValueOffset)); 3363 __ ldr(result, FieldMemOperand(result, JSGlobalPropertyCell::kValueOffset));
2556 } else { 3364 } else {
2557 __ mov(result, Operand(prototype)); 3365 __ mov(result, Operand(object));
2558 } 3366 }
2559 } 3367 }
2560 3368
2561 3369
2562 void LCodeGen::DoCheckPrototypeMaps(LCheckPrototypeMaps* instr) { 3370 void LCodeGen::DoCheckPrototypeMaps(LCheckPrototypeMaps* instr) {
2563 Register temp1 = ToRegister(instr->temp1()); 3371 Register temp1 = ToRegister(instr->TempAt(0));
2564 Register temp2 = ToRegister(instr->temp2()); 3372 Register temp2 = ToRegister(instr->TempAt(1));
2565 3373
2566 Handle<JSObject> holder = instr->holder(); 3374 Handle<JSObject> holder = instr->holder();
2567 Handle<JSObject> current_prototype = instr->prototype(); 3375 Handle<JSObject> current_prototype = instr->prototype();
2568 3376
2569 // Load prototype object. 3377 // Load prototype object.
2570 LoadPrototype(temp1, current_prototype); 3378 LoadHeapObject(temp1, current_prototype);
2571 3379
2572 // Check prototype maps up to the holder. 3380 // Check prototype maps up to the holder.
2573 while (!current_prototype.is_identical_to(holder)) { 3381 while (!current_prototype.is_identical_to(holder)) {
2574 __ ldr(temp2, FieldMemOperand(temp1, HeapObject::kMapOffset)); 3382 __ ldr(temp2, FieldMemOperand(temp1, HeapObject::kMapOffset));
2575 __ cmp(temp2, Operand(Handle<Map>(current_prototype->map()))); 3383 __ cmp(temp2, Operand(Handle<Map>(current_prototype->map())));
2576 DeoptimizeIf(ne, instr->environment()); 3384 DeoptimizeIf(ne, instr->environment());
2577 current_prototype = 3385 current_prototype =
2578 Handle<JSObject>(JSObject::cast(current_prototype->GetPrototype())); 3386 Handle<JSObject>(JSObject::cast(current_prototype->GetPrototype()));
2579 // Load next prototype object. 3387 // Load next prototype object.
2580 LoadPrototype(temp1, current_prototype); 3388 LoadHeapObject(temp1, current_prototype);
2581 } 3389 }
2582 3390
2583 // Check the holder map. 3391 // Check the holder map.
2584 __ ldr(temp2, FieldMemOperand(temp1, HeapObject::kMapOffset)); 3392 __ ldr(temp2, FieldMemOperand(temp1, HeapObject::kMapOffset));
2585 __ cmp(temp2, Operand(Handle<Map>(current_prototype->map()))); 3393 __ cmp(temp2, Operand(Handle<Map>(current_prototype->map())));
2586 DeoptimizeIf(ne, instr->environment()); 3394 DeoptimizeIf(ne, instr->environment());
2587 } 3395 }
2588 3396
2589 3397
2590 void LCodeGen::DoArrayLiteral(LArrayLiteral* instr) { 3398 void LCodeGen::DoArrayLiteral(LArrayLiteral* instr) {
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
2702 __ mov(r1, Operand(pretenure 3510 __ mov(r1, Operand(pretenure
2703 ? FACTORY->true_value() 3511 ? FACTORY->true_value()
2704 : FACTORY->false_value())); 3512 : FACTORY->false_value()));
2705 __ Push(cp, r2, r1); 3513 __ Push(cp, r2, r1);
2706 CallRuntime(Runtime::kNewClosure, 3, instr); 3514 CallRuntime(Runtime::kNewClosure, 3, instr);
2707 } 3515 }
2708 } 3516 }
2709 3517
2710 3518
2711 void LCodeGen::DoTypeof(LTypeof* instr) { 3519 void LCodeGen::DoTypeof(LTypeof* instr) {
2712 Register input = ToRegister(instr->input()); 3520 Register input = ToRegister(instr->InputAt(0));
2713 __ push(input); 3521 __ push(input);
2714 CallRuntime(Runtime::kTypeof, 1, instr); 3522 CallRuntime(Runtime::kTypeof, 1, instr);
2715 } 3523 }
2716 3524
2717 3525
2718 void LCodeGen::DoTypeofIs(LTypeofIs* instr) { 3526 void LCodeGen::DoTypeofIs(LTypeofIs* instr) {
2719 Register input = ToRegister(instr->input()); 3527 Register input = ToRegister(instr->InputAt(0));
2720 Register result = ToRegister(instr->result()); 3528 Register result = ToRegister(instr->result());
2721 Label true_label; 3529 Label true_label;
2722 Label false_label; 3530 Label false_label;
2723 Label done; 3531 Label done;
2724 3532
2725 Condition final_branch_condition = EmitTypeofIs(&true_label, 3533 Condition final_branch_condition = EmitTypeofIs(&true_label,
2726 &false_label, 3534 &false_label,
2727 input, 3535 input,
2728 instr->type_literal()); 3536 instr->type_literal());
2729 __ b(final_branch_condition, &true_label); 3537 __ b(final_branch_condition, &true_label);
2730 __ bind(&false_label); 3538 __ bind(&false_label);
2731 __ LoadRoot(result, Heap::kFalseValueRootIndex); 3539 __ LoadRoot(result, Heap::kFalseValueRootIndex);
2732 __ b(&done); 3540 __ b(&done);
2733 3541
2734 __ bind(&true_label); 3542 __ bind(&true_label);
2735 __ LoadRoot(result, Heap::kTrueValueRootIndex); 3543 __ LoadRoot(result, Heap::kTrueValueRootIndex);
2736 3544
2737 __ bind(&done); 3545 __ bind(&done);
2738 } 3546 }
2739 3547
2740 3548
2741 void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) { 3549 void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) {
2742 Register input = ToRegister(instr->input()); 3550 Register input = ToRegister(instr->InputAt(0));
2743 int true_block = chunk_->LookupDestination(instr->true_block_id()); 3551 int true_block = chunk_->LookupDestination(instr->true_block_id());
2744 int false_block = chunk_->LookupDestination(instr->false_block_id()); 3552 int false_block = chunk_->LookupDestination(instr->false_block_id());
2745 Label* true_label = chunk_->GetAssemblyLabel(true_block); 3553 Label* true_label = chunk_->GetAssemblyLabel(true_block);
2746 Label* false_label = chunk_->GetAssemblyLabel(false_block); 3554 Label* false_label = chunk_->GetAssemblyLabel(false_block);
2747 3555
2748 Condition final_branch_condition = EmitTypeofIs(true_label, 3556 Condition final_branch_condition = EmitTypeofIs(true_label,
2749 false_label, 3557 false_label,
2750 input, 3558 input,
2751 instr->type_literal()); 3559 instr->type_literal());
2752 3560
2753 EmitBranch(true_block, false_block, final_branch_condition); 3561 EmitBranch(true_block, false_block, final_branch_condition);
2754 } 3562 }
2755 3563
2756 3564
2757 Condition LCodeGen::EmitTypeofIs(Label* true_label, 3565 Condition LCodeGen::EmitTypeofIs(Label* true_label,
2758 Label* false_label, 3566 Label* false_label,
2759 Register input, 3567 Register input,
2760 Handle<String> type_name) { 3568 Handle<String> type_name) {
2761 Condition final_branch_condition = no_condition; 3569 Condition final_branch_condition = kNoCondition;
2762 Register scratch = scratch0(); 3570 Register scratch = scratch0();
2763 if (type_name->Equals(HEAP->number_symbol())) { 3571 if (type_name->Equals(HEAP->number_symbol())) {
2764 __ tst(input, Operand(kSmiTagMask)); 3572 __ tst(input, Operand(kSmiTagMask));
2765 __ b(eq, true_label); 3573 __ b(eq, true_label);
2766 __ ldr(input, FieldMemOperand(input, HeapObject::kMapOffset)); 3574 __ ldr(input, FieldMemOperand(input, HeapObject::kMapOffset));
2767 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex); 3575 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex);
2768 __ cmp(input, Operand(ip)); 3576 __ cmp(input, Operand(ip));
2769 final_branch_condition = eq; 3577 final_branch_condition = eq;
2770 3578
2771 } else if (type_name->Equals(HEAP->string_symbol())) { 3579 } else if (type_name->Equals(HEAP->string_symbol())) {
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
2836 } 3644 }
2837 3645
2838 3646
2839 void LCodeGen::DoLazyBailout(LLazyBailout* instr) { 3647 void LCodeGen::DoLazyBailout(LLazyBailout* instr) {
2840 // No code for lazy bailout instruction. Used to capture environment after a 3648 // No code for lazy bailout instruction. Used to capture environment after a
2841 // call for populating the safepoint data with deoptimization data. 3649 // call for populating the safepoint data with deoptimization data.
2842 } 3650 }
2843 3651
2844 3652
2845 void LCodeGen::DoDeoptimize(LDeoptimize* instr) { 3653 void LCodeGen::DoDeoptimize(LDeoptimize* instr) {
2846 DeoptimizeIf(no_condition, instr->environment()); 3654 DeoptimizeIf(kNoCondition, instr->environment());
2847 } 3655 }
2848 3656
2849 3657
2850 void LCodeGen::DoDeleteProperty(LDeleteProperty* instr) { 3658 void LCodeGen::DoDeleteProperty(LDeleteProperty* instr) {
2851 Register object = ToRegister(instr->object()); 3659 Register object = ToRegister(instr->object());
2852 Register key = ToRegister(instr->key()); 3660 Register key = ToRegister(instr->key());
2853 __ Push(object, key); 3661 __ Push(object, key);
2854 RecordPosition(instr->pointer_map()->position()); 3662 RecordPosition(instr->pointer_map()->position());
2855 SafepointGenerator safepoint_generator(this, 3663 SafepointGenerator safepoint_generator(this,
2856 instr->pointer_map(), 3664 instr->pointer_map(),
(...skipping 15 matching lines...) Expand all
2872 3680
2873 3681
2874 void LCodeGen::DoOsrEntry(LOsrEntry* instr) { 3682 void LCodeGen::DoOsrEntry(LOsrEntry* instr) {
2875 Abort("DoOsrEntry unimplemented."); 3683 Abort("DoOsrEntry unimplemented.");
2876 } 3684 }
2877 3685
2878 3686
2879 #undef __ 3687 #undef __
2880 3688
2881 } } // namespace v8::internal 3689 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/arm/lithium-codegen-arm.h ('k') | src/arm/macro-assembler-arm.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698