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

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

Issue 7348008: Merge up to 8597 to experimental/gc from the bleeding edge. (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/gc/
Patch Set: '' Created 9 years, 5 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 128 matching lines...) Expand 10 before | Expand all | Expand 10 after
139 info_->function()->name()->IsEqualTo(CStrVector(FLAG_stop_at))) { 139 info_->function()->name()->IsEqualTo(CStrVector(FLAG_stop_at))) {
140 __ stop("stop_at"); 140 __ stop("stop_at");
141 } 141 }
142 #endif 142 #endif
143 143
144 // r1: Callee's JS function. 144 // r1: Callee's JS function.
145 // cp: Callee's context. 145 // cp: Callee's context.
146 // fp: Caller's frame pointer. 146 // fp: Caller's frame pointer.
147 // lr: Caller's pc. 147 // lr: Caller's pc.
148 148
149 // Strict mode functions need to replace the receiver with undefined 149 // Strict mode functions and builtins need to replace the receiver
150 // when called as functions (without an explicit receiver 150 // with undefined when called as functions (without an explicit
151 // object). r5 is zero for method calls and non-zero for function 151 // receiver object). r5 is zero for method calls and non-zero for
152 // calls. 152 // function calls.
153 if (info_->is_strict_mode()) { 153 if (info_->is_strict_mode() || info_->is_native()) {
154 Label ok; 154 Label ok;
155 __ cmp(r5, Operand(0)); 155 __ cmp(r5, Operand(0));
156 __ b(eq, &ok); 156 __ b(eq, &ok);
157 int receiver_offset = scope()->num_parameters() * kPointerSize; 157 int receiver_offset = scope()->num_parameters() * kPointerSize;
158 __ LoadRoot(r2, Heap::kUndefinedValueRootIndex); 158 __ LoadRoot(r2, Heap::kUndefinedValueRootIndex);
159 __ str(r2, MemOperand(sp, receiver_offset)); 159 __ str(r2, MemOperand(sp, receiver_offset));
160 __ bind(&ok); 160 __ bind(&ok);
161 } 161 }
162 162
163 __ stm(db_w, sp, r1.bit() | cp.bit() | fp.bit() | lr.bit()); 163 __ stm(db_w, sp, r1.bit() | cp.bit() | fp.bit() | lr.bit());
(...skipping 18 matching lines...) Expand all
182 // Possibly allocate a local context. 182 // Possibly allocate a local context.
183 int heap_slots = scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; 183 int heap_slots = scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
184 if (heap_slots > 0) { 184 if (heap_slots > 0) {
185 Comment(";;; Allocate local context"); 185 Comment(";;; Allocate local context");
186 // Argument to NewContext is the function, which is in r1. 186 // Argument to NewContext is the function, which is in r1.
187 __ push(r1); 187 __ push(r1);
188 if (heap_slots <= FastNewContextStub::kMaximumSlots) { 188 if (heap_slots <= FastNewContextStub::kMaximumSlots) {
189 FastNewContextStub stub(heap_slots); 189 FastNewContextStub stub(heap_slots);
190 __ CallStub(&stub); 190 __ CallStub(&stub);
191 } else { 191 } else {
192 __ CallRuntime(Runtime::kNewContext, 1); 192 __ CallRuntime(Runtime::kNewFunctionContext, 1);
193 } 193 }
194 RecordSafepoint(Safepoint::kNoDeoptimizationIndex); 194 RecordSafepoint(Safepoint::kNoDeoptimizationIndex);
195 // Context is returned in both r0 and cp. It replaces the context 195 // Context is returned in both r0 and cp. It replaces the context
196 // passed to us. It's saved in the stack and kept live in cp. 196 // passed to us. It's saved in the stack and kept live in cp.
197 __ str(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 197 __ str(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
198 // Copy any necessary parameters into the context. 198 // Copy any necessary parameters into the context.
199 int num_parameters = scope()->num_parameters(); 199 int num_parameters = scope()->num_parameters();
200 for (int i = 0; i < num_parameters; i++) { 200 for (int i = 0; i < num_parameters; i++) {
201 Slot* slot = scope()->parameter(i)->AsSlot(); 201 Slot* slot = scope()->parameter(i)->AsSlot();
202 if (slot != NULL && slot->type() == Slot::CONTEXT) { 202 if (slot != NULL && slot->type() == Slot::CONTEXT) {
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
248 if (current_instruction_ < instructions_->length() - 1) { 248 if (current_instruction_ < instructions_->length() - 1) {
249 return instructions_->at(current_instruction_ + 1); 249 return instructions_->at(current_instruction_ + 1);
250 } else { 250 } else {
251 return NULL; 251 return NULL;
252 } 252 }
253 } 253 }
254 254
255 255
256 bool LCodeGen::GenerateDeferredCode() { 256 bool LCodeGen::GenerateDeferredCode() {
257 ASSERT(is_generating()); 257 ASSERT(is_generating());
258 for (int i = 0; !is_aborted() && i < deferred_.length(); i++) { 258 if (deferred_.length() > 0) {
259 LDeferredCode* code = deferred_[i]; 259 for (int i = 0; !is_aborted() && i < deferred_.length(); i++) {
260 __ bind(code->entry()); 260 LDeferredCode* code = deferred_[i];
261 code->Generate(); 261 __ bind(code->entry());
262 __ jmp(code->exit()); 262 code->Generate();
263 __ jmp(code->exit());
264 }
265
266 // Pad code to ensure that the last piece of deferred code have
267 // room for lazy bailout.
268 while ((masm()->pc_offset() - LastSafepointEnd())
269 < Deoptimizer::patch_size()) {
270 __ nop();
271 }
263 } 272 }
264 273
265 // Force constant pool emission at the end of the deferred code to make 274 // Force constant pool emission at the end of the deferred code to make
266 // sure that no constant pools are emitted after. 275 // sure that no constant pools are emitted after.
267 masm()->CheckConstPool(true, false); 276 masm()->CheckConstPool(true, false);
268 277
269 return !is_aborted(); 278 return !is_aborted();
270 } 279 }
271 280
272 281
(...skipping 488 matching lines...) Expand 10 before | Expand all | Expand 10 after
761 void LCodeGen::RecordSafepointWithRegistersAndDoubles( 770 void LCodeGen::RecordSafepointWithRegistersAndDoubles(
762 LPointerMap* pointers, 771 LPointerMap* pointers,
763 int arguments, 772 int arguments,
764 int deoptimization_index) { 773 int deoptimization_index) {
765 RecordSafepoint(pointers, Safepoint::kWithRegistersAndDoubles, arguments, 774 RecordSafepoint(pointers, Safepoint::kWithRegistersAndDoubles, arguments,
766 deoptimization_index); 775 deoptimization_index);
767 } 776 }
768 777
769 778
770 void LCodeGen::RecordPosition(int position) { 779 void LCodeGen::RecordPosition(int position) {
771 if (!FLAG_debug_info || position == RelocInfo::kNoPosition) return; 780 if (position == RelocInfo::kNoPosition) return;
772 masm()->positions_recorder()->RecordPosition(position); 781 masm()->positions_recorder()->RecordPosition(position);
773 } 782 }
774 783
775 784
776 void LCodeGen::DoLabel(LLabel* label) { 785 void LCodeGen::DoLabel(LLabel* label) {
777 if (label->is_loop_header()) { 786 if (label->is_loop_header()) {
778 Comment(";;; B%d - LOOP entry", label->block_id()); 787 Comment(";;; B%d - LOOP entry", label->block_id());
779 } else { 788 } else {
780 Comment(";;; B%d", label->block_id()); 789 Comment(";;; B%d", label->block_id());
781 } 790 }
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
864 873
865 874
866 void LCodeGen::DoUnknownOSRValue(LUnknownOSRValue* instr) { 875 void LCodeGen::DoUnknownOSRValue(LUnknownOSRValue* instr) {
867 // Nothing to do. 876 // Nothing to do.
868 } 877 }
869 878
870 879
871 void LCodeGen::DoModI(LModI* instr) { 880 void LCodeGen::DoModI(LModI* instr) {
872 if (instr->hydrogen()->HasPowerOf2Divisor()) { 881 if (instr->hydrogen()->HasPowerOf2Divisor()) {
873 Register dividend = ToRegister(instr->InputAt(0)); 882 Register dividend = ToRegister(instr->InputAt(0));
883 Register result = ToRegister(instr->result());
874 884
875 int32_t divisor = 885 int32_t divisor =
876 HConstant::cast(instr->hydrogen()->right())->Integer32Value(); 886 HConstant::cast(instr->hydrogen()->right())->Integer32Value();
877 887
878 if (divisor < 0) divisor = -divisor; 888 if (divisor < 0) divisor = -divisor;
879 889
880 Label positive_dividend, done; 890 Label positive_dividend, done;
881 __ cmp(dividend, Operand(0)); 891 __ cmp(dividend, Operand(0));
882 __ b(pl, &positive_dividend); 892 __ b(pl, &positive_dividend);
883 __ rsb(dividend, dividend, Operand(0)); 893 __ rsb(result, dividend, Operand(0));
884 __ and_(dividend, dividend, Operand(divisor - 1)); 894 __ and_(result, result, Operand(divisor - 1), SetCC);
885 __ rsb(dividend, dividend, Operand(0), SetCC);
886 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 895 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
887 __ b(ne, &done); 896 DeoptimizeIf(eq, instr->environment());
888 DeoptimizeIf(al, instr->environment());
889 } 897 }
898 __ rsb(result, result, Operand(0));
899 __ b(&done);
890 __ bind(&positive_dividend); 900 __ bind(&positive_dividend);
891 __ and_(dividend, dividend, Operand(divisor - 1)); 901 __ and_(result, dividend, Operand(divisor - 1));
892 __ bind(&done); 902 __ bind(&done);
893 return; 903 return;
894 } 904 }
895 905
896 // These registers hold untagged 32 bit values. 906 // These registers hold untagged 32 bit values.
897 Register left = ToRegister(instr->InputAt(0)); 907 Register left = ToRegister(instr->InputAt(0));
898 Register right = ToRegister(instr->InputAt(1)); 908 Register right = ToRegister(instr->InputAt(1));
899 Register result = ToRegister(instr->result()); 909 Register result = ToRegister(instr->result());
900 910
901 Register scratch = scratch0(); 911 Register scratch = scratch0();
902 Register scratch2 = ToRegister(instr->TempAt(0)); 912 Register scratch2 = ToRegister(instr->TempAt(0));
903 DwVfpRegister dividend = ToDoubleRegister(instr->TempAt(1)); 913 DwVfpRegister dividend = ToDoubleRegister(instr->TempAt(1));
904 DwVfpRegister divisor = ToDoubleRegister(instr->TempAt(2)); 914 DwVfpRegister divisor = ToDoubleRegister(instr->TempAt(2));
905 DwVfpRegister quotient = double_scratch0(); 915 DwVfpRegister quotient = double_scratch0();
906 916
907 ASSERT(result.is(left));
908
909 ASSERT(!dividend.is(divisor)); 917 ASSERT(!dividend.is(divisor));
910 ASSERT(!dividend.is(quotient)); 918 ASSERT(!dividend.is(quotient));
911 ASSERT(!divisor.is(quotient)); 919 ASSERT(!divisor.is(quotient));
912 ASSERT(!scratch.is(left)); 920 ASSERT(!scratch.is(left));
913 ASSERT(!scratch.is(right)); 921 ASSERT(!scratch.is(right));
914 ASSERT(!scratch.is(result)); 922 ASSERT(!scratch.is(result));
915 923
916 Label done, vfp_modulo, both_positive, right_negative; 924 Label done, vfp_modulo, both_positive, right_negative;
917 925
918 // Check for x % 0. 926 // Check for x % 0.
919 if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) { 927 if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) {
920 __ cmp(right, Operand(0)); 928 __ cmp(right, Operand(0));
921 DeoptimizeIf(eq, instr->environment()); 929 DeoptimizeIf(eq, instr->environment());
922 } 930 }
923 931
932 __ Move(result, left);
933
924 // (0 % x) must yield 0 (if x is finite, which is the case here). 934 // (0 % x) must yield 0 (if x is finite, which is the case here).
925 __ cmp(left, Operand(0)); 935 __ cmp(left, Operand(0));
926 __ b(eq, &done); 936 __ b(eq, &done);
927 // Preload right in a vfp register. 937 // Preload right in a vfp register.
928 __ vmov(divisor.low(), right); 938 __ vmov(divisor.low(), right);
929 __ b(lt, &vfp_modulo); 939 __ b(lt, &vfp_modulo);
930 940
931 __ cmp(left, Operand(right)); 941 __ cmp(left, Operand(right));
932 __ b(lt, &done); 942 __ b(lt, &done);
933 943
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after
1110 RecordSafepointWithRegistersAndDoubles(instr->pointer_map(), 1120 RecordSafepointWithRegistersAndDoubles(instr->pointer_map(),
1111 0, 1121 0,
1112 Safepoint::kNoDeoptimizationIndex); 1122 Safepoint::kNoDeoptimizationIndex);
1113 // Overwrite the stored value of r0 with the result of the stub. 1123 // Overwrite the stored value of r0 with the result of the stub.
1114 __ StoreToSafepointRegistersAndDoublesSlot(r0, r0); 1124 __ StoreToSafepointRegistersAndDoublesSlot(r0, r0);
1115 } 1125 }
1116 1126
1117 1127
1118 void LCodeGen::DoMulI(LMulI* instr) { 1128 void LCodeGen::DoMulI(LMulI* instr) {
1119 Register scratch = scratch0(); 1129 Register scratch = scratch0();
1130 Register result = ToRegister(instr->result());
1131 // Note that result may alias left.
1120 Register left = ToRegister(instr->InputAt(0)); 1132 Register left = ToRegister(instr->InputAt(0));
1121 Register right = EmitLoadRegister(instr->InputAt(1), scratch); 1133 LOperand* right_op = instr->InputAt(1);
1122 1134
1123 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero) && 1135 bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow);
1124 !instr->InputAt(1)->IsConstantOperand()) { 1136 bool bailout_on_minus_zero =
1125 __ orr(ToRegister(instr->TempAt(0)), left, right); 1137 instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero);
1126 }
1127 1138
1128 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { 1139 if (right_op->IsConstantOperand() && !can_overflow) {
1129 // scratch:left = left * right. 1140 // Use optimized code for specific constants.
1130 __ smull(left, scratch, left, right); 1141 int32_t constant = ToInteger32(LConstantOperand::cast(right_op));
1131 __ mov(ip, Operand(left, ASR, 31)); 1142
1132 __ cmp(ip, Operand(scratch)); 1143 if (bailout_on_minus_zero && (constant < 0)) {
1133 DeoptimizeIf(ne, instr->environment()); 1144 // The case of a null constant will be handled separately.
1145 // If constant is negative and left is null, the result should be -0.
1146 __ cmp(left, Operand(0));
1147 DeoptimizeIf(eq, instr->environment());
1148 }
1149
1150 switch (constant) {
1151 case -1:
1152 __ rsb(result, left, Operand(0));
1153 break;
1154 case 0:
1155 if (bailout_on_minus_zero) {
1156 // If left is strictly negative and the constant is null, the
1157 // result is -0. Deoptimize if required, otherwise return 0.
1158 __ cmp(left, Operand(0));
1159 DeoptimizeIf(mi, instr->environment());
1160 }
1161 __ mov(result, Operand(0));
1162 break;
1163 case 1:
1164 __ Move(result, left);
1165 break;
1166 default:
1167 // Multiplying by powers of two and powers of two plus or minus
1168 // one can be done faster with shifted operands.
1169 // For other constants we emit standard code.
1170 int32_t mask = constant >> 31;
1171 uint32_t constant_abs = (constant + mask) ^ mask;
1172
1173 if (IsPowerOf2(constant_abs) ||
1174 IsPowerOf2(constant_abs - 1) ||
1175 IsPowerOf2(constant_abs + 1)) {
1176 if (IsPowerOf2(constant_abs)) {
1177 int32_t shift = WhichPowerOf2(constant_abs);
1178 __ mov(result, Operand(left, LSL, shift));
1179 } else if (IsPowerOf2(constant_abs - 1)) {
1180 int32_t shift = WhichPowerOf2(constant_abs - 1);
1181 __ add(result, left, Operand(left, LSL, shift));
1182 } else if (IsPowerOf2(constant_abs + 1)) {
1183 int32_t shift = WhichPowerOf2(constant_abs + 1);
1184 __ rsb(result, left, Operand(left, LSL, shift));
1185 }
1186
1187 // Correct the sign of the result is the constant is negative.
1188 if (constant < 0) __ rsb(result, result, Operand(0));
1189
1190 } else {
1191 // Generate standard code.
1192 __ mov(ip, Operand(constant));
1193 __ mul(result, left, ip);
1194 }
1195 }
1196
1134 } else { 1197 } else {
1135 __ mul(left, left, right); 1198 Register right = EmitLoadRegister(right_op, scratch);
1136 } 1199 if (bailout_on_minus_zero) {
1200 __ orr(ToRegister(instr->TempAt(0)), left, right);
1201 }
1137 1202
1138 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 1203 if (can_overflow) {
1139 // Bail out if the result is supposed to be negative zero. 1204 // scratch:result = left * right.
1140 Label done; 1205 __ smull(result, scratch, left, right);
1141 __ cmp(left, Operand(0)); 1206 __ cmp(scratch, Operand(result, ASR, 31));
1142 __ b(ne, &done); 1207 DeoptimizeIf(ne, instr->environment());
1143 if (instr->InputAt(1)->IsConstantOperand()) {
1144 if (ToInteger32(LConstantOperand::cast(instr->InputAt(1))) <= 0) {
1145 DeoptimizeIf(al, instr->environment());
1146 }
1147 } else { 1208 } else {
1148 // Test the non-zero operand for negative sign. 1209 __ mul(result, left, right);
1210 }
1211
1212 if (bailout_on_minus_zero) {
1213 // Bail out if the result is supposed to be negative zero.
1214 Label done;
1215 __ cmp(result, Operand(0));
1216 __ b(ne, &done);
1149 __ cmp(ToRegister(instr->TempAt(0)), Operand(0)); 1217 __ cmp(ToRegister(instr->TempAt(0)), Operand(0));
1150 DeoptimizeIf(mi, instr->environment()); 1218 DeoptimizeIf(mi, instr->environment());
1219 __ bind(&done);
1151 } 1220 }
1152 __ bind(&done);
1153 } 1221 }
1154 } 1222 }
1155 1223
1156 1224
1157 void LCodeGen::DoBitI(LBitI* instr) { 1225 void LCodeGen::DoBitI(LBitI* instr) {
1158 LOperand* left = instr->InputAt(0); 1226 LOperand* left_op = instr->InputAt(0);
1159 LOperand* right = instr->InputAt(1); 1227 LOperand* right_op = instr->InputAt(1);
1160 ASSERT(left->Equals(instr->result())); 1228 ASSERT(left_op->IsRegister());
1161 ASSERT(left->IsRegister()); 1229 Register left = ToRegister(left_op);
1162 Register result = ToRegister(left); 1230 Register result = ToRegister(instr->result());
1163 Operand right_operand(no_reg); 1231 Operand right(no_reg);
1164 1232
1165 if (right->IsStackSlot() || right->IsArgument()) { 1233 if (right_op->IsStackSlot() || right_op->IsArgument()) {
1166 Register right_reg = EmitLoadRegister(right, ip); 1234 right = Operand(EmitLoadRegister(right_op, ip));
1167 right_operand = Operand(right_reg);
1168 } else { 1235 } else {
1169 ASSERT(right->IsRegister() || right->IsConstantOperand()); 1236 ASSERT(right_op->IsRegister() || right_op->IsConstantOperand());
1170 right_operand = ToOperand(right); 1237 right = ToOperand(right_op);
1171 } 1238 }
1172 1239
1173 switch (instr->op()) { 1240 switch (instr->op()) {
1174 case Token::BIT_AND: 1241 case Token::BIT_AND:
1175 __ and_(result, ToRegister(left), right_operand); 1242 __ and_(result, left, right);
1176 break; 1243 break;
1177 case Token::BIT_OR: 1244 case Token::BIT_OR:
1178 __ orr(result, ToRegister(left), right_operand); 1245 __ orr(result, left, right);
1179 break; 1246 break;
1180 case Token::BIT_XOR: 1247 case Token::BIT_XOR:
1181 __ eor(result, ToRegister(left), right_operand); 1248 __ eor(result, left, right);
1182 break; 1249 break;
1183 default: 1250 default:
1184 UNREACHABLE(); 1251 UNREACHABLE();
1185 break; 1252 break;
1186 } 1253 }
1187 } 1254 }
1188 1255
1189 1256
1190 void LCodeGen::DoShiftI(LShiftI* instr) { 1257 void LCodeGen::DoShiftI(LShiftI* instr) {
1258 // Both 'left' and 'right' are "used at start" (see LCodeGen::DoShift), so
1259 // result may alias either of them.
1260 LOperand* right_op = instr->InputAt(1);
1261 Register left = ToRegister(instr->InputAt(0));
1262 Register result = ToRegister(instr->result());
1191 Register scratch = scratch0(); 1263 Register scratch = scratch0();
1192 LOperand* left = instr->InputAt(0); 1264 if (right_op->IsRegister()) {
1193 LOperand* right = instr->InputAt(1); 1265 // Mask the right_op operand.
1194 ASSERT(left->Equals(instr->result())); 1266 __ and_(scratch, ToRegister(right_op), Operand(0x1F));
1195 ASSERT(left->IsRegister());
1196 Register result = ToRegister(left);
1197 if (right->IsRegister()) {
1198 // Mask the right operand.
1199 __ and_(scratch, ToRegister(right), Operand(0x1F));
1200 switch (instr->op()) { 1267 switch (instr->op()) {
1201 case Token::SAR: 1268 case Token::SAR:
1202 __ mov(result, Operand(result, ASR, scratch)); 1269 __ mov(result, Operand(left, ASR, scratch));
1203 break; 1270 break;
1204 case Token::SHR: 1271 case Token::SHR:
1205 if (instr->can_deopt()) { 1272 if (instr->can_deopt()) {
1206 __ mov(result, Operand(result, LSR, scratch), SetCC); 1273 __ mov(result, Operand(left, LSR, scratch), SetCC);
1207 DeoptimizeIf(mi, instr->environment()); 1274 DeoptimizeIf(mi, instr->environment());
1208 } else { 1275 } else {
1209 __ mov(result, Operand(result, LSR, scratch)); 1276 __ mov(result, Operand(left, LSR, scratch));
1210 } 1277 }
1211 break; 1278 break;
1212 case Token::SHL: 1279 case Token::SHL:
1213 __ mov(result, Operand(result, LSL, scratch)); 1280 __ mov(result, Operand(left, LSL, scratch));
1214 break; 1281 break;
1215 default: 1282 default:
1216 UNREACHABLE(); 1283 UNREACHABLE();
1217 break; 1284 break;
1218 } 1285 }
1219 } else { 1286 } else {
1220 int value = ToInteger32(LConstantOperand::cast(right)); 1287 // Mask the right_op operand.
1288 int value = ToInteger32(LConstantOperand::cast(right_op));
1221 uint8_t shift_count = static_cast<uint8_t>(value & 0x1F); 1289 uint8_t shift_count = static_cast<uint8_t>(value & 0x1F);
1222 switch (instr->op()) { 1290 switch (instr->op()) {
1223 case Token::SAR: 1291 case Token::SAR:
1224 if (shift_count != 0) { 1292 if (shift_count != 0) {
1225 __ mov(result, Operand(result, ASR, shift_count)); 1293 __ mov(result, Operand(left, ASR, shift_count));
1294 } else {
1295 __ Move(result, left);
1226 } 1296 }
1227 break; 1297 break;
1228 case Token::SHR: 1298 case Token::SHR:
1229 if (shift_count == 0 && instr->can_deopt()) { 1299 if (shift_count != 0) {
1230 __ tst(result, Operand(0x80000000)); 1300 __ mov(result, Operand(left, LSR, shift_count));
1231 DeoptimizeIf(ne, instr->environment());
1232 } else { 1301 } else {
1233 __ mov(result, Operand(result, LSR, shift_count)); 1302 if (instr->can_deopt()) {
1303 __ tst(left, Operand(0x80000000));
1304 DeoptimizeIf(ne, instr->environment());
1305 }
1306 __ Move(result, left);
1234 } 1307 }
1235 break; 1308 break;
1236 case Token::SHL: 1309 case Token::SHL:
1237 if (shift_count != 0) { 1310 if (shift_count != 0) {
1238 __ mov(result, Operand(result, LSL, shift_count)); 1311 __ mov(result, Operand(left, LSL, shift_count));
1312 } else {
1313 __ Move(result, left);
1239 } 1314 }
1240 break; 1315 break;
1241 default: 1316 default:
1242 UNREACHABLE(); 1317 UNREACHABLE();
1243 break; 1318 break;
1244 } 1319 }
1245 } 1320 }
1246 } 1321 }
1247 1322
1248 1323
1249 void LCodeGen::DoSubI(LSubI* instr) { 1324 void LCodeGen::DoSubI(LSubI* instr) {
1250 LOperand* left = instr->InputAt(0); 1325 LOperand* left = instr->InputAt(0);
1251 LOperand* right = instr->InputAt(1); 1326 LOperand* right = instr->InputAt(1);
1252 ASSERT(left->Equals(instr->result())); 1327 LOperand* result = instr->result();
1253 bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow); 1328 bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow);
1254 SBit set_cond = can_overflow ? SetCC : LeaveCC; 1329 SBit set_cond = can_overflow ? SetCC : LeaveCC;
1255 1330
1256 if (right->IsStackSlot() || right->IsArgument()) { 1331 if (right->IsStackSlot() || right->IsArgument()) {
1257 Register right_reg = EmitLoadRegister(right, ip); 1332 Register right_reg = EmitLoadRegister(right, ip);
1258 __ sub(ToRegister(left), ToRegister(left), Operand(right_reg), set_cond); 1333 __ sub(ToRegister(result), ToRegister(left), Operand(right_reg), set_cond);
1259 } else { 1334 } else {
1260 ASSERT(right->IsRegister() || right->IsConstantOperand()); 1335 ASSERT(right->IsRegister() || right->IsConstantOperand());
1261 __ sub(ToRegister(left), ToRegister(left), ToOperand(right), set_cond); 1336 __ sub(ToRegister(result), ToRegister(left), ToOperand(right), set_cond);
1262 } 1337 }
1263 1338
1264 if (can_overflow) { 1339 if (can_overflow) {
1265 DeoptimizeIf(vs, instr->environment()); 1340 DeoptimizeIf(vs, instr->environment());
1266 } 1341 }
1267 } 1342 }
1268 1343
1269 1344
1270 void LCodeGen::DoConstantI(LConstantI* instr) { 1345 void LCodeGen::DoConstantI(LConstantI* instr) {
1271 ASSERT(instr->result()->IsRegister()); 1346 ASSERT(instr->result()->IsRegister());
1272 __ mov(ToRegister(instr->result()), Operand(instr->value())); 1347 __ mov(ToRegister(instr->result()), Operand(instr->value()));
1273 } 1348 }
1274 1349
1275 1350
1276 void LCodeGen::DoConstantD(LConstantD* instr) { 1351 void LCodeGen::DoConstantD(LConstantD* instr) {
1277 ASSERT(instr->result()->IsDoubleRegister()); 1352 ASSERT(instr->result()->IsDoubleRegister());
1278 DwVfpRegister result = ToDoubleRegister(instr->result()); 1353 DwVfpRegister result = ToDoubleRegister(instr->result());
1279 double v = instr->value(); 1354 double v = instr->value();
1280 __ vmov(result, v); 1355 __ Vmov(result, v);
1281 } 1356 }
1282 1357
1283 1358
1284 void LCodeGen::DoConstantT(LConstantT* instr) { 1359 void LCodeGen::DoConstantT(LConstantT* instr) {
1285 ASSERT(instr->result()->IsRegister()); 1360 ASSERT(instr->result()->IsRegister());
1286 __ mov(ToRegister(instr->result()), Operand(instr->value())); 1361 __ mov(ToRegister(instr->result()), Operand(instr->value()));
1287 } 1362 }
1288 1363
1289 1364
1290 void LCodeGen::DoJSArrayLength(LJSArrayLength* instr) { 1365 void LCodeGen::DoJSArrayLength(LJSArrayLength* instr) {
(...skipping 10 matching lines...) Expand all
1301 } 1376 }
1302 1377
1303 1378
1304 void LCodeGen::DoFixedArrayLength(LFixedArrayLength* instr) { 1379 void LCodeGen::DoFixedArrayLength(LFixedArrayLength* instr) {
1305 Register result = ToRegister(instr->result()); 1380 Register result = ToRegister(instr->result());
1306 Register array = ToRegister(instr->InputAt(0)); 1381 Register array = ToRegister(instr->InputAt(0));
1307 __ ldr(result, FieldMemOperand(array, FixedArray::kLengthOffset)); 1382 __ ldr(result, FieldMemOperand(array, FixedArray::kLengthOffset));
1308 } 1383 }
1309 1384
1310 1385
1386 void LCodeGen::DoElementsKind(LElementsKind* instr) {
1387 Register result = ToRegister(instr->result());
1388 Register input = ToRegister(instr->InputAt(0));
1389
1390 // Load map into |result|.
1391 __ ldr(result, FieldMemOperand(input, HeapObject::kMapOffset));
1392 // Load the map's "bit field 2" into |result|. We only need the first byte,
1393 // but the following bit field extraction takes care of that anyway.
1394 __ ldr(result, FieldMemOperand(result, Map::kBitField2Offset));
1395 // Retrieve elements_kind from bit field 2.
1396 __ ubfx(result, result, Map::kElementsKindShift, Map::kElementsKindBitCount);
1397 }
1398
1399
1311 void LCodeGen::DoValueOf(LValueOf* instr) { 1400 void LCodeGen::DoValueOf(LValueOf* instr) {
1312 Register input = ToRegister(instr->InputAt(0)); 1401 Register input = ToRegister(instr->InputAt(0));
1313 Register result = ToRegister(instr->result()); 1402 Register result = ToRegister(instr->result());
1314 Register map = ToRegister(instr->TempAt(0)); 1403 Register map = ToRegister(instr->TempAt(0));
1315 ASSERT(input.is(result));
1316 Label done; 1404 Label done;
1317 1405
1318 // If the object is a smi return the object. 1406 // If the object is a smi return the object.
1319 __ tst(input, Operand(kSmiTagMask)); 1407 __ tst(input, Operand(kSmiTagMask));
1408 __ Move(result, input, eq);
1320 __ b(eq, &done); 1409 __ b(eq, &done);
1321 1410
1322 // If the object is not a value type, return the object. 1411 // If the object is not a value type, return the object.
1323 __ CompareObjectType(input, map, map, JS_VALUE_TYPE); 1412 __ CompareObjectType(input, map, map, JS_VALUE_TYPE);
1413 __ Move(result, input, ne);
1324 __ b(ne, &done); 1414 __ b(ne, &done);
1325 __ ldr(result, FieldMemOperand(input, JSValue::kValueOffset)); 1415 __ ldr(result, FieldMemOperand(input, JSValue::kValueOffset));
1326 1416
1327 __ bind(&done); 1417 __ bind(&done);
1328 } 1418 }
1329 1419
1330 1420
1331 void LCodeGen::DoBitNotI(LBitNotI* instr) { 1421 void LCodeGen::DoBitNotI(LBitNotI* instr) {
1332 LOperand* input = instr->InputAt(0); 1422 Register input = ToRegister(instr->InputAt(0));
1333 ASSERT(input->Equals(instr->result())); 1423 Register result = ToRegister(instr->result());
1334 __ mvn(ToRegister(input), Operand(ToRegister(input))); 1424 __ mvn(result, Operand(input));
1335 } 1425 }
1336 1426
1337 1427
1338 void LCodeGen::DoThrow(LThrow* instr) { 1428 void LCodeGen::DoThrow(LThrow* instr) {
1339 Register input_reg = EmitLoadRegister(instr->InputAt(0), ip); 1429 Register input_reg = EmitLoadRegister(instr->InputAt(0), ip);
1340 __ push(input_reg); 1430 __ push(input_reg);
1341 CallRuntime(Runtime::kThrow, 1, instr); 1431 CallRuntime(Runtime::kThrow, 1, instr);
1342 1432
1343 if (FLAG_debug_code) { 1433 if (FLAG_debug_code) {
1344 __ stop("Unreachable code."); 1434 __ stop("Unreachable code.");
1345 } 1435 }
1346 } 1436 }
1347 1437
1348 1438
1349 void LCodeGen::DoAddI(LAddI* instr) { 1439 void LCodeGen::DoAddI(LAddI* instr) {
1350 LOperand* left = instr->InputAt(0); 1440 LOperand* left = instr->InputAt(0);
1351 LOperand* right = instr->InputAt(1); 1441 LOperand* right = instr->InputAt(1);
1352 ASSERT(left->Equals(instr->result())); 1442 LOperand* result = instr->result();
1353 bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow); 1443 bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow);
1354 SBit set_cond = can_overflow ? SetCC : LeaveCC; 1444 SBit set_cond = can_overflow ? SetCC : LeaveCC;
1355 1445
1356 if (right->IsStackSlot() || right->IsArgument()) { 1446 if (right->IsStackSlot() || right->IsArgument()) {
1357 Register right_reg = EmitLoadRegister(right, ip); 1447 Register right_reg = EmitLoadRegister(right, ip);
1358 __ add(ToRegister(left), ToRegister(left), Operand(right_reg), set_cond); 1448 __ add(ToRegister(result), ToRegister(left), Operand(right_reg), set_cond);
1359 } else { 1449 } else {
1360 ASSERT(right->IsRegister() || right->IsConstantOperand()); 1450 ASSERT(right->IsRegister() || right->IsConstantOperand());
1361 __ add(ToRegister(left), ToRegister(left), ToOperand(right), set_cond); 1451 __ add(ToRegister(result), ToRegister(left), ToOperand(right), set_cond);
1362 } 1452 }
1363 1453
1364 if (can_overflow) { 1454 if (can_overflow) {
1365 DeoptimizeIf(vs, instr->environment()); 1455 DeoptimizeIf(vs, instr->environment());
1366 } 1456 }
1367 } 1457 }
1368 1458
1369 1459
1370 void LCodeGen::DoArithmeticD(LArithmeticD* instr) { 1460 void LCodeGen::DoArithmeticD(LArithmeticD* instr) {
1371 DoubleRegister left = ToDoubleRegister(instr->InputAt(0)); 1461 DoubleRegister left = ToDoubleRegister(instr->InputAt(0));
1372 DoubleRegister right = ToDoubleRegister(instr->InputAt(1)); 1462 DoubleRegister right = ToDoubleRegister(instr->InputAt(1));
1463 DoubleRegister result = ToDoubleRegister(instr->result());
1373 switch (instr->op()) { 1464 switch (instr->op()) {
1374 case Token::ADD: 1465 case Token::ADD:
1375 __ vadd(left, left, right); 1466 __ vadd(result, left, right);
1376 break; 1467 break;
1377 case Token::SUB: 1468 case Token::SUB:
1378 __ vsub(left, left, right); 1469 __ vsub(result, left, right);
1379 break; 1470 break;
1380 case Token::MUL: 1471 case Token::MUL:
1381 __ vmul(left, left, right); 1472 __ vmul(result, left, right);
1382 break; 1473 break;
1383 case Token::DIV: 1474 case Token::DIV:
1384 __ vdiv(left, left, right); 1475 __ vdiv(result, left, right);
1385 break; 1476 break;
1386 case Token::MOD: { 1477 case Token::MOD: {
1387 // Save r0-r3 on the stack. 1478 // Save r0-r3 on the stack.
1388 __ stm(db_w, sp, r0.bit() | r1.bit() | r2.bit() | r3.bit()); 1479 __ stm(db_w, sp, r0.bit() | r1.bit() | r2.bit() | r3.bit());
1389 1480
1390 __ PrepareCallCFunction(0, 2, scratch0()); 1481 __ PrepareCallCFunction(0, 2, scratch0());
1391 __ SetCallCDoubleArguments(left, right); 1482 __ SetCallCDoubleArguments(left, right);
1392 __ CallCFunction( 1483 __ CallCFunction(
1393 ExternalReference::double_fp_operation(Token::MOD, isolate()), 1484 ExternalReference::double_fp_operation(Token::MOD, isolate()),
1394 0, 2); 1485 0, 2);
1395 // Move the result in the double result register. 1486 // Move the result in the double result register.
1396 __ GetCFunctionDoubleResult(ToDoubleRegister(instr->result())); 1487 __ GetCFunctionDoubleResult(result);
1397 1488
1398 // Restore r0-r3. 1489 // Restore r0-r3.
1399 __ ldm(ia_w, sp, r0.bit() | r1.bit() | r2.bit() | r3.bit()); 1490 __ ldm(ia_w, sp, r0.bit() | r1.bit() | r2.bit() | r3.bit());
1400 break; 1491 break;
1401 } 1492 }
1402 default: 1493 default:
1403 UNREACHABLE(); 1494 UNREACHABLE();
1404 break; 1495 break;
1405 } 1496 }
1406 } 1497 }
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
1440 __ b(cc, chunk_->GetAssemblyLabel(left_block)); 1531 __ b(cc, chunk_->GetAssemblyLabel(left_block));
1441 __ b(chunk_->GetAssemblyLabel(right_block)); 1532 __ b(chunk_->GetAssemblyLabel(right_block));
1442 } 1533 }
1443 } 1534 }
1444 1535
1445 1536
1446 void LCodeGen::DoBranch(LBranch* instr) { 1537 void LCodeGen::DoBranch(LBranch* instr) {
1447 int true_block = chunk_->LookupDestination(instr->true_block_id()); 1538 int true_block = chunk_->LookupDestination(instr->true_block_id());
1448 int false_block = chunk_->LookupDestination(instr->false_block_id()); 1539 int false_block = chunk_->LookupDestination(instr->false_block_id());
1449 1540
1450 Representation r = instr->hydrogen()->representation(); 1541 Representation r = instr->hydrogen()->value()->representation();
1451 if (r.IsInteger32()) { 1542 if (r.IsInteger32()) {
1452 Register reg = ToRegister(instr->InputAt(0)); 1543 Register reg = ToRegister(instr->InputAt(0));
1453 __ cmp(reg, Operand(0)); 1544 __ cmp(reg, Operand(0));
1454 EmitBranch(true_block, false_block, ne); 1545 EmitBranch(true_block, false_block, ne);
1455 } else if (r.IsDouble()) { 1546 } else if (r.IsDouble()) {
1456 DoubleRegister reg = ToDoubleRegister(instr->InputAt(0)); 1547 DoubleRegister reg = ToDoubleRegister(instr->InputAt(0));
1457 Register scratch = scratch0(); 1548 Register scratch = scratch0();
1458 1549
1459 // Test the double value. Zero and NaN are false. 1550 // Test the double value. Zero and NaN are false.
1460 __ VFPCompareAndLoadFlags(reg, 0.0, scratch); 1551 __ VFPCompareAndLoadFlags(reg, 0.0, scratch);
1461 __ tst(scratch, Operand(kVFPZConditionFlagBit | kVFPVConditionFlagBit)); 1552 __ tst(scratch, Operand(kVFPZConditionFlagBit | kVFPVConditionFlagBit));
1462 EmitBranch(true_block, false_block, ne); 1553 EmitBranch(true_block, false_block, ne);
1463 } else { 1554 } else {
1464 ASSERT(r.IsTagged()); 1555 ASSERT(r.IsTagged());
1465 Register reg = ToRegister(instr->InputAt(0)); 1556 Register reg = ToRegister(instr->InputAt(0));
1466 if (instr->hydrogen()->type().IsBoolean()) { 1557 if (instr->hydrogen()->value()->type().IsBoolean()) {
1467 __ LoadRoot(ip, Heap::kTrueValueRootIndex); 1558 __ LoadRoot(ip, Heap::kTrueValueRootIndex);
1468 __ cmp(reg, ip); 1559 __ cmp(reg, ip);
1469 EmitBranch(true_block, false_block, eq); 1560 EmitBranch(true_block, false_block, eq);
1470 } else { 1561 } else {
1471 Label* true_label = chunk_->GetAssemblyLabel(true_block); 1562 Label* true_label = chunk_->GetAssemblyLabel(true_block);
1472 Label* false_label = chunk_->GetAssemblyLabel(false_block); 1563 Label* false_label = chunk_->GetAssemblyLabel(false_block);
1473 1564
1474 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); 1565 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
1475 __ cmp(reg, ip); 1566 __ cmp(reg, ip);
1476 __ b(eq, false_label); 1567 __ b(eq, false_label);
1477 __ LoadRoot(ip, Heap::kTrueValueRootIndex); 1568 __ LoadRoot(ip, Heap::kTrueValueRootIndex);
1478 __ cmp(reg, ip); 1569 __ cmp(reg, ip);
1479 __ b(eq, true_label); 1570 __ b(eq, true_label);
1480 __ LoadRoot(ip, Heap::kFalseValueRootIndex); 1571 __ LoadRoot(ip, Heap::kFalseValueRootIndex);
1481 __ cmp(reg, ip); 1572 __ cmp(reg, ip);
1482 __ b(eq, false_label); 1573 __ b(eq, false_label);
1483 __ cmp(reg, Operand(0)); 1574 __ cmp(reg, Operand(0));
1484 __ b(eq, false_label); 1575 __ b(eq, false_label);
1485 __ tst(reg, Operand(kSmiTagMask)); 1576 __ JumpIfSmi(reg, true_label);
1486 __ b(eq, true_label);
1487 1577
1488 // Test double values. Zero and NaN are false. 1578 // Test double values. Zero and NaN are false.
1489 Label call_stub; 1579 Label call_stub;
1490 DoubleRegister dbl_scratch = d0; 1580 DoubleRegister dbl_scratch = double_scratch0();
1491 Register scratch = scratch0(); 1581 Register scratch = scratch0();
1492 __ ldr(scratch, FieldMemOperand(reg, HeapObject::kMapOffset)); 1582 __ ldr(scratch, FieldMemOperand(reg, HeapObject::kMapOffset));
1493 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex); 1583 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex);
1494 __ cmp(scratch, Operand(ip)); 1584 __ cmp(scratch, Operand(ip));
1495 __ b(ne, &call_stub); 1585 __ b(ne, &call_stub);
1496 __ sub(ip, reg, Operand(kHeapObjectTag)); 1586 __ sub(ip, reg, Operand(kHeapObjectTag));
1497 __ vldr(dbl_scratch, ip, HeapNumber::kValueOffset); 1587 __ vldr(dbl_scratch, ip, HeapNumber::kValueOffset);
1498 __ VFPCompareAndLoadFlags(dbl_scratch, 0.0, scratch); 1588 __ VFPCompareAndLoadFlags(dbl_scratch, 0.0, scratch);
1499 __ tst(scratch, Operand(kVFPZConditionFlagBit | kVFPVConditionFlagBit)); 1589 __ tst(scratch, Operand(kVFPZConditionFlagBit | kVFPVConditionFlagBit));
1500 __ b(ne, false_label); 1590 __ b(ne, false_label);
1501 __ b(true_label); 1591 __ b(true_label);
1502 1592
1503 // The conversion stub doesn't cause garbage collections so it's 1593 // The conversion stub doesn't cause garbage collections so it's
1504 // safe to not record a safepoint after the call. 1594 // safe to not record a safepoint after the call.
1505 __ bind(&call_stub); 1595 __ bind(&call_stub);
1506 ToBooleanStub stub(reg); 1596 ToBooleanStub stub(reg);
1507 RegList saved_regs = kJSCallerSaved | kCalleeSaved; 1597 RegList saved_regs = kJSCallerSaved | kCalleeSaved;
1508 __ stm(db_w, sp, saved_regs); 1598 __ stm(db_w, sp, saved_regs);
1509 __ CallStub(&stub); 1599 __ CallStub(&stub);
1510 __ cmp(reg, Operand(0)); 1600 __ cmp(reg, Operand(0));
1511 __ ldm(ia_w, sp, saved_regs); 1601 __ ldm(ia_w, sp, saved_regs);
1512 EmitBranch(true_block, false_block, ne); 1602 EmitBranch(true_block, false_block, ne);
1513 } 1603 }
1514 } 1604 }
1515 } 1605 }
1516 1606
1517 1607
1518 void LCodeGen::EmitGoto(int block, LDeferredCode* deferred_stack_check) { 1608 void LCodeGen::EmitGoto(int block) {
1519 block = chunk_->LookupDestination(block); 1609 block = chunk_->LookupDestination(block);
1520 int next_block = GetNextEmittedBlock(current_block_); 1610 int next_block = GetNextEmittedBlock(current_block_);
1521 if (block != next_block) { 1611 if (block != next_block) {
1522 // Perform stack overflow check if this goto needs it before jumping. 1612 __ jmp(chunk_->GetAssemblyLabel(block));
1523 if (deferred_stack_check != NULL) {
1524 __ LoadRoot(ip, Heap::kStackLimitRootIndex);
1525 __ cmp(sp, Operand(ip));
1526 __ b(hs, chunk_->GetAssemblyLabel(block));
1527 __ jmp(deferred_stack_check->entry());
1528 deferred_stack_check->SetExit(chunk_->GetAssemblyLabel(block));
1529 } else {
1530 __ jmp(chunk_->GetAssemblyLabel(block));
1531 }
1532 } 1613 }
1533 } 1614 }
1534 1615
1535 1616
1536 void LCodeGen::DoDeferredStackCheck(LGoto* instr) { 1617 void LCodeGen::DoGoto(LGoto* instr) {
1537 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); 1618 EmitGoto(instr->block_id());
1538 CallRuntimeFromDeferred(Runtime::kStackGuard, 0, instr);
1539 } 1619 }
1540 1620
1541 1621
1542 void LCodeGen::DoGoto(LGoto* instr) {
1543 class DeferredStackCheck: public LDeferredCode {
1544 public:
1545 DeferredStackCheck(LCodeGen* codegen, LGoto* instr)
1546 : LDeferredCode(codegen), instr_(instr) { }
1547 virtual void Generate() { codegen()->DoDeferredStackCheck(instr_); }
1548 private:
1549 LGoto* instr_;
1550 };
1551
1552 DeferredStackCheck* deferred = NULL;
1553 if (instr->include_stack_check()) {
1554 deferred = new DeferredStackCheck(this, instr);
1555 }
1556 EmitGoto(instr->block_id(), deferred);
1557 }
1558
1559
1560 Condition LCodeGen::TokenToCondition(Token::Value op, bool is_unsigned) { 1622 Condition LCodeGen::TokenToCondition(Token::Value op, bool is_unsigned) {
1561 Condition cond = kNoCondition; 1623 Condition cond = kNoCondition;
1562 switch (op) { 1624 switch (op) {
1563 case Token::EQ: 1625 case Token::EQ:
1564 case Token::EQ_STRICT: 1626 case Token::EQ_STRICT:
1565 cond = eq; 1627 cond = eq;
1566 break; 1628 break;
1567 case Token::LT: 1629 case Token::LT:
1568 cond = is_unsigned ? lo : lt; 1630 cond = is_unsigned ? lo : lt;
1569 break; 1631 break;
(...skipping 13 matching lines...) Expand all
1583 } 1645 }
1584 return cond; 1646 return cond;
1585 } 1647 }
1586 1648
1587 1649
1588 void LCodeGen::EmitCmpI(LOperand* left, LOperand* right) { 1650 void LCodeGen::EmitCmpI(LOperand* left, LOperand* right) {
1589 __ cmp(ToRegister(left), ToRegister(right)); 1651 __ cmp(ToRegister(left), ToRegister(right));
1590 } 1652 }
1591 1653
1592 1654
1593 void LCodeGen::DoCmpID(LCmpID* instr) {
1594 LOperand* left = instr->InputAt(0);
1595 LOperand* right = instr->InputAt(1);
1596 LOperand* result = instr->result();
1597 Register scratch = scratch0();
1598
1599 Label unordered, done;
1600 if (instr->is_double()) {
1601 // Compare left and right as doubles and load the
1602 // resulting flags into the normal status register.
1603 __ VFPCompareAndSetFlags(ToDoubleRegister(left), ToDoubleRegister(right));
1604 // If a NaN is involved, i.e. the result is unordered (V set),
1605 // jump to unordered to return false.
1606 __ b(vs, &unordered);
1607 } else {
1608 EmitCmpI(left, right);
1609 }
1610
1611 Condition cc = TokenToCondition(instr->op(), instr->is_double());
1612 __ LoadRoot(ToRegister(result), Heap::kTrueValueRootIndex);
1613 __ b(cc, &done);
1614
1615 __ bind(&unordered);
1616 __ LoadRoot(ToRegister(result), Heap::kFalseValueRootIndex);
1617 __ bind(&done);
1618 }
1619
1620
1621 void LCodeGen::DoCmpIDAndBranch(LCmpIDAndBranch* instr) { 1655 void LCodeGen::DoCmpIDAndBranch(LCmpIDAndBranch* instr) {
1622 LOperand* left = instr->InputAt(0); 1656 LOperand* left = instr->InputAt(0);
1623 LOperand* right = instr->InputAt(1); 1657 LOperand* right = instr->InputAt(1);
1624 int false_block = chunk_->LookupDestination(instr->false_block_id()); 1658 int false_block = chunk_->LookupDestination(instr->false_block_id());
1625 int true_block = chunk_->LookupDestination(instr->true_block_id()); 1659 int true_block = chunk_->LookupDestination(instr->true_block_id());
1626 1660
1627 if (instr->is_double()) { 1661 if (instr->is_double()) {
1628 // Compare left and right as doubles and load the 1662 // Compare left and right as doubles and load the
1629 // resulting flags into the normal status register. 1663 // resulting flags into the normal status register.
1630 __ VFPCompareAndSetFlags(ToDoubleRegister(left), ToDoubleRegister(right)); 1664 __ VFPCompareAndSetFlags(ToDoubleRegister(left), ToDoubleRegister(right));
1631 // If a NaN is involved, i.e. the result is unordered (V set), 1665 // If a NaN is involved, i.e. the result is unordered (V set),
1632 // jump to false block label. 1666 // jump to false block label.
1633 __ b(vs, chunk_->GetAssemblyLabel(false_block)); 1667 __ b(vs, chunk_->GetAssemblyLabel(false_block));
1634 } else { 1668 } else {
1635 EmitCmpI(left, right); 1669 EmitCmpI(left, right);
1636 } 1670 }
1637 1671
1638 Condition cc = TokenToCondition(instr->op(), instr->is_double()); 1672 Condition cc = TokenToCondition(instr->op(), instr->is_double());
1639 EmitBranch(true_block, false_block, cc); 1673 EmitBranch(true_block, false_block, cc);
1640 } 1674 }
1641 1675
1642 1676
1643 void LCodeGen::DoCmpJSObjectEq(LCmpJSObjectEq* instr) { 1677 void LCodeGen::DoCmpObjectEqAndBranch(LCmpObjectEqAndBranch* instr) {
1644 Register left = ToRegister(instr->InputAt(0));
1645 Register right = ToRegister(instr->InputAt(1));
1646 Register result = ToRegister(instr->result());
1647
1648 __ cmp(left, Operand(right));
1649 __ LoadRoot(result, Heap::kTrueValueRootIndex, eq);
1650 __ LoadRoot(result, Heap::kFalseValueRootIndex, ne);
1651 }
1652
1653
1654 void LCodeGen::DoCmpJSObjectEqAndBranch(LCmpJSObjectEqAndBranch* instr) {
1655 Register left = ToRegister(instr->InputAt(0)); 1678 Register left = ToRegister(instr->InputAt(0));
1656 Register right = ToRegister(instr->InputAt(1)); 1679 Register right = ToRegister(instr->InputAt(1));
1657 int false_block = chunk_->LookupDestination(instr->false_block_id()); 1680 int false_block = chunk_->LookupDestination(instr->false_block_id());
1658 int true_block = chunk_->LookupDestination(instr->true_block_id()); 1681 int true_block = chunk_->LookupDestination(instr->true_block_id());
1659 1682
1660 __ cmp(left, Operand(right)); 1683 __ cmp(left, Operand(right));
1661 EmitBranch(true_block, false_block, eq); 1684 EmitBranch(true_block, false_block, eq);
1662 } 1685 }
1663 1686
1664 1687
1665 void LCodeGen::DoCmpSymbolEq(LCmpSymbolEq* instr) { 1688 void LCodeGen::DoCmpConstantEqAndBranch(LCmpConstantEqAndBranch* instr) {
1666 Register left = ToRegister(instr->InputAt(0)); 1689 Register left = ToRegister(instr->InputAt(0));
1667 Register right = ToRegister(instr->InputAt(1)); 1690 int true_block = chunk_->LookupDestination(instr->true_block_id());
1668 Register result = ToRegister(instr->result()); 1691 int false_block = chunk_->LookupDestination(instr->false_block_id());
1669 1692
1670 __ cmp(left, Operand(right)); 1693 __ cmp(left, Operand(instr->hydrogen()->right()));
1671 __ LoadRoot(result, Heap::kTrueValueRootIndex, eq);
1672 __ LoadRoot(result, Heap::kFalseValueRootIndex, ne);
1673 }
1674
1675
1676 void LCodeGen::DoCmpSymbolEqAndBranch(LCmpSymbolEqAndBranch* instr) {
1677 Register left = ToRegister(instr->InputAt(0));
1678 Register right = ToRegister(instr->InputAt(1));
1679 int false_block = chunk_->LookupDestination(instr->false_block_id());
1680 int true_block = chunk_->LookupDestination(instr->true_block_id());
1681
1682 __ cmp(left, Operand(right));
1683 EmitBranch(true_block, false_block, eq); 1694 EmitBranch(true_block, false_block, eq);
1684 } 1695 }
1685 1696
1686 1697
1687 void LCodeGen::DoIsNull(LIsNull* instr) {
1688 Register reg = ToRegister(instr->InputAt(0));
1689 Register result = ToRegister(instr->result());
1690
1691 __ LoadRoot(ip, Heap::kNullValueRootIndex);
1692 __ cmp(reg, ip);
1693 if (instr->is_strict()) {
1694 __ LoadRoot(result, Heap::kTrueValueRootIndex, eq);
1695 __ LoadRoot(result, Heap::kFalseValueRootIndex, ne);
1696 } else {
1697 Label true_value, false_value, done;
1698 __ b(eq, &true_value);
1699 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
1700 __ cmp(ip, reg);
1701 __ b(eq, &true_value);
1702 __ tst(reg, Operand(kSmiTagMask));
1703 __ b(eq, &false_value);
1704 // Check for undetectable objects by looking in the bit field in
1705 // the map. The object has already been smi checked.
1706 Register scratch = result;
1707 __ ldr(scratch, FieldMemOperand(reg, HeapObject::kMapOffset));
1708 __ ldrb(scratch, FieldMemOperand(scratch, Map::kBitFieldOffset));
1709 __ tst(scratch, Operand(1 << Map::kIsUndetectable));
1710 __ b(ne, &true_value);
1711 __ bind(&false_value);
1712 __ LoadRoot(result, Heap::kFalseValueRootIndex);
1713 __ jmp(&done);
1714 __ bind(&true_value);
1715 __ LoadRoot(result, Heap::kTrueValueRootIndex);
1716 __ bind(&done);
1717 }
1718 }
1719
1720
1721 void LCodeGen::DoIsNullAndBranch(LIsNullAndBranch* instr) { 1698 void LCodeGen::DoIsNullAndBranch(LIsNullAndBranch* instr) {
1722 Register scratch = scratch0(); 1699 Register scratch = scratch0();
1723 Register reg = ToRegister(instr->InputAt(0)); 1700 Register reg = ToRegister(instr->InputAt(0));
1724 1701
1725 // TODO(fsc): If the expression is known to be a smi, then it's 1702 // TODO(fsc): If the expression is known to be a smi, then it's
1726 // definitely not null. Jump to the false block. 1703 // definitely not null. Jump to the false block.
1727 1704
1728 int true_block = chunk_->LookupDestination(instr->true_block_id()); 1705 int true_block = chunk_->LookupDestination(instr->true_block_id());
1729 int false_block = chunk_->LookupDestination(instr->false_block_id()); 1706 int false_block = chunk_->LookupDestination(instr->false_block_id());
1730 1707
1731 __ LoadRoot(ip, Heap::kNullValueRootIndex); 1708 __ LoadRoot(ip, Heap::kNullValueRootIndex);
1732 __ cmp(reg, ip); 1709 __ cmp(reg, ip);
1733 if (instr->is_strict()) { 1710 if (instr->is_strict()) {
1734 EmitBranch(true_block, false_block, eq); 1711 EmitBranch(true_block, false_block, eq);
1735 } else { 1712 } else {
1736 Label* true_label = chunk_->GetAssemblyLabel(true_block); 1713 Label* true_label = chunk_->GetAssemblyLabel(true_block);
1737 Label* false_label = chunk_->GetAssemblyLabel(false_block); 1714 Label* false_label = chunk_->GetAssemblyLabel(false_block);
1738 __ b(eq, true_label); 1715 __ b(eq, true_label);
1739 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); 1716 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
1740 __ cmp(reg, ip); 1717 __ cmp(reg, ip);
1741 __ b(eq, true_label); 1718 __ b(eq, true_label);
1742 __ tst(reg, Operand(kSmiTagMask)); 1719 __ JumpIfSmi(reg, false_label);
1743 __ b(eq, false_label);
1744 // Check for undetectable objects by looking in the bit field in 1720 // Check for undetectable objects by looking in the bit field in
1745 // the map. The object has already been smi checked. 1721 // the map. The object has already been smi checked.
1746 __ ldr(scratch, FieldMemOperand(reg, HeapObject::kMapOffset)); 1722 __ ldr(scratch, FieldMemOperand(reg, HeapObject::kMapOffset));
1747 __ ldrb(scratch, FieldMemOperand(scratch, Map::kBitFieldOffset)); 1723 __ ldrb(scratch, FieldMemOperand(scratch, Map::kBitFieldOffset));
1748 __ tst(scratch, Operand(1 << Map::kIsUndetectable)); 1724 __ tst(scratch, Operand(1 << Map::kIsUndetectable));
1749 EmitBranch(true_block, false_block, ne); 1725 EmitBranch(true_block, false_block, ne);
1750 } 1726 }
1751 } 1727 }
1752 1728
1753 1729
1754 Condition LCodeGen::EmitIsObject(Register input, 1730 Condition LCodeGen::EmitIsObject(Register input,
1755 Register temp1, 1731 Register temp1,
1756 Register temp2,
1757 Label* is_not_object, 1732 Label* is_not_object,
1758 Label* is_object) { 1733 Label* is_object) {
1734 Register temp2 = scratch0();
1759 __ JumpIfSmi(input, is_not_object); 1735 __ JumpIfSmi(input, is_not_object);
1760 1736
1761 __ LoadRoot(temp1, Heap::kNullValueRootIndex); 1737 __ LoadRoot(temp2, Heap::kNullValueRootIndex);
1762 __ cmp(input, temp1); 1738 __ cmp(input, temp2);
1763 __ b(eq, is_object); 1739 __ b(eq, is_object);
1764 1740
1765 // Load map. 1741 // Load map.
1766 __ ldr(temp1, FieldMemOperand(input, HeapObject::kMapOffset)); 1742 __ ldr(temp1, FieldMemOperand(input, HeapObject::kMapOffset));
1767 // Undetectable objects behave like undefined. 1743 // Undetectable objects behave like undefined.
1768 __ ldrb(temp2, FieldMemOperand(temp1, Map::kBitFieldOffset)); 1744 __ ldrb(temp2, FieldMemOperand(temp1, Map::kBitFieldOffset));
1769 __ tst(temp2, Operand(1 << Map::kIsUndetectable)); 1745 __ tst(temp2, Operand(1 << Map::kIsUndetectable));
1770 __ b(ne, is_not_object); 1746 __ b(ne, is_not_object);
1771 1747
1772 // Load instance type and check that it is in object type range. 1748 // Load instance type and check that it is in object type range.
1773 __ ldrb(temp2, FieldMemOperand(temp1, Map::kInstanceTypeOffset)); 1749 __ ldrb(temp2, FieldMemOperand(temp1, Map::kInstanceTypeOffset));
1774 __ cmp(temp2, Operand(FIRST_JS_OBJECT_TYPE)); 1750 __ cmp(temp2, Operand(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE));
1775 __ b(lt, is_not_object); 1751 __ b(lt, is_not_object);
1776 __ cmp(temp2, Operand(LAST_JS_OBJECT_TYPE)); 1752 __ cmp(temp2, Operand(LAST_NONCALLABLE_SPEC_OBJECT_TYPE));
1777 return le; 1753 return le;
1778 } 1754 }
1779 1755
1780 1756
1781 void LCodeGen::DoIsObject(LIsObject* instr) {
1782 Register reg = ToRegister(instr->InputAt(0));
1783 Register result = ToRegister(instr->result());
1784 Register temp = scratch0();
1785 Label is_false, is_true, done;
1786
1787 Condition true_cond = EmitIsObject(reg, result, temp, &is_false, &is_true);
1788 __ b(true_cond, &is_true);
1789
1790 __ bind(&is_false);
1791 __ LoadRoot(result, Heap::kFalseValueRootIndex);
1792 __ b(&done);
1793
1794 __ bind(&is_true);
1795 __ LoadRoot(result, Heap::kTrueValueRootIndex);
1796
1797 __ bind(&done);
1798 }
1799
1800
1801 void LCodeGen::DoIsObjectAndBranch(LIsObjectAndBranch* instr) { 1757 void LCodeGen::DoIsObjectAndBranch(LIsObjectAndBranch* instr) {
1802 Register reg = ToRegister(instr->InputAt(0)); 1758 Register reg = ToRegister(instr->InputAt(0));
1803 Register temp1 = ToRegister(instr->TempAt(0)); 1759 Register temp1 = ToRegister(instr->TempAt(0));
1804 Register temp2 = scratch0(); 1760 Register temp2 = scratch0();
1805 1761
1806 int true_block = chunk_->LookupDestination(instr->true_block_id()); 1762 int true_block = chunk_->LookupDestination(instr->true_block_id());
1807 int false_block = chunk_->LookupDestination(instr->false_block_id()); 1763 int false_block = chunk_->LookupDestination(instr->false_block_id());
1808 Label* true_label = chunk_->GetAssemblyLabel(true_block); 1764 Label* true_label = chunk_->GetAssemblyLabel(true_block);
1809 Label* false_label = chunk_->GetAssemblyLabel(false_block); 1765 Label* false_label = chunk_->GetAssemblyLabel(false_block);
1810 1766
1811 Condition true_cond = 1767 Condition true_cond =
1812 EmitIsObject(reg, temp1, temp2, false_label, true_label); 1768 EmitIsObject(reg, temp1, false_label, true_label);
1813 1769
1814 EmitBranch(true_block, false_block, true_cond); 1770 EmitBranch(true_block, false_block, true_cond);
1815 } 1771 }
1816 1772
1817 1773
1818 void LCodeGen::DoIsSmi(LIsSmi* instr) {
1819 ASSERT(instr->hydrogen()->value()->representation().IsTagged());
1820 Register result = ToRegister(instr->result());
1821 Register input_reg = EmitLoadRegister(instr->InputAt(0), ip);
1822 __ tst(input_reg, Operand(kSmiTagMask));
1823 __ LoadRoot(result, Heap::kTrueValueRootIndex);
1824 Label done;
1825 __ b(eq, &done);
1826 __ LoadRoot(result, Heap::kFalseValueRootIndex);
1827 __ bind(&done);
1828 }
1829
1830
1831 void LCodeGen::DoIsSmiAndBranch(LIsSmiAndBranch* instr) { 1774 void LCodeGen::DoIsSmiAndBranch(LIsSmiAndBranch* instr) {
1832 int true_block = chunk_->LookupDestination(instr->true_block_id()); 1775 int true_block = chunk_->LookupDestination(instr->true_block_id());
1833 int false_block = chunk_->LookupDestination(instr->false_block_id()); 1776 int false_block = chunk_->LookupDestination(instr->false_block_id());
1834 1777
1835 Register input_reg = EmitLoadRegister(instr->InputAt(0), ip); 1778 Register input_reg = EmitLoadRegister(instr->InputAt(0), ip);
1836 __ tst(input_reg, Operand(kSmiTagMask)); 1779 __ tst(input_reg, Operand(kSmiTagMask));
1837 EmitBranch(true_block, false_block, eq); 1780 EmitBranch(true_block, false_block, eq);
1838 } 1781 }
1839 1782
1840 1783
1841 void LCodeGen::DoIsUndetectable(LIsUndetectable* instr) {
1842 Register input = ToRegister(instr->InputAt(0));
1843 Register result = ToRegister(instr->result());
1844
1845 ASSERT(instr->hydrogen()->value()->representation().IsTagged());
1846 Label false_label, done;
1847 __ JumpIfSmi(input, &false_label);
1848 __ ldr(result, FieldMemOperand(input, HeapObject::kMapOffset));
1849 __ ldrb(result, FieldMemOperand(result, Map::kBitFieldOffset));
1850 __ tst(result, Operand(1 << Map::kIsUndetectable));
1851 __ b(eq, &false_label);
1852 __ LoadRoot(result, Heap::kTrueValueRootIndex);
1853 __ jmp(&done);
1854 __ bind(&false_label);
1855 __ LoadRoot(result, Heap::kFalseValueRootIndex);
1856 __ bind(&done);
1857 }
1858
1859
1860 void LCodeGen::DoIsUndetectableAndBranch(LIsUndetectableAndBranch* instr) { 1784 void LCodeGen::DoIsUndetectableAndBranch(LIsUndetectableAndBranch* instr) {
1861 Register input = ToRegister(instr->InputAt(0)); 1785 Register input = ToRegister(instr->InputAt(0));
1862 Register temp = ToRegister(instr->TempAt(0)); 1786 Register temp = ToRegister(instr->TempAt(0));
1863 1787
1864 int true_block = chunk_->LookupDestination(instr->true_block_id()); 1788 int true_block = chunk_->LookupDestination(instr->true_block_id());
1865 int false_block = chunk_->LookupDestination(instr->false_block_id()); 1789 int false_block = chunk_->LookupDestination(instr->false_block_id());
1866 1790
1867 __ JumpIfSmi(input, chunk_->GetAssemblyLabel(false_block)); 1791 __ JumpIfSmi(input, chunk_->GetAssemblyLabel(false_block));
1868 __ ldr(temp, FieldMemOperand(input, HeapObject::kMapOffset)); 1792 __ ldr(temp, FieldMemOperand(input, HeapObject::kMapOffset));
1869 __ ldrb(temp, FieldMemOperand(temp, Map::kBitFieldOffset)); 1793 __ ldrb(temp, FieldMemOperand(temp, Map::kBitFieldOffset));
1870 __ tst(temp, Operand(1 << Map::kIsUndetectable)); 1794 __ tst(temp, Operand(1 << Map::kIsUndetectable));
1871 EmitBranch(true_block, false_block, ne); 1795 EmitBranch(true_block, false_block, ne);
1872 } 1796 }
1873 1797
1874 1798
1875 static InstanceType TestType(HHasInstanceType* instr) { 1799 static InstanceType TestType(HHasInstanceTypeAndBranch* instr) {
1876 InstanceType from = instr->from(); 1800 InstanceType from = instr->from();
1877 InstanceType to = instr->to(); 1801 InstanceType to = instr->to();
1878 if (from == FIRST_TYPE) return to; 1802 if (from == FIRST_TYPE) return to;
1879 ASSERT(from == to || to == LAST_TYPE); 1803 ASSERT(from == to || to == LAST_TYPE);
1880 return from; 1804 return from;
1881 } 1805 }
1882 1806
1883 1807
1884 static Condition BranchCondition(HHasInstanceType* instr) { 1808 static Condition BranchCondition(HHasInstanceTypeAndBranch* instr) {
1885 InstanceType from = instr->from(); 1809 InstanceType from = instr->from();
1886 InstanceType to = instr->to(); 1810 InstanceType to = instr->to();
1887 if (from == to) return eq; 1811 if (from == to) return eq;
1888 if (to == LAST_TYPE) return hs; 1812 if (to == LAST_TYPE) return hs;
1889 if (from == FIRST_TYPE) return ls; 1813 if (from == FIRST_TYPE) return ls;
1890 UNREACHABLE(); 1814 UNREACHABLE();
1891 return eq; 1815 return eq;
1892 } 1816 }
1893 1817
1894 1818
1895 void LCodeGen::DoHasInstanceType(LHasInstanceType* instr) {
1896 Register input = ToRegister(instr->InputAt(0));
1897 Register result = ToRegister(instr->result());
1898
1899 ASSERT(instr->hydrogen()->value()->representation().IsTagged());
1900 Label done;
1901 __ tst(input, Operand(kSmiTagMask));
1902 __ LoadRoot(result, Heap::kFalseValueRootIndex, eq);
1903 __ b(eq, &done);
1904 __ CompareObjectType(input, result, result, TestType(instr->hydrogen()));
1905 Condition cond = BranchCondition(instr->hydrogen());
1906 __ LoadRoot(result, Heap::kTrueValueRootIndex, cond);
1907 __ LoadRoot(result, Heap::kFalseValueRootIndex, NegateCondition(cond));
1908 __ bind(&done);
1909 }
1910
1911
1912 void LCodeGen::DoHasInstanceTypeAndBranch(LHasInstanceTypeAndBranch* instr) { 1819 void LCodeGen::DoHasInstanceTypeAndBranch(LHasInstanceTypeAndBranch* instr) {
1913 Register scratch = scratch0(); 1820 Register scratch = scratch0();
1914 Register input = ToRegister(instr->InputAt(0)); 1821 Register input = ToRegister(instr->InputAt(0));
1915 1822
1916 int true_block = chunk_->LookupDestination(instr->true_block_id()); 1823 int true_block = chunk_->LookupDestination(instr->true_block_id());
1917 int false_block = chunk_->LookupDestination(instr->false_block_id()); 1824 int false_block = chunk_->LookupDestination(instr->false_block_id());
1918 1825
1919 Label* false_label = chunk_->GetAssemblyLabel(false_block); 1826 Label* false_label = chunk_->GetAssemblyLabel(false_block);
1920 1827
1921 __ tst(input, Operand(kSmiTagMask)); 1828 __ JumpIfSmi(input, false_label);
1922 __ b(eq, false_label);
1923 1829
1924 __ CompareObjectType(input, scratch, scratch, TestType(instr->hydrogen())); 1830 __ CompareObjectType(input, scratch, scratch, TestType(instr->hydrogen()));
1925 EmitBranch(true_block, false_block, BranchCondition(instr->hydrogen())); 1831 EmitBranch(true_block, false_block, BranchCondition(instr->hydrogen()));
1926 } 1832 }
1927 1833
1928 1834
1929 void LCodeGen::DoGetCachedArrayIndex(LGetCachedArrayIndex* instr) { 1835 void LCodeGen::DoGetCachedArrayIndex(LGetCachedArrayIndex* instr) {
1930 Register input = ToRegister(instr->InputAt(0)); 1836 Register input = ToRegister(instr->InputAt(0));
1931 Register result = ToRegister(instr->result()); 1837 Register result = ToRegister(instr->result());
1932 1838
1933 if (FLAG_debug_code) { 1839 if (FLAG_debug_code) {
1934 __ AbortIfNotString(input); 1840 __ AbortIfNotString(input);
1935 } 1841 }
1936 1842
1937 __ ldr(result, FieldMemOperand(input, String::kHashFieldOffset)); 1843 __ ldr(result, FieldMemOperand(input, String::kHashFieldOffset));
1938 __ IndexFromHash(result, result); 1844 __ IndexFromHash(result, result);
1939 } 1845 }
1940 1846
1941 1847
1942 void LCodeGen::DoHasCachedArrayIndex(LHasCachedArrayIndex* instr) {
1943 Register input = ToRegister(instr->InputAt(0));
1944 Register result = ToRegister(instr->result());
1945 Register scratch = scratch0();
1946
1947 ASSERT(instr->hydrogen()->value()->representation().IsTagged());
1948 __ ldr(scratch,
1949 FieldMemOperand(input, String::kHashFieldOffset));
1950 __ tst(scratch, Operand(String::kContainsCachedArrayIndexMask));
1951 __ LoadRoot(result, Heap::kTrueValueRootIndex, eq);
1952 __ LoadRoot(result, Heap::kFalseValueRootIndex, ne);
1953 }
1954
1955
1956 void LCodeGen::DoHasCachedArrayIndexAndBranch( 1848 void LCodeGen::DoHasCachedArrayIndexAndBranch(
1957 LHasCachedArrayIndexAndBranch* instr) { 1849 LHasCachedArrayIndexAndBranch* instr) {
1958 Register input = ToRegister(instr->InputAt(0)); 1850 Register input = ToRegister(instr->InputAt(0));
1959 Register scratch = scratch0(); 1851 Register scratch = scratch0();
1960 1852
1961 int true_block = chunk_->LookupDestination(instr->true_block_id()); 1853 int true_block = chunk_->LookupDestination(instr->true_block_id());
1962 int false_block = chunk_->LookupDestination(instr->false_block_id()); 1854 int false_block = chunk_->LookupDestination(instr->false_block_id());
1963 1855
1964 __ ldr(scratch, 1856 __ ldr(scratch,
1965 FieldMemOperand(input, String::kHashFieldOffset)); 1857 FieldMemOperand(input, String::kHashFieldOffset));
1966 __ tst(scratch, Operand(String::kContainsCachedArrayIndexMask)); 1858 __ tst(scratch, Operand(String::kContainsCachedArrayIndexMask));
1967 EmitBranch(true_block, false_block, eq); 1859 EmitBranch(true_block, false_block, eq);
1968 } 1860 }
1969 1861
1970 1862
1971 // Branches to a label or falls through with the answer in flags. Trashes 1863 // Branches to a label or falls through with the answer in flags. Trashes
1972 // the temp registers, but not the input. Only input and temp2 may alias. 1864 // the temp registers, but not the input. Only input and temp2 may alias.
1973 void LCodeGen::EmitClassOfTest(Label* is_true, 1865 void LCodeGen::EmitClassOfTest(Label* is_true,
1974 Label* is_false, 1866 Label* is_false,
1975 Handle<String>class_name, 1867 Handle<String>class_name,
1976 Register input, 1868 Register input,
1977 Register temp, 1869 Register temp,
1978 Register temp2) { 1870 Register temp2) {
1979 ASSERT(!input.is(temp)); 1871 ASSERT(!input.is(temp));
1980 ASSERT(!temp.is(temp2)); // But input and temp2 may be the same register. 1872 ASSERT(!temp.is(temp2)); // But input and temp2 may be the same register.
1981 __ tst(input, Operand(kSmiTagMask)); 1873 __ JumpIfSmi(input, is_false);
1982 __ b(eq, is_false); 1874 __ CompareObjectType(input, temp, temp2, FIRST_SPEC_OBJECT_TYPE);
1983 __ CompareObjectType(input, temp, temp2, FIRST_JS_OBJECT_TYPE);
1984 __ b(lt, is_false); 1875 __ b(lt, is_false);
1985 1876
1986 // Map is now in temp. 1877 // Map is now in temp.
1987 // Functions have class 'Function'. 1878 // Functions have class 'Function'.
1988 __ CompareInstanceType(temp, temp2, JS_FUNCTION_TYPE); 1879 __ CompareInstanceType(temp, temp2, FIRST_CALLABLE_SPEC_OBJECT_TYPE);
1989 if (class_name->IsEqualTo(CStrVector("Function"))) { 1880 if (class_name->IsEqualTo(CStrVector("Function"))) {
1990 __ b(eq, is_true); 1881 __ b(ge, is_true);
1991 } else { 1882 } else {
1992 __ b(eq, is_false); 1883 __ b(ge, is_false);
1993 } 1884 }
1994 1885
1995 // Check if the constructor in the map is a function. 1886 // Check if the constructor in the map is a function.
1996 __ ldr(temp, FieldMemOperand(temp, Map::kConstructorOffset)); 1887 __ ldr(temp, FieldMemOperand(temp, Map::kConstructorOffset));
1997 1888
1998 // As long as JS_FUNCTION_TYPE is the last instance type and it is 1889 // As long as LAST_CALLABLE_SPEC_OBJECT_TYPE is the last instance type and
1999 // right after LAST_JS_OBJECT_TYPE, we can avoid checking for 1890 // FIRST_CALLABLE_SPEC_OBJECT_TYPE comes right after
2000 // LAST_JS_OBJECT_TYPE. 1891 // LAST_NONCALLABLE_SPEC_OBJECT_TYPE, we can avoid checking for the latter.
2001 ASSERT(LAST_TYPE == JS_FUNCTION_TYPE); 1892 STATIC_ASSERT(LAST_TYPE == LAST_CALLABLE_SPEC_OBJECT_TYPE);
2002 ASSERT(JS_FUNCTION_TYPE == LAST_JS_OBJECT_TYPE + 1); 1893 STATIC_ASSERT(FIRST_CALLABLE_SPEC_OBJECT_TYPE ==
1894 LAST_NONCALLABLE_SPEC_OBJECT_TYPE + 1);
2003 1895
2004 // Objects with a non-function constructor have class 'Object'. 1896 // Objects with a non-function constructor have class 'Object'.
2005 __ CompareObjectType(temp, temp2, temp2, JS_FUNCTION_TYPE); 1897 __ CompareObjectType(temp, temp2, temp2, JS_FUNCTION_TYPE);
2006 if (class_name->IsEqualTo(CStrVector("Object"))) { 1898 if (class_name->IsEqualTo(CStrVector("Object"))) {
2007 __ b(ne, is_true); 1899 __ b(ne, is_true);
2008 } else { 1900 } else {
2009 __ b(ne, is_false); 1901 __ b(ne, is_false);
2010 } 1902 }
2011 1903
2012 // temp now contains the constructor function. Grab the 1904 // temp now contains the constructor function. Grab the
2013 // instance class name from there. 1905 // instance class name from there.
2014 __ ldr(temp, FieldMemOperand(temp, JSFunction::kSharedFunctionInfoOffset)); 1906 __ ldr(temp, FieldMemOperand(temp, JSFunction::kSharedFunctionInfoOffset));
2015 __ ldr(temp, FieldMemOperand(temp, 1907 __ ldr(temp, FieldMemOperand(temp,
2016 SharedFunctionInfo::kInstanceClassNameOffset)); 1908 SharedFunctionInfo::kInstanceClassNameOffset));
2017 // The class name we are testing against is a symbol because it's a literal. 1909 // The class name we are testing against is a symbol because it's a literal.
2018 // The name in the constructor is a symbol because of the way the context is 1910 // The name in the constructor is a symbol because of the way the context is
2019 // booted. This routine isn't expected to work for random API-created 1911 // booted. This routine isn't expected to work for random API-created
2020 // classes and it doesn't have to because you can't access it with natives 1912 // classes and it doesn't have to because you can't access it with natives
2021 // syntax. Since both sides are symbols it is sufficient to use an identity 1913 // syntax. Since both sides are symbols it is sufficient to use an identity
2022 // comparison. 1914 // comparison.
2023 __ cmp(temp, Operand(class_name)); 1915 __ cmp(temp, Operand(class_name));
2024 // End with the answer in flags. 1916 // End with the answer in flags.
2025 } 1917 }
2026 1918
2027 1919
2028 void LCodeGen::DoClassOfTest(LClassOfTest* instr) {
2029 Register input = ToRegister(instr->InputAt(0));
2030 Register result = ToRegister(instr->result());
2031 ASSERT(input.is(result));
2032 Handle<String> class_name = instr->hydrogen()->class_name();
2033
2034 Label done, is_true, is_false;
2035
2036 EmitClassOfTest(&is_true, &is_false, class_name, input, scratch0(), input);
2037 __ b(ne, &is_false);
2038
2039 __ bind(&is_true);
2040 __ LoadRoot(result, Heap::kTrueValueRootIndex);
2041 __ jmp(&done);
2042
2043 __ bind(&is_false);
2044 __ LoadRoot(result, Heap::kFalseValueRootIndex);
2045 __ bind(&done);
2046 }
2047
2048
2049 void LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) { 1920 void LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) {
2050 Register input = ToRegister(instr->InputAt(0)); 1921 Register input = ToRegister(instr->InputAt(0));
2051 Register temp = scratch0(); 1922 Register temp = scratch0();
2052 Register temp2 = ToRegister(instr->TempAt(0)); 1923 Register temp2 = ToRegister(instr->TempAt(0));
2053 Handle<String> class_name = instr->hydrogen()->class_name(); 1924 Handle<String> class_name = instr->hydrogen()->class_name();
2054 1925
2055 int true_block = chunk_->LookupDestination(instr->true_block_id()); 1926 int true_block = chunk_->LookupDestination(instr->true_block_id());
2056 int false_block = chunk_->LookupDestination(instr->false_block_id()); 1927 int false_block = chunk_->LookupDestination(instr->false_block_id());
2057 1928
2058 Label* true_label = chunk_->GetAssemblyLabel(true_block); 1929 Label* true_label = chunk_->GetAssemblyLabel(true_block);
(...skipping 23 matching lines...) Expand all
2082 1953
2083 InstanceofStub stub(InstanceofStub::kArgsInRegisters); 1954 InstanceofStub stub(InstanceofStub::kArgsInRegisters);
2084 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); 1955 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
2085 1956
2086 __ cmp(r0, Operand(0)); 1957 __ cmp(r0, Operand(0));
2087 __ mov(r0, Operand(factory()->false_value()), LeaveCC, ne); 1958 __ mov(r0, Operand(factory()->false_value()), LeaveCC, ne);
2088 __ mov(r0, Operand(factory()->true_value()), LeaveCC, eq); 1959 __ mov(r0, Operand(factory()->true_value()), LeaveCC, eq);
2089 } 1960 }
2090 1961
2091 1962
2092 void LCodeGen::DoInstanceOfAndBranch(LInstanceOfAndBranch* instr) {
2093 ASSERT(ToRegister(instr->InputAt(0)).is(r0)); // Object is in r0.
2094 ASSERT(ToRegister(instr->InputAt(1)).is(r1)); // Function is in r1.
2095
2096 int true_block = chunk_->LookupDestination(instr->true_block_id());
2097 int false_block = chunk_->LookupDestination(instr->false_block_id());
2098
2099 InstanceofStub stub(InstanceofStub::kArgsInRegisters);
2100 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
2101 __ cmp(r0, Operand(0));
2102 EmitBranch(true_block, false_block, eq);
2103 }
2104
2105
2106 void LCodeGen::DoInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr) { 1963 void LCodeGen::DoInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr) {
2107 class DeferredInstanceOfKnownGlobal: public LDeferredCode { 1964 class DeferredInstanceOfKnownGlobal: public LDeferredCode {
2108 public: 1965 public:
2109 DeferredInstanceOfKnownGlobal(LCodeGen* codegen, 1966 DeferredInstanceOfKnownGlobal(LCodeGen* codegen,
2110 LInstanceOfKnownGlobal* instr) 1967 LInstanceOfKnownGlobal* instr)
2111 : LDeferredCode(codegen), instr_(instr) { } 1968 : LDeferredCode(codegen), instr_(instr) { }
2112 virtual void Generate() { 1969 virtual void Generate() {
2113 codegen()->DoDeferredLInstanceOfKnownGlobal(instr_, &map_check_); 1970 codegen()->DoDeferredLInstanceOfKnownGlobal(instr_, &map_check_);
2114 } 1971 }
2115 1972
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after
2250 } 2107 }
2251 __ LoadRoot(ToRegister(instr->result()), 2108 __ LoadRoot(ToRegister(instr->result()),
2252 Heap::kTrueValueRootIndex, 2109 Heap::kTrueValueRootIndex,
2253 condition); 2110 condition);
2254 __ LoadRoot(ToRegister(instr->result()), 2111 __ LoadRoot(ToRegister(instr->result()),
2255 Heap::kFalseValueRootIndex, 2112 Heap::kFalseValueRootIndex,
2256 NegateCondition(condition)); 2113 NegateCondition(condition));
2257 } 2114 }
2258 2115
2259 2116
2260 void LCodeGen::DoCmpTAndBranch(LCmpTAndBranch* instr) {
2261 Token::Value op = instr->op();
2262 int true_block = chunk_->LookupDestination(instr->true_block_id());
2263 int false_block = chunk_->LookupDestination(instr->false_block_id());
2264
2265 Handle<Code> ic = CompareIC::GetUninitialized(op);
2266 CallCode(ic, RelocInfo::CODE_TARGET, instr);
2267
2268 // The compare stub expects compare condition and the input operands
2269 // reversed for GT and LTE.
2270 Condition condition = ComputeCompareCondition(op);
2271 if (op == Token::GT || op == Token::LTE) {
2272 condition = ReverseCondition(condition);
2273 }
2274 __ cmp(r0, Operand(0));
2275 EmitBranch(true_block, false_block, condition);
2276 }
2277
2278
2279 void LCodeGen::DoReturn(LReturn* instr) { 2117 void LCodeGen::DoReturn(LReturn* instr) {
2280 if (FLAG_trace) { 2118 if (FLAG_trace) {
2281 // Push the return value on the stack as the parameter. 2119 // Push the return value on the stack as the parameter.
2282 // Runtime::TraceExit returns its parameter in r0. 2120 // Runtime::TraceExit returns its parameter in r0.
2283 __ push(r0); 2121 __ push(r0);
2284 __ CallRuntime(Runtime::kTraceExit, 1); 2122 __ CallRuntime(Runtime::kTraceExit, 1);
2285 } 2123 }
2286 int32_t sp_delta = (GetParameterCount() + 1) * kPointerSize; 2124 int32_t sp_delta = (GetParameterCount() + 1) * kPointerSize;
2287 __ mov(sp, fp); 2125 __ mov(sp, fp);
2288 __ ldm(ia_w, sp, fp.bit() | lr.bit()); 2126 __ ldm(ia_w, sp, fp.bit() | lr.bit());
(...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after
2512 } 2350 }
2513 2351
2514 2352
2515 void LCodeGen::DoLoadElements(LLoadElements* instr) { 2353 void LCodeGen::DoLoadElements(LLoadElements* instr) {
2516 Register result = ToRegister(instr->result()); 2354 Register result = ToRegister(instr->result());
2517 Register input = ToRegister(instr->InputAt(0)); 2355 Register input = ToRegister(instr->InputAt(0));
2518 Register scratch = scratch0(); 2356 Register scratch = scratch0();
2519 2357
2520 __ ldr(result, FieldMemOperand(input, JSObject::kElementsOffset)); 2358 __ ldr(result, FieldMemOperand(input, JSObject::kElementsOffset));
2521 if (FLAG_debug_code) { 2359 if (FLAG_debug_code) {
2522 Label done; 2360 Label done, fail;
2523 __ ldr(scratch, FieldMemOperand(result, HeapObject::kMapOffset)); 2361 __ ldr(scratch, FieldMemOperand(result, HeapObject::kMapOffset));
2524 __ LoadRoot(ip, Heap::kFixedArrayMapRootIndex); 2362 __ LoadRoot(ip, Heap::kFixedArrayMapRootIndex);
2525 __ cmp(scratch, ip); 2363 __ cmp(scratch, ip);
2526 __ b(eq, &done); 2364 __ b(eq, &done);
2527 __ LoadRoot(ip, Heap::kFixedCOWArrayMapRootIndex); 2365 __ LoadRoot(ip, Heap::kFixedCOWArrayMapRootIndex);
2528 __ cmp(scratch, ip); 2366 __ cmp(scratch, ip);
2529 __ b(eq, &done); 2367 __ b(eq, &done);
2530 __ ldr(scratch, FieldMemOperand(result, HeapObject::kMapOffset)); 2368 // |scratch| still contains |input|'s map.
2531 __ ldrb(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset)); 2369 __ ldr(scratch, FieldMemOperand(scratch, Map::kBitField2Offset));
2532 __ sub(scratch, scratch, Operand(FIRST_EXTERNAL_ARRAY_TYPE)); 2370 __ ubfx(scratch, scratch, Map::kElementsKindShift,
2533 __ cmp(scratch, Operand(kExternalArrayTypeCount)); 2371 Map::kElementsKindBitCount);
2534 __ Check(cc, "Check for fast elements failed."); 2372 __ cmp(scratch, Operand(JSObject::FAST_ELEMENTS));
2373 __ b(eq, &done);
2374 __ cmp(scratch, Operand(JSObject::FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND));
2375 __ b(lt, &fail);
2376 __ cmp(scratch, Operand(JSObject::LAST_EXTERNAL_ARRAY_ELEMENTS_KIND));
2377 __ b(le, &done);
2378 __ bind(&fail);
2379 __ Abort("Check for fast or external elements failed.");
2535 __ bind(&done); 2380 __ bind(&done);
2536 } 2381 }
2537 } 2382 }
2538 2383
2539 2384
2540 void LCodeGen::DoLoadExternalArrayPointer( 2385 void LCodeGen::DoLoadExternalArrayPointer(
2541 LLoadExternalArrayPointer* instr) { 2386 LLoadExternalArrayPointer* instr) {
2542 Register to_reg = ToRegister(instr->result()); 2387 Register to_reg = ToRegister(instr->result());
2543 Register from_reg = ToRegister(instr->InputAt(0)); 2388 Register from_reg = ToRegister(instr->InputAt(0));
2544 __ ldr(to_reg, FieldMemOperand(from_reg, 2389 __ ldr(to_reg, FieldMemOperand(from_reg,
(...skipping 17 matching lines...) Expand all
2562 __ add(length, length, Operand(1)); 2407 __ add(length, length, Operand(1));
2563 __ ldr(result, MemOperand(arguments, length, LSL, kPointerSizeLog2)); 2408 __ ldr(result, MemOperand(arguments, length, LSL, kPointerSizeLog2));
2564 } 2409 }
2565 2410
2566 2411
2567 void LCodeGen::DoLoadKeyedFastElement(LLoadKeyedFastElement* instr) { 2412 void LCodeGen::DoLoadKeyedFastElement(LLoadKeyedFastElement* instr) {
2568 Register elements = ToRegister(instr->elements()); 2413 Register elements = ToRegister(instr->elements());
2569 Register key = EmitLoadRegister(instr->key(), scratch0()); 2414 Register key = EmitLoadRegister(instr->key(), scratch0());
2570 Register result = ToRegister(instr->result()); 2415 Register result = ToRegister(instr->result());
2571 Register scratch = scratch0(); 2416 Register scratch = scratch0();
2572 ASSERT(result.is(elements));
2573 2417
2574 // Load the result. 2418 // Load the result.
2575 __ add(scratch, elements, Operand(key, LSL, kPointerSizeLog2)); 2419 __ add(scratch, elements, Operand(key, LSL, kPointerSizeLog2));
2576 __ ldr(result, FieldMemOperand(scratch, FixedArray::kHeaderSize)); 2420 __ ldr(result, FieldMemOperand(scratch, FixedArray::kHeaderSize));
2577 2421
2578 // Check for the hole value. 2422 // Check for the hole value.
2579 if (instr->hydrogen()->RequiresHoleCheck()) { 2423 if (instr->hydrogen()->RequiresHoleCheck()) {
2580 __ LoadRoot(scratch, Heap::kTheHoleValueRootIndex); 2424 __ LoadRoot(scratch, Heap::kTheHoleValueRootIndex);
2581 __ cmp(result, scratch); 2425 __ cmp(result, scratch);
2582 DeoptimizeIf(eq, instr->environment()); 2426 DeoptimizeIf(eq, instr->environment());
2583 } 2427 }
2584 } 2428 }
2585 2429
2586 2430
2587 void LCodeGen::DoLoadKeyedSpecializedArrayElement( 2431 void LCodeGen::DoLoadKeyedSpecializedArrayElement(
2588 LLoadKeyedSpecializedArrayElement* instr) { 2432 LLoadKeyedSpecializedArrayElement* instr) {
2589 Register external_pointer = ToRegister(instr->external_pointer()); 2433 Register external_pointer = ToRegister(instr->external_pointer());
2590 Register key = no_reg; 2434 Register key = no_reg;
2591 ExternalArrayType array_type = instr->array_type(); 2435 JSObject::ElementsKind elements_kind = instr->elements_kind();
2592 bool key_is_constant = instr->key()->IsConstantOperand(); 2436 bool key_is_constant = instr->key()->IsConstantOperand();
2593 int constant_key = 0; 2437 int constant_key = 0;
2594 if (key_is_constant) { 2438 if (key_is_constant) {
2595 constant_key = ToInteger32(LConstantOperand::cast(instr->key())); 2439 constant_key = ToInteger32(LConstantOperand::cast(instr->key()));
2596 if (constant_key & 0xF0000000) { 2440 if (constant_key & 0xF0000000) {
2597 Abort("array index constant value too big."); 2441 Abort("array index constant value too big.");
2598 } 2442 }
2599 } else { 2443 } else {
2600 key = ToRegister(instr->key()); 2444 key = ToRegister(instr->key());
2601 } 2445 }
2602 int shift_size = ExternalArrayTypeToShiftSize(array_type); 2446 int shift_size = ElementsKindToShiftSize(elements_kind);
2603 2447
2604 if (array_type == kExternalFloatArray || array_type == kExternalDoubleArray) { 2448 if (elements_kind == JSObject::EXTERNAL_FLOAT_ELEMENTS ||
2449 elements_kind == JSObject::EXTERNAL_DOUBLE_ELEMENTS) {
2605 CpuFeatures::Scope scope(VFP3); 2450 CpuFeatures::Scope scope(VFP3);
2606 DwVfpRegister result(ToDoubleRegister(instr->result())); 2451 DwVfpRegister result(ToDoubleRegister(instr->result()));
2607 Operand operand(key_is_constant ? Operand(constant_key * (1 << shift_size)) 2452 Operand operand(key_is_constant ? Operand(constant_key * (1 << shift_size))
2608 : Operand(key, LSL, shift_size)); 2453 : Operand(key, LSL, shift_size));
2609 __ add(scratch0(), external_pointer, operand); 2454 __ add(scratch0(), external_pointer, operand);
2610 if (array_type == kExternalFloatArray) { 2455 if (elements_kind == JSObject::EXTERNAL_FLOAT_ELEMENTS) {
2611 __ vldr(result.low(), scratch0(), 0); 2456 __ vldr(result.low(), scratch0(), 0);
2612 __ vcvt_f64_f32(result, result.low()); 2457 __ vcvt_f64_f32(result, result.low());
2613 } else { // i.e. array_type == kExternalDoubleArray 2458 } else { // i.e. elements_kind == JSObject::EXTERNAL_DOUBLE_ELEMENTS
2614 __ vldr(result, scratch0(), 0); 2459 __ vldr(result, scratch0(), 0);
2615 } 2460 }
2616 } else { 2461 } else {
2617 Register result(ToRegister(instr->result())); 2462 Register result(ToRegister(instr->result()));
2618 MemOperand mem_operand(key_is_constant 2463 MemOperand mem_operand(key_is_constant
2619 ? MemOperand(external_pointer, constant_key * (1 << shift_size)) 2464 ? MemOperand(external_pointer, constant_key * (1 << shift_size))
2620 : MemOperand(external_pointer, key, LSL, shift_size)); 2465 : MemOperand(external_pointer, key, LSL, shift_size));
2621 switch (array_type) { 2466 switch (elements_kind) {
2622 case kExternalByteArray: 2467 case JSObject::EXTERNAL_BYTE_ELEMENTS:
2623 __ ldrsb(result, mem_operand); 2468 __ ldrsb(result, mem_operand);
2624 break; 2469 break;
2625 case kExternalUnsignedByteArray: 2470 case JSObject::EXTERNAL_PIXEL_ELEMENTS:
2626 case kExternalPixelArray: 2471 case JSObject::EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
2627 __ ldrb(result, mem_operand); 2472 __ ldrb(result, mem_operand);
2628 break; 2473 break;
2629 case kExternalShortArray: 2474 case JSObject::EXTERNAL_SHORT_ELEMENTS:
2630 __ ldrsh(result, mem_operand); 2475 __ ldrsh(result, mem_operand);
2631 break; 2476 break;
2632 case kExternalUnsignedShortArray: 2477 case JSObject::EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
2633 __ ldrh(result, mem_operand); 2478 __ ldrh(result, mem_operand);
2634 break; 2479 break;
2635 case kExternalIntArray: 2480 case JSObject::EXTERNAL_INT_ELEMENTS:
2636 __ ldr(result, mem_operand); 2481 __ ldr(result, mem_operand);
2637 break; 2482 break;
2638 case kExternalUnsignedIntArray: 2483 case JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS:
2639 __ ldr(result, mem_operand); 2484 __ ldr(result, mem_operand);
2640 __ cmp(result, Operand(0x80000000)); 2485 __ cmp(result, Operand(0x80000000));
2641 // TODO(danno): we could be more clever here, perhaps having a special 2486 // TODO(danno): we could be more clever here, perhaps having a special
2642 // version of the stub that detects if the overflow case actually 2487 // version of the stub that detects if the overflow case actually
2643 // happens, and generate code that returns a double rather than int. 2488 // happens, and generate code that returns a double rather than int.
2644 DeoptimizeIf(cs, instr->environment()); 2489 DeoptimizeIf(cs, instr->environment());
2645 break; 2490 break;
2646 case kExternalFloatArray: 2491 case JSObject::EXTERNAL_FLOAT_ELEMENTS:
2647 case kExternalDoubleArray: 2492 case JSObject::EXTERNAL_DOUBLE_ELEMENTS:
2493 case JSObject::FAST_DOUBLE_ELEMENTS:
2494 case JSObject::FAST_ELEMENTS:
2495 case JSObject::DICTIONARY_ELEMENTS:
2496 case JSObject::NON_STRICT_ARGUMENTS_ELEMENTS:
2648 UNREACHABLE(); 2497 UNREACHABLE();
2649 break; 2498 break;
2650 } 2499 }
2651 } 2500 }
2652 } 2501 }
2653 2502
2654 2503
2655 void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) { 2504 void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) {
2656 ASSERT(ToRegister(instr->object()).is(r1)); 2505 ASSERT(ToRegister(instr->object()).is(r1));
2657 ASSERT(ToRegister(instr->key()).is(r0)); 2506 ASSERT(ToRegister(instr->key()).is(r0));
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
2703 void LCodeGen::DoApplyArguments(LApplyArguments* instr) { 2552 void LCodeGen::DoApplyArguments(LApplyArguments* instr) {
2704 Register receiver = ToRegister(instr->receiver()); 2553 Register receiver = ToRegister(instr->receiver());
2705 Register function = ToRegister(instr->function()); 2554 Register function = ToRegister(instr->function());
2706 Register length = ToRegister(instr->length()); 2555 Register length = ToRegister(instr->length());
2707 Register elements = ToRegister(instr->elements()); 2556 Register elements = ToRegister(instr->elements());
2708 Register scratch = scratch0(); 2557 Register scratch = scratch0();
2709 ASSERT(receiver.is(r0)); // Used for parameter count. 2558 ASSERT(receiver.is(r0)); // Used for parameter count.
2710 ASSERT(function.is(r1)); // Required by InvokeFunction. 2559 ASSERT(function.is(r1)); // Required by InvokeFunction.
2711 ASSERT(ToRegister(instr->result()).is(r0)); 2560 ASSERT(ToRegister(instr->result()).is(r0));
2712 2561
2713 // If the receiver is null or undefined, we have to pass the global object 2562 // If the receiver is null or undefined, we have to pass the global
2714 // as a receiver. 2563 // object as a receiver to normal functions. Values have to be
2564 // passed unchanged to builtins and strict-mode functions.
2715 Label global_object, receiver_ok; 2565 Label global_object, receiver_ok;
2566
2567 // Do not transform the receiver to object for strict mode
2568 // functions.
2569 __ ldr(scratch,
2570 FieldMemOperand(function, JSFunction::kSharedFunctionInfoOffset));
2571 __ ldr(scratch,
2572 FieldMemOperand(scratch, SharedFunctionInfo::kCompilerHintsOffset));
2573 __ tst(scratch,
2574 Operand(1 << (SharedFunctionInfo::kStrictModeFunction + kSmiTagSize)));
2575 __ b(ne, &receiver_ok);
2576
2577 // Do not transform the receiver to object for builtins.
2578 __ tst(scratch, Operand(1 << (SharedFunctionInfo::kNative + kSmiTagSize)));
2579 __ b(ne, &receiver_ok);
2580
2581 // Normal function. Replace undefined or null with global receiver.
2716 __ LoadRoot(scratch, Heap::kNullValueRootIndex); 2582 __ LoadRoot(scratch, Heap::kNullValueRootIndex);
2717 __ cmp(receiver, scratch); 2583 __ cmp(receiver, scratch);
2718 __ b(eq, &global_object); 2584 __ b(eq, &global_object);
2719 __ LoadRoot(scratch, Heap::kUndefinedValueRootIndex); 2585 __ LoadRoot(scratch, Heap::kUndefinedValueRootIndex);
2720 __ cmp(receiver, scratch); 2586 __ cmp(receiver, scratch);
2721 __ b(eq, &global_object); 2587 __ b(eq, &global_object);
2722 2588
2723 // Deoptimize if the receiver is not a JS object. 2589 // Deoptimize if the receiver is not a JS object.
2724 __ tst(receiver, Operand(kSmiTagMask)); 2590 __ tst(receiver, Operand(kSmiTagMask));
2725 DeoptimizeIf(eq, instr->environment()); 2591 DeoptimizeIf(eq, instr->environment());
2726 __ CompareObjectType(receiver, scratch, scratch, FIRST_JS_OBJECT_TYPE); 2592 __ CompareObjectType(receiver, scratch, scratch, FIRST_SPEC_OBJECT_TYPE);
2727 DeoptimizeIf(lo, instr->environment()); 2593 DeoptimizeIf(lt, instr->environment());
2728 __ jmp(&receiver_ok); 2594 __ jmp(&receiver_ok);
2729 2595
2730 __ bind(&global_object); 2596 __ bind(&global_object);
2731 __ ldr(receiver, GlobalObjectOperand()); 2597 __ ldr(receiver, GlobalObjectOperand());
2598 __ ldr(receiver,
2599 FieldMemOperand(receiver, JSGlobalObject::kGlobalReceiverOffset));
2732 __ bind(&receiver_ok); 2600 __ bind(&receiver_ok);
2733 2601
2734 // Copy the arguments to this function possibly from the 2602 // Copy the arguments to this function possibly from the
2735 // adaptor frame below it. 2603 // adaptor frame below it.
2736 const uint32_t kArgumentsLimit = 1 * KB; 2604 const uint32_t kArgumentsLimit = 1 * KB;
2737 __ cmp(length, Operand(kArgumentsLimit)); 2605 __ cmp(length, Operand(kArgumentsLimit));
2738 DeoptimizeIf(hi, instr->environment()); 2606 DeoptimizeIf(hi, instr->environment());
2739 2607
2740 // Push the receiver and use the register to keep the original 2608 // Push the receiver and use the register to keep the original
2741 // number of arguments. 2609 // number of arguments.
(...skipping 19 matching lines...) Expand all
2761 LPointerMap* pointers = instr->pointer_map(); 2629 LPointerMap* pointers = instr->pointer_map();
2762 LEnvironment* env = instr->deoptimization_environment(); 2630 LEnvironment* env = instr->deoptimization_environment();
2763 RecordPosition(pointers->position()); 2631 RecordPosition(pointers->position());
2764 RegisterEnvironmentForDeoptimization(env); 2632 RegisterEnvironmentForDeoptimization(env);
2765 SafepointGenerator safepoint_generator(this, 2633 SafepointGenerator safepoint_generator(this,
2766 pointers, 2634 pointers,
2767 env->deoptimization_index()); 2635 env->deoptimization_index());
2768 // The number of arguments is stored in receiver which is r0, as expected 2636 // The number of arguments is stored in receiver which is r0, as expected
2769 // by InvokeFunction. 2637 // by InvokeFunction.
2770 v8::internal::ParameterCount actual(receiver); 2638 v8::internal::ParameterCount actual(receiver);
2771 __ InvokeFunction(function, actual, CALL_FUNCTION, safepoint_generator); 2639 __ InvokeFunction(function, actual, CALL_FUNCTION,
2640 safepoint_generator, CALL_AS_METHOD);
2772 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 2641 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
2773 } 2642 }
2774 2643
2775 2644
2776 void LCodeGen::DoPushArgument(LPushArgument* instr) { 2645 void LCodeGen::DoPushArgument(LPushArgument* instr) {
2777 LOperand* argument = instr->InputAt(0); 2646 LOperand* argument = instr->InputAt(0);
2778 if (argument->IsDoubleRegister() || argument->IsDoubleStackSlot()) { 2647 if (argument->IsDoubleRegister() || argument->IsDoubleStackSlot()) {
2779 Abort("DoPushArgument not implemented for double type."); 2648 Abort("DoPushArgument not implemented for double type.");
2780 } else { 2649 } else {
2781 Register argument_reg = EmitLoadRegister(argument, ip); 2650 Register argument_reg = EmitLoadRegister(argument, ip);
2782 __ push(argument_reg); 2651 __ push(argument_reg);
2783 } 2652 }
2784 } 2653 }
2785 2654
2786 2655
2656 void LCodeGen::DoThisFunction(LThisFunction* instr) {
2657 Register result = ToRegister(instr->result());
2658 __ ldr(result, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
2659 }
2660
2661
2787 void LCodeGen::DoContext(LContext* instr) { 2662 void LCodeGen::DoContext(LContext* instr) {
2788 Register result = ToRegister(instr->result()); 2663 Register result = ToRegister(instr->result());
2789 __ mov(result, cp); 2664 __ mov(result, cp);
2790 } 2665 }
2791 2666
2792 2667
2793 void LCodeGen::DoOuterContext(LOuterContext* instr) { 2668 void LCodeGen::DoOuterContext(LOuterContext* instr) {
2794 Register context = ToRegister(instr->context()); 2669 Register context = ToRegister(instr->context());
2795 Register result = ToRegister(instr->result()); 2670 Register result = ToRegister(instr->result());
2796 __ ldr(result, 2671 __ ldr(result,
2797 MemOperand(context, Context::SlotOffset(Context::CLOSURE_INDEX))); 2672 MemOperand(context, Context::SlotOffset(Context::PREVIOUS_INDEX)));
2798 __ ldr(result, FieldMemOperand(result, JSFunction::kContextOffset));
2799 } 2673 }
2800 2674
2801 2675
2802 void LCodeGen::DoGlobalObject(LGlobalObject* instr) { 2676 void LCodeGen::DoGlobalObject(LGlobalObject* instr) {
2803 Register context = ToRegister(instr->context()); 2677 Register context = ToRegister(instr->context());
2804 Register result = ToRegister(instr->result()); 2678 Register result = ToRegister(instr->result());
2805 __ ldr(result, ContextOperand(cp, Context::GLOBAL_INDEX)); 2679 __ ldr(result, ContextOperand(cp, Context::GLOBAL_INDEX));
2806 } 2680 }
2807 2681
2808 2682
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
2852 ASSERT(ToRegister(instr->result()).is(r0)); 2726 ASSERT(ToRegister(instr->result()).is(r0));
2853 __ mov(r1, Operand(instr->function())); 2727 __ mov(r1, Operand(instr->function()));
2854 CallKnownFunction(instr->function(), 2728 CallKnownFunction(instr->function(),
2855 instr->arity(), 2729 instr->arity(),
2856 instr, 2730 instr,
2857 CALL_AS_METHOD); 2731 CALL_AS_METHOD);
2858 } 2732 }
2859 2733
2860 2734
2861 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LUnaryMathOperation* instr) { 2735 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LUnaryMathOperation* instr) {
2862 ASSERT(instr->InputAt(0)->Equals(instr->result()));
2863 Register input = ToRegister(instr->InputAt(0)); 2736 Register input = ToRegister(instr->InputAt(0));
2737 Register result = ToRegister(instr->result());
2864 Register scratch = scratch0(); 2738 Register scratch = scratch0();
2865 2739
2866 // Deoptimize if not a heap number. 2740 // Deoptimize if not a heap number.
2867 __ ldr(scratch, FieldMemOperand(input, HeapObject::kMapOffset)); 2741 __ ldr(scratch, FieldMemOperand(input, HeapObject::kMapOffset));
2868 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex); 2742 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex);
2869 __ cmp(scratch, Operand(ip)); 2743 __ cmp(scratch, Operand(ip));
2870 DeoptimizeIf(ne, instr->environment()); 2744 DeoptimizeIf(ne, instr->environment());
2871 2745
2872 Label done; 2746 Label done;
2873 Register exponent = scratch0(); 2747 Register exponent = scratch0();
2874 scratch = no_reg; 2748 scratch = no_reg;
2875 __ ldr(exponent, FieldMemOperand(input, HeapNumber::kExponentOffset)); 2749 __ ldr(exponent, FieldMemOperand(input, HeapNumber::kExponentOffset));
2876 // Check the sign of the argument. If the argument is positive, just 2750 // Check the sign of the argument. If the argument is positive, just
2877 // return it. We do not need to patch the stack since |input| and 2751 // return it.
2878 // |result| are the same register and |input| would be restored
2879 // unchanged by popping safepoint registers.
2880 __ tst(exponent, Operand(HeapNumber::kSignMask)); 2752 __ tst(exponent, Operand(HeapNumber::kSignMask));
2753 // Move the input to the result if necessary.
2754 __ Move(result, input);
2881 __ b(eq, &done); 2755 __ b(eq, &done);
2882 2756
2883 // Input is negative. Reverse its sign. 2757 // Input is negative. Reverse its sign.
2884 // Preserve the value of all registers. 2758 // Preserve the value of all registers.
2885 { 2759 {
2886 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); 2760 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters);
2887 2761
2888 // Registers were saved at the safepoint, so we can use 2762 // Registers were saved at the safepoint, so we can use
2889 // many scratch registers. 2763 // many scratch registers.
2890 Register tmp1 = input.is(r1) ? r0 : r1; 2764 Register tmp1 = input.is(r1) ? r0 : r1;
(...skipping 19 matching lines...) Expand all
2910 __ ldr(exponent, FieldMemOperand(input, HeapNumber::kExponentOffset)); 2784 __ ldr(exponent, FieldMemOperand(input, HeapNumber::kExponentOffset));
2911 2785
2912 __ bind(&allocated); 2786 __ bind(&allocated);
2913 // exponent: floating point exponent value. 2787 // exponent: floating point exponent value.
2914 // tmp1: allocated heap number. 2788 // tmp1: allocated heap number.
2915 __ bic(exponent, exponent, Operand(HeapNumber::kSignMask)); 2789 __ bic(exponent, exponent, Operand(HeapNumber::kSignMask));
2916 __ str(exponent, FieldMemOperand(tmp1, HeapNumber::kExponentOffset)); 2790 __ str(exponent, FieldMemOperand(tmp1, HeapNumber::kExponentOffset));
2917 __ ldr(tmp2, FieldMemOperand(input, HeapNumber::kMantissaOffset)); 2791 __ ldr(tmp2, FieldMemOperand(input, HeapNumber::kMantissaOffset));
2918 __ str(tmp2, FieldMemOperand(tmp1, HeapNumber::kMantissaOffset)); 2792 __ str(tmp2, FieldMemOperand(tmp1, HeapNumber::kMantissaOffset));
2919 2793
2920 __ StoreToSafepointRegisterSlot(tmp1, input); 2794 __ StoreToSafepointRegisterSlot(tmp1, result);
2921 } 2795 }
2922 2796
2923 __ bind(&done); 2797 __ bind(&done);
2924 } 2798 }
2925 2799
2926 2800
2927 void LCodeGen::EmitIntegerMathAbs(LUnaryMathOperation* instr) { 2801 void LCodeGen::EmitIntegerMathAbs(LUnaryMathOperation* instr) {
2928 Register input = ToRegister(instr->InputAt(0)); 2802 Register input = ToRegister(instr->InputAt(0));
2803 Register result = ToRegister(instr->result());
2929 __ cmp(input, Operand(0)); 2804 __ cmp(input, Operand(0));
2805 __ Move(result, input, pl);
2930 // We can make rsb conditional because the previous cmp instruction 2806 // We can make rsb conditional because the previous cmp instruction
2931 // will clear the V (overflow) flag and rsb won't set this flag 2807 // will clear the V (overflow) flag and rsb won't set this flag
2932 // if input is positive. 2808 // if input is positive.
2933 __ rsb(input, input, Operand(0), SetCC, mi); 2809 __ rsb(result, input, Operand(0), SetCC, mi);
2934 // Deoptimize on overflow. 2810 // Deoptimize on overflow.
2935 DeoptimizeIf(vs, instr->environment()); 2811 DeoptimizeIf(vs, instr->environment());
2936 } 2812 }
2937 2813
2938 2814
2939 void LCodeGen::DoMathAbs(LUnaryMathOperation* instr) { 2815 void LCodeGen::DoMathAbs(LUnaryMathOperation* instr) {
2940 // Class for deferred case. 2816 // Class for deferred case.
2941 class DeferredMathAbsTaggedHeapNumber: public LDeferredCode { 2817 class DeferredMathAbsTaggedHeapNumber: public LDeferredCode {
2942 public: 2818 public:
2943 DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen, 2819 DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen,
2944 LUnaryMathOperation* instr) 2820 LUnaryMathOperation* instr)
2945 : LDeferredCode(codegen), instr_(instr) { } 2821 : LDeferredCode(codegen), instr_(instr) { }
2946 virtual void Generate() { 2822 virtual void Generate() {
2947 codegen()->DoDeferredMathAbsTaggedHeapNumber(instr_); 2823 codegen()->DoDeferredMathAbsTaggedHeapNumber(instr_);
2948 } 2824 }
2949 private: 2825 private:
2950 LUnaryMathOperation* instr_; 2826 LUnaryMathOperation* instr_;
2951 }; 2827 };
2952 2828
2953 ASSERT(instr->InputAt(0)->Equals(instr->result()));
2954 Representation r = instr->hydrogen()->value()->representation(); 2829 Representation r = instr->hydrogen()->value()->representation();
2955 if (r.IsDouble()) { 2830 if (r.IsDouble()) {
2956 DwVfpRegister input = ToDoubleRegister(instr->InputAt(0)); 2831 DwVfpRegister input = ToDoubleRegister(instr->InputAt(0));
2957 __ vabs(input, input); 2832 DwVfpRegister result = ToDoubleRegister(instr->result());
2833 __ vabs(result, input);
2958 } else if (r.IsInteger32()) { 2834 } else if (r.IsInteger32()) {
2959 EmitIntegerMathAbs(instr); 2835 EmitIntegerMathAbs(instr);
2960 } else { 2836 } else {
2961 // Representation is tagged. 2837 // Representation is tagged.
2962 DeferredMathAbsTaggedHeapNumber* deferred = 2838 DeferredMathAbsTaggedHeapNumber* deferred =
2963 new DeferredMathAbsTaggedHeapNumber(this, instr); 2839 new DeferredMathAbsTaggedHeapNumber(this, instr);
2964 Register input = ToRegister(instr->InputAt(0)); 2840 Register input = ToRegister(instr->InputAt(0));
2965 // Smi check. 2841 // Smi check.
2966 __ JumpIfNotSmi(input, deferred->entry()); 2842 __ JumpIfNotSmi(input, deferred->entry());
2967 // If smi, handle it directly. 2843 // If smi, handle it directly.
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
3025 } 2901 }
3026 2902
3027 // The following conversion will not work with numbers 2903 // The following conversion will not work with numbers
3028 // outside of ]-2^32, 2^32[. 2904 // outside of ]-2^32, 2^32[.
3029 __ cmp(scratch2, Operand(HeapNumber::kExponentBias + 32)); 2905 __ cmp(scratch2, Operand(HeapNumber::kExponentBias + 32));
3030 DeoptimizeIf(ge, instr->environment()); 2906 DeoptimizeIf(ge, instr->environment());
3031 2907
3032 // Save the original sign for later comparison. 2908 // Save the original sign for later comparison.
3033 __ and_(scratch2, scratch1, Operand(HeapNumber::kSignMask)); 2909 __ and_(scratch2, scratch1, Operand(HeapNumber::kSignMask));
3034 2910
3035 __ vmov(double_scratch0(), 0.5); 2911 __ Vmov(double_scratch0(), 0.5);
3036 __ vadd(input, input, double_scratch0()); 2912 __ vadd(input, input, double_scratch0());
3037 2913
3038 // Check sign of the result: if the sign changed, the input 2914 // Check sign of the result: if the sign changed, the input
3039 // value was in ]0.5, 0[ and the result should be -0. 2915 // value was in ]0.5, 0[ and the result should be -0.
3040 __ vmov(scratch1, input.high()); 2916 __ vmov(scratch1, input.high());
3041 __ eor(scratch1, scratch1, Operand(scratch2), SetCC); 2917 __ eor(scratch1, scratch1, Operand(scratch2), SetCC);
3042 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 2918 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
3043 DeoptimizeIf(mi, instr->environment()); 2919 DeoptimizeIf(mi, instr->environment());
3044 } else { 2920 } else {
3045 __ mov(result, Operand(0), LeaveCC, mi); 2921 __ mov(result, Operand(0), LeaveCC, mi);
(...skipping 16 matching lines...) Expand all
3062 __ vmov(scratch1, input.high()); 2938 __ vmov(scratch1, input.high());
3063 __ tst(scratch1, Operand(HeapNumber::kSignMask)); 2939 __ tst(scratch1, Operand(HeapNumber::kSignMask));
3064 DeoptimizeIf(ne, instr->environment()); 2940 DeoptimizeIf(ne, instr->environment());
3065 } 2941 }
3066 __ bind(&done); 2942 __ bind(&done);
3067 } 2943 }
3068 2944
3069 2945
3070 void LCodeGen::DoMathSqrt(LUnaryMathOperation* instr) { 2946 void LCodeGen::DoMathSqrt(LUnaryMathOperation* instr) {
3071 DoubleRegister input = ToDoubleRegister(instr->InputAt(0)); 2947 DoubleRegister input = ToDoubleRegister(instr->InputAt(0));
3072 ASSERT(ToDoubleRegister(instr->result()).is(input)); 2948 DoubleRegister result = ToDoubleRegister(instr->result());
3073 __ vsqrt(input, input); 2949 __ vsqrt(result, input);
3074 } 2950 }
3075 2951
3076 2952
3077 void LCodeGen::DoMathPowHalf(LUnaryMathOperation* instr) { 2953 void LCodeGen::DoMathPowHalf(LUnaryMathOperation* instr) {
3078 DoubleRegister input = ToDoubleRegister(instr->InputAt(0)); 2954 DoubleRegister input = ToDoubleRegister(instr->InputAt(0));
3079 Register scratch = scratch0(); 2955 DoubleRegister result = ToDoubleRegister(instr->result());
3080 SwVfpRegister single_scratch = double_scratch0().low();
3081 DoubleRegister double_scratch = double_scratch0();
3082 ASSERT(ToDoubleRegister(instr->result()).is(input));
3083
3084 // Add +0 to convert -0 to +0. 2956 // Add +0 to convert -0 to +0.
3085 __ mov(scratch, Operand(0)); 2957 __ vadd(result, input, kDoubleRegZero);
3086 __ vmov(single_scratch, scratch); 2958 __ vsqrt(result, result);
3087 __ vcvt_f64_s32(double_scratch, single_scratch);
3088 __ vadd(input, input, double_scratch);
3089 __ vsqrt(input, input);
3090 } 2959 }
3091 2960
3092 2961
3093 void LCodeGen::DoPower(LPower* instr) { 2962 void LCodeGen::DoPower(LPower* instr) {
3094 LOperand* left = instr->InputAt(0); 2963 LOperand* left = instr->InputAt(0);
3095 LOperand* right = instr->InputAt(1); 2964 LOperand* right = instr->InputAt(1);
3096 Register scratch = scratch0(); 2965 Register scratch = scratch0();
3097 DoubleRegister result_reg = ToDoubleRegister(instr->result()); 2966 DoubleRegister result_reg = ToDoubleRegister(instr->result());
3098 Representation exponent_type = instr->hydrogen()->right()->representation(); 2967 Representation exponent_type = instr->hydrogen()->right()->representation();
3099 if (exponent_type.IsDouble()) { 2968 if (exponent_type.IsDouble()) {
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
3209 void LCodeGen::DoInvokeFunction(LInvokeFunction* instr) { 3078 void LCodeGen::DoInvokeFunction(LInvokeFunction* instr) {
3210 ASSERT(ToRegister(instr->function()).is(r1)); 3079 ASSERT(ToRegister(instr->function()).is(r1));
3211 ASSERT(instr->HasPointerMap()); 3080 ASSERT(instr->HasPointerMap());
3212 ASSERT(instr->HasDeoptimizationEnvironment()); 3081 ASSERT(instr->HasDeoptimizationEnvironment());
3213 LPointerMap* pointers = instr->pointer_map(); 3082 LPointerMap* pointers = instr->pointer_map();
3214 LEnvironment* env = instr->deoptimization_environment(); 3083 LEnvironment* env = instr->deoptimization_environment();
3215 RecordPosition(pointers->position()); 3084 RecordPosition(pointers->position());
3216 RegisterEnvironmentForDeoptimization(env); 3085 RegisterEnvironmentForDeoptimization(env);
3217 SafepointGenerator generator(this, pointers, env->deoptimization_index()); 3086 SafepointGenerator generator(this, pointers, env->deoptimization_index());
3218 ParameterCount count(instr->arity()); 3087 ParameterCount count(instr->arity());
3219 __ InvokeFunction(r1, count, CALL_FUNCTION, generator); 3088 __ InvokeFunction(r1, count, CALL_FUNCTION, generator, CALL_AS_METHOD);
3220 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 3089 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
3221 } 3090 }
3222 3091
3223 3092
3224 void LCodeGen::DoCallKeyed(LCallKeyed* instr) { 3093 void LCodeGen::DoCallKeyed(LCallKeyed* instr) {
3225 ASSERT(ToRegister(instr->result()).is(r0)); 3094 ASSERT(ToRegister(instr->result()).is(r0));
3226 3095
3227 int arity = instr->arity(); 3096 int arity = instr->arity();
3228 Handle<Code> ic = 3097 Handle<Code> ic =
3229 isolate()->stub_cache()->ComputeKeyedCallInitialize(arity, NOT_IN_LOOP); 3098 isolate()->stub_cache()->ComputeKeyedCallInitialize(arity, NOT_IN_LOOP);
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after
3369 __ RecordWrite(elements, key, value, kLRHasBeenSaved, kSaveFPRegs); 3238 __ RecordWrite(elements, key, value, kLRHasBeenSaved, kSaveFPRegs);
3370 } 3239 }
3371 } 3240 }
3372 3241
3373 3242
3374 void LCodeGen::DoStoreKeyedSpecializedArrayElement( 3243 void LCodeGen::DoStoreKeyedSpecializedArrayElement(
3375 LStoreKeyedSpecializedArrayElement* instr) { 3244 LStoreKeyedSpecializedArrayElement* instr) {
3376 3245
3377 Register external_pointer = ToRegister(instr->external_pointer()); 3246 Register external_pointer = ToRegister(instr->external_pointer());
3378 Register key = no_reg; 3247 Register key = no_reg;
3379 ExternalArrayType array_type = instr->array_type(); 3248 JSObject::ElementsKind elements_kind = instr->elements_kind();
3380 bool key_is_constant = instr->key()->IsConstantOperand(); 3249 bool key_is_constant = instr->key()->IsConstantOperand();
3381 int constant_key = 0; 3250 int constant_key = 0;
3382 if (key_is_constant) { 3251 if (key_is_constant) {
3383 constant_key = ToInteger32(LConstantOperand::cast(instr->key())); 3252 constant_key = ToInteger32(LConstantOperand::cast(instr->key()));
3384 if (constant_key & 0xF0000000) { 3253 if (constant_key & 0xF0000000) {
3385 Abort("array index constant value too big."); 3254 Abort("array index constant value too big.");
3386 } 3255 }
3387 } else { 3256 } else {
3388 key = ToRegister(instr->key()); 3257 key = ToRegister(instr->key());
3389 } 3258 }
3390 int shift_size = ExternalArrayTypeToShiftSize(array_type); 3259 int shift_size = ElementsKindToShiftSize(elements_kind);
3391 3260
3392 if (array_type == kExternalFloatArray || array_type == kExternalDoubleArray) { 3261 if (elements_kind == JSObject::EXTERNAL_FLOAT_ELEMENTS ||
3262 elements_kind == JSObject::EXTERNAL_DOUBLE_ELEMENTS) {
3393 CpuFeatures::Scope scope(VFP3); 3263 CpuFeatures::Scope scope(VFP3);
3394 DwVfpRegister value(ToDoubleRegister(instr->value())); 3264 DwVfpRegister value(ToDoubleRegister(instr->value()));
3395 Operand operand(key_is_constant ? Operand(constant_key * (1 << shift_size)) 3265 Operand operand(key_is_constant ? Operand(constant_key * (1 << shift_size))
3396 : Operand(key, LSL, shift_size)); 3266 : Operand(key, LSL, shift_size));
3397 __ add(scratch0(), external_pointer, operand); 3267 __ add(scratch0(), external_pointer, operand);
3398 if (array_type == kExternalFloatArray) { 3268 if (elements_kind == JSObject::EXTERNAL_FLOAT_ELEMENTS) {
3399 __ vcvt_f32_f64(double_scratch0().low(), value); 3269 __ vcvt_f32_f64(double_scratch0().low(), value);
3400 __ vstr(double_scratch0().low(), scratch0(), 0); 3270 __ vstr(double_scratch0().low(), scratch0(), 0);
3401 } else { // i.e. array_type == kExternalDoubleArray 3271 } else { // i.e. elements_kind == JSObject::EXTERNAL_DOUBLE_ELEMENTS
3402 __ vstr(value, scratch0(), 0); 3272 __ vstr(value, scratch0(), 0);
3403 } 3273 }
3404 } else { 3274 } else {
3405 Register value(ToRegister(instr->value())); 3275 Register value(ToRegister(instr->value()));
3406 MemOperand mem_operand(key_is_constant 3276 MemOperand mem_operand(key_is_constant
3407 ? MemOperand(external_pointer, constant_key * (1 << shift_size)) 3277 ? MemOperand(external_pointer, constant_key * (1 << shift_size))
3408 : MemOperand(external_pointer, key, LSL, shift_size)); 3278 : MemOperand(external_pointer, key, LSL, shift_size));
3409 switch (array_type) { 3279 switch (elements_kind) {
3410 case kExternalPixelArray: 3280 case JSObject::EXTERNAL_PIXEL_ELEMENTS:
3411 case kExternalByteArray: 3281 case JSObject::EXTERNAL_BYTE_ELEMENTS:
3412 case kExternalUnsignedByteArray: 3282 case JSObject::EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
3413 __ strb(value, mem_operand); 3283 __ strb(value, mem_operand);
3414 break; 3284 break;
3415 case kExternalShortArray: 3285 case JSObject::EXTERNAL_SHORT_ELEMENTS:
3416 case kExternalUnsignedShortArray: 3286 case JSObject::EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
3417 __ strh(value, mem_operand); 3287 __ strh(value, mem_operand);
3418 break; 3288 break;
3419 case kExternalIntArray: 3289 case JSObject::EXTERNAL_INT_ELEMENTS:
3420 case kExternalUnsignedIntArray: 3290 case JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS:
3421 __ str(value, mem_operand); 3291 __ str(value, mem_operand);
3422 break; 3292 break;
3423 case kExternalFloatArray: 3293 case JSObject::EXTERNAL_FLOAT_ELEMENTS:
3424 case kExternalDoubleArray: 3294 case JSObject::EXTERNAL_DOUBLE_ELEMENTS:
3295 case JSObject::FAST_DOUBLE_ELEMENTS:
3296 case JSObject::FAST_ELEMENTS:
3297 case JSObject::DICTIONARY_ELEMENTS:
3298 case JSObject::NON_STRICT_ARGUMENTS_ELEMENTS:
3425 UNREACHABLE(); 3299 UNREACHABLE();
3426 break; 3300 break;
3427 } 3301 }
3428 } 3302 }
3429 } 3303 }
3430 3304
3431 3305
3432 void LCodeGen::DoStoreKeyedGeneric(LStoreKeyedGeneric* instr) { 3306 void LCodeGen::DoStoreKeyedGeneric(LStoreKeyedGeneric* instr) {
3433 ASSERT(ToRegister(instr->object()).is(r2)); 3307 ASSERT(ToRegister(instr->object()).is(r2));
3434 ASSERT(ToRegister(instr->key()).is(r1)); 3308 ASSERT(ToRegister(instr->key()).is(r1));
(...skipping 240 matching lines...) Expand 10 before | Expand all | Expand 10 after
3675 DeferredNumberTagI* deferred = new DeferredNumberTagI(this, instr); 3549 DeferredNumberTagI* deferred = new DeferredNumberTagI(this, instr);
3676 __ SmiTag(reg, SetCC); 3550 __ SmiTag(reg, SetCC);
3677 __ b(vs, deferred->entry()); 3551 __ b(vs, deferred->entry());
3678 __ bind(deferred->exit()); 3552 __ bind(deferred->exit());
3679 } 3553 }
3680 3554
3681 3555
3682 void LCodeGen::DoDeferredNumberTagI(LNumberTagI* instr) { 3556 void LCodeGen::DoDeferredNumberTagI(LNumberTagI* instr) {
3683 Label slow; 3557 Label slow;
3684 Register reg = ToRegister(instr->InputAt(0)); 3558 Register reg = ToRegister(instr->InputAt(0));
3685 DoubleRegister dbl_scratch = d0; 3559 DoubleRegister dbl_scratch = double_scratch0();
3686 SwVfpRegister flt_scratch = s0; 3560 SwVfpRegister flt_scratch = dbl_scratch.low();
3687 3561
3688 // Preserve the value of all registers. 3562 // Preserve the value of all registers.
3689 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); 3563 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters);
3690 3564
3691 // There was overflow, so bits 30 and 31 of the original integer 3565 // There was overflow, so bits 30 and 31 of the original integer
3692 // disagree. Try to allocate a heap number in new space and store 3566 // disagree. Try to allocate a heap number in new space and store
3693 // the value in there. If that fails, call the runtime system. 3567 // the value in there. If that fails, call the runtime system.
3694 Label done; 3568 Label done;
3695 __ SmiUntag(reg); 3569 __ SmiUntag(reg);
3696 __ eor(reg, reg, Operand(0x80000000)); 3570 __ eor(reg, reg, Operand(0x80000000));
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
3782 __ SmiUntag(ToRegister(input), SetCC); 3656 __ SmiUntag(ToRegister(input), SetCC);
3783 DeoptimizeIf(cs, instr->environment()); 3657 DeoptimizeIf(cs, instr->environment());
3784 } else { 3658 } else {
3785 __ SmiUntag(ToRegister(input)); 3659 __ SmiUntag(ToRegister(input));
3786 } 3660 }
3787 } 3661 }
3788 3662
3789 3663
3790 void LCodeGen::EmitNumberUntagD(Register input_reg, 3664 void LCodeGen::EmitNumberUntagD(Register input_reg,
3791 DoubleRegister result_reg, 3665 DoubleRegister result_reg,
3666 bool deoptimize_on_undefined,
3792 LEnvironment* env) { 3667 LEnvironment* env) {
3793 Register scratch = scratch0(); 3668 Register scratch = scratch0();
3794 SwVfpRegister flt_scratch = s0; 3669 SwVfpRegister flt_scratch = double_scratch0().low();
3795 ASSERT(!result_reg.is(d0)); 3670 ASSERT(!result_reg.is(double_scratch0()));
3796 3671
3797 Label load_smi, heap_number, done; 3672 Label load_smi, heap_number, done;
3798 3673
3799 // Smi check. 3674 // Smi check.
3800 __ tst(input_reg, Operand(kSmiTagMask)); 3675 __ JumpIfSmi(input_reg, &load_smi);
3801 __ b(eq, &load_smi);
3802 3676
3803 // Heap number map check. 3677 // Heap number map check.
3804 __ ldr(scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset)); 3678 __ ldr(scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset));
3805 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex); 3679 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex);
3806 __ cmp(scratch, Operand(ip)); 3680 __ cmp(scratch, Operand(ip));
3807 __ b(eq, &heap_number); 3681 if (deoptimize_on_undefined) {
3682 DeoptimizeIf(ne, env);
3683 } else {
3684 Label heap_number;
3685 __ b(eq, &heap_number);
3808 3686
3809 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); 3687 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
3810 __ cmp(input_reg, Operand(ip)); 3688 __ cmp(input_reg, Operand(ip));
3811 DeoptimizeIf(ne, env); 3689 DeoptimizeIf(ne, env);
3812 3690
3813 // Convert undefined to NaN. 3691 // Convert undefined to NaN.
3814 __ LoadRoot(ip, Heap::kNanValueRootIndex); 3692 __ LoadRoot(ip, Heap::kNanValueRootIndex);
3815 __ sub(ip, ip, Operand(kHeapObjectTag)); 3693 __ sub(ip, ip, Operand(kHeapObjectTag));
3816 __ vldr(result_reg, ip, HeapNumber::kValueOffset); 3694 __ vldr(result_reg, ip, HeapNumber::kValueOffset);
3817 __ jmp(&done); 3695 __ jmp(&done);
3818 3696
3697 __ bind(&heap_number);
3698 }
3819 // Heap number to double register conversion. 3699 // Heap number to double register conversion.
3820 __ bind(&heap_number);
3821 __ sub(ip, input_reg, Operand(kHeapObjectTag)); 3700 __ sub(ip, input_reg, Operand(kHeapObjectTag));
3822 __ vldr(result_reg, ip, HeapNumber::kValueOffset); 3701 __ vldr(result_reg, ip, HeapNumber::kValueOffset);
3823 __ jmp(&done); 3702 __ jmp(&done);
3824 3703
3825 // Smi to double register conversion 3704 // Smi to double register conversion
3826 __ bind(&load_smi); 3705 __ bind(&load_smi);
3827 __ SmiUntag(input_reg); // Untag smi before converting to float. 3706 __ SmiUntag(input_reg); // Untag smi before converting to float.
3828 __ vmov(flt_scratch, input_reg); 3707 __ vmov(flt_scratch, input_reg);
3829 __ vcvt_f64_s32(result_reg, flt_scratch); 3708 __ vcvt_f64_s32(result_reg, flt_scratch);
3830 __ SmiTag(input_reg); // Retag smi. 3709 __ SmiTag(input_reg); // Retag smi.
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
3944 3823
3945 void LCodeGen::DoNumberUntagD(LNumberUntagD* instr) { 3824 void LCodeGen::DoNumberUntagD(LNumberUntagD* instr) {
3946 LOperand* input = instr->InputAt(0); 3825 LOperand* input = instr->InputAt(0);
3947 ASSERT(input->IsRegister()); 3826 ASSERT(input->IsRegister());
3948 LOperand* result = instr->result(); 3827 LOperand* result = instr->result();
3949 ASSERT(result->IsDoubleRegister()); 3828 ASSERT(result->IsDoubleRegister());
3950 3829
3951 Register input_reg = ToRegister(input); 3830 Register input_reg = ToRegister(input);
3952 DoubleRegister result_reg = ToDoubleRegister(result); 3831 DoubleRegister result_reg = ToDoubleRegister(result);
3953 3832
3954 EmitNumberUntagD(input_reg, result_reg, instr->environment()); 3833 EmitNumberUntagD(input_reg, result_reg,
3834 instr->hydrogen()->deoptimize_on_undefined(),
3835 instr->environment());
3955 } 3836 }
3956 3837
3957 3838
3958 void LCodeGen::DoDoubleToI(LDoubleToI* instr) { 3839 void LCodeGen::DoDoubleToI(LDoubleToI* instr) {
3959 Register result_reg = ToRegister(instr->result()); 3840 Register result_reg = ToRegister(instr->result());
3960 Register scratch1 = scratch0(); 3841 Register scratch1 = scratch0();
3961 Register scratch2 = ToRegister(instr->TempAt(0)); 3842 Register scratch2 = ToRegister(instr->TempAt(0));
3962 DwVfpRegister double_input = ToDoubleRegister(instr->InputAt(0)); 3843 DwVfpRegister double_input = ToDoubleRegister(instr->InputAt(0));
3963 DwVfpRegister double_scratch = double_scratch0(); 3844 DwVfpRegister double_scratch = double_scratch0();
3964 SwVfpRegister single_scratch = double_scratch0().low(); 3845 SwVfpRegister single_scratch = double_scratch0().low();
(...skipping 325 matching lines...) Expand 10 before | Expand all | Expand 10 after
4290 } 4171 }
4291 4172
4292 4173
4293 void LCodeGen::DoTypeof(LTypeof* instr) { 4174 void LCodeGen::DoTypeof(LTypeof* instr) {
4294 Register input = ToRegister(instr->InputAt(0)); 4175 Register input = ToRegister(instr->InputAt(0));
4295 __ push(input); 4176 __ push(input);
4296 CallRuntime(Runtime::kTypeof, 1, instr); 4177 CallRuntime(Runtime::kTypeof, 1, instr);
4297 } 4178 }
4298 4179
4299 4180
4300 void LCodeGen::DoTypeofIs(LTypeofIs* instr) {
4301 Register input = ToRegister(instr->InputAt(0));
4302 Register result = ToRegister(instr->result());
4303 Label true_label;
4304 Label false_label;
4305 Label done;
4306
4307 Condition final_branch_condition = EmitTypeofIs(&true_label,
4308 &false_label,
4309 input,
4310 instr->type_literal());
4311 __ b(final_branch_condition, &true_label);
4312 __ bind(&false_label);
4313 __ LoadRoot(result, Heap::kFalseValueRootIndex);
4314 __ b(&done);
4315
4316 __ bind(&true_label);
4317 __ LoadRoot(result, Heap::kTrueValueRootIndex);
4318
4319 __ bind(&done);
4320 }
4321
4322
4323 void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) { 4181 void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) {
4324 Register input = ToRegister(instr->InputAt(0)); 4182 Register input = ToRegister(instr->InputAt(0));
4325 int true_block = chunk_->LookupDestination(instr->true_block_id()); 4183 int true_block = chunk_->LookupDestination(instr->true_block_id());
4326 int false_block = chunk_->LookupDestination(instr->false_block_id()); 4184 int false_block = chunk_->LookupDestination(instr->false_block_id());
4327 Label* true_label = chunk_->GetAssemblyLabel(true_block); 4185 Label* true_label = chunk_->GetAssemblyLabel(true_block);
4328 Label* false_label = chunk_->GetAssemblyLabel(false_block); 4186 Label* false_label = chunk_->GetAssemblyLabel(false_block);
4329 4187
4330 Condition final_branch_condition = EmitTypeofIs(true_label, 4188 Condition final_branch_condition = EmitTypeofIs(true_label,
4331 false_label, 4189 false_label,
4332 input, 4190 input,
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
4368 __ b(eq, true_label); 4226 __ b(eq, true_label);
4369 __ JumpIfSmi(input, false_label); 4227 __ JumpIfSmi(input, false_label);
4370 // Check for undetectable objects => true. 4228 // Check for undetectable objects => true.
4371 __ ldr(input, FieldMemOperand(input, HeapObject::kMapOffset)); 4229 __ ldr(input, FieldMemOperand(input, HeapObject::kMapOffset));
4372 __ ldrb(ip, FieldMemOperand(input, Map::kBitFieldOffset)); 4230 __ ldrb(ip, FieldMemOperand(input, Map::kBitFieldOffset));
4373 __ tst(ip, Operand(1 << Map::kIsUndetectable)); 4231 __ tst(ip, Operand(1 << Map::kIsUndetectable));
4374 final_branch_condition = ne; 4232 final_branch_condition = ne;
4375 4233
4376 } else if (type_name->Equals(heap()->function_symbol())) { 4234 } else if (type_name->Equals(heap()->function_symbol())) {
4377 __ JumpIfSmi(input, false_label); 4235 __ JumpIfSmi(input, false_label);
4378 __ CompareObjectType(input, input, scratch, FIRST_FUNCTION_CLASS_TYPE); 4236 __ CompareObjectType(input, input, scratch,
4237 FIRST_CALLABLE_SPEC_OBJECT_TYPE);
4379 final_branch_condition = ge; 4238 final_branch_condition = ge;
4380 4239
4381 } else if (type_name->Equals(heap()->object_symbol())) { 4240 } else if (type_name->Equals(heap()->object_symbol())) {
4382 __ JumpIfSmi(input, false_label); 4241 __ JumpIfSmi(input, false_label);
4383 __ CompareRoot(input, Heap::kNullValueRootIndex); 4242 __ CompareRoot(input, Heap::kNullValueRootIndex);
4384 __ b(eq, true_label); 4243 __ b(eq, true_label);
4385 __ CompareObjectType(input, input, scratch, FIRST_JS_OBJECT_TYPE); 4244 __ CompareObjectType(input, input, scratch,
4386 __ b(lo, false_label); 4245 FIRST_NONCALLABLE_SPEC_OBJECT_TYPE);
4387 __ CompareInstanceType(input, scratch, FIRST_FUNCTION_CLASS_TYPE); 4246 __ b(lt, false_label);
4388 __ b(hs, false_label); 4247 __ CompareInstanceType(input, scratch, LAST_NONCALLABLE_SPEC_OBJECT_TYPE);
4248 __ b(gt, false_label);
4389 // Check for undetectable objects => false. 4249 // Check for undetectable objects => false.
4390 __ ldrb(ip, FieldMemOperand(input, Map::kBitFieldOffset)); 4250 __ ldrb(ip, FieldMemOperand(input, Map::kBitFieldOffset));
4391 __ tst(ip, Operand(1 << Map::kIsUndetectable)); 4251 __ tst(ip, Operand(1 << Map::kIsUndetectable));
4392 final_branch_condition = eq; 4252 final_branch_condition = eq;
4393 4253
4394 } else { 4254 } else {
4395 final_branch_condition = ne; 4255 final_branch_condition = ne;
4396 __ b(false_label); 4256 __ b(false_label);
4397 // A dead branch instruction will be generated after this point. 4257 // A dead branch instruction will be generated after this point.
4398 } 4258 }
4399 4259
4400 return final_branch_condition; 4260 return final_branch_condition;
4401 } 4261 }
4402 4262
4403 4263
4404 void LCodeGen::DoIsConstructCall(LIsConstructCall* instr) {
4405 Register result = ToRegister(instr->result());
4406 Label true_label;
4407 Label false_label;
4408 Label done;
4409
4410 EmitIsConstructCall(result, scratch0());
4411 __ b(eq, &true_label);
4412
4413 __ LoadRoot(result, Heap::kFalseValueRootIndex);
4414 __ b(&done);
4415
4416
4417 __ bind(&true_label);
4418 __ LoadRoot(result, Heap::kTrueValueRootIndex);
4419
4420 __ bind(&done);
4421 }
4422
4423
4424 void LCodeGen::DoIsConstructCallAndBranch(LIsConstructCallAndBranch* instr) { 4264 void LCodeGen::DoIsConstructCallAndBranch(LIsConstructCallAndBranch* instr) {
4425 Register temp1 = ToRegister(instr->TempAt(0)); 4265 Register temp1 = ToRegister(instr->TempAt(0));
4426 int true_block = chunk_->LookupDestination(instr->true_block_id()); 4266 int true_block = chunk_->LookupDestination(instr->true_block_id());
4427 int false_block = chunk_->LookupDestination(instr->false_block_id()); 4267 int false_block = chunk_->LookupDestination(instr->false_block_id());
4428 4268
4429 EmitIsConstructCall(temp1, scratch0()); 4269 EmitIsConstructCall(temp1, scratch0());
4430 EmitBranch(true_block, false_block, eq); 4270 EmitBranch(true_block, false_block, eq);
4431 } 4271 }
4432 4272
4433 4273
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
4488 LEnvironment* env = instr->deoptimization_environment(); 4328 LEnvironment* env = instr->deoptimization_environment();
4489 RecordPosition(pointers->position()); 4329 RecordPosition(pointers->position());
4490 RegisterEnvironmentForDeoptimization(env); 4330 RegisterEnvironmentForDeoptimization(env);
4491 SafepointGenerator safepoint_generator(this, 4331 SafepointGenerator safepoint_generator(this,
4492 pointers, 4332 pointers,
4493 env->deoptimization_index()); 4333 env->deoptimization_index());
4494 __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION, safepoint_generator); 4334 __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION, safepoint_generator);
4495 } 4335 }
4496 4336
4497 4337
4338 void LCodeGen::DoDeferredStackCheck(LStackCheck* instr) {
4339 {
4340 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters);
4341 __ CallRuntimeSaveDoubles(Runtime::kStackGuard);
4342 RegisterLazyDeoptimization(
4343 instr, RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS);
4344 }
4345
4346 // The gap code includes the restoring of the safepoint registers.
4347 int pc = masm()->pc_offset();
4348 safepoints_.SetPcAfterGap(pc);
4349 }
4350
4351
4498 void LCodeGen::DoStackCheck(LStackCheck* instr) { 4352 void LCodeGen::DoStackCheck(LStackCheck* instr) {
4499 // Perform stack overflow check. 4353 class DeferredStackCheck: public LDeferredCode {
4500 Label ok; 4354 public:
4501 __ LoadRoot(ip, Heap::kStackLimitRootIndex); 4355 DeferredStackCheck(LCodeGen* codegen, LStackCheck* instr)
4502 __ cmp(sp, Operand(ip)); 4356 : LDeferredCode(codegen), instr_(instr) { }
4503 __ b(hs, &ok); 4357 virtual void Generate() { codegen()->DoDeferredStackCheck(instr_); }
4504 StackCheckStub stub; 4358 private:
4505 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); 4359 LStackCheck* instr_;
4506 __ bind(&ok); 4360 };
4361
4362 if (instr->hydrogen()->is_function_entry()) {
4363 // Perform stack overflow check.
4364 Label done;
4365 __ LoadRoot(ip, Heap::kStackLimitRootIndex);
4366 __ cmp(sp, Operand(ip));
4367 __ b(hs, &done);
4368 StackCheckStub stub;
4369 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
4370 __ bind(&done);
4371 } else {
4372 ASSERT(instr->hydrogen()->is_backwards_branch());
4373 // Perform stack overflow check if this goto needs it before jumping.
4374 DeferredStackCheck* deferred_stack_check =
4375 new DeferredStackCheck(this, instr);
4376 __ LoadRoot(ip, Heap::kStackLimitRootIndex);
4377 __ cmp(sp, Operand(ip));
4378 __ b(lo, deferred_stack_check->entry());
4379 __ bind(instr->done_label());
4380 deferred_stack_check->SetExit(instr->done_label());
4381 }
4507 } 4382 }
4508 4383
4509 4384
4510 void LCodeGen::DoOsrEntry(LOsrEntry* instr) { 4385 void LCodeGen::DoOsrEntry(LOsrEntry* instr) {
4511 // This is a pseudo-instruction that ensures that the environment here is 4386 // This is a pseudo-instruction that ensures that the environment here is
4512 // properly registered for deoptimization and records the assembler's PC 4387 // properly registered for deoptimization and records the assembler's PC
4513 // offset. 4388 // offset.
4514 LEnvironment* environment = instr->environment(); 4389 LEnvironment* environment = instr->environment();
4515 environment->SetSpilledRegisters(instr->SpilledRegisterArray(), 4390 environment->SetSpilledRegisters(instr->SpilledRegisterArray(),
4516 instr->SpilledDoubleRegisterArray()); 4391 instr->SpilledDoubleRegisterArray());
4517 4392
4518 // If the environment were already registered, we would have no way of 4393 // If the environment were already registered, we would have no way of
4519 // backpatching it with the spill slot operands. 4394 // backpatching it with the spill slot operands.
4520 ASSERT(!environment->HasBeenRegistered()); 4395 ASSERT(!environment->HasBeenRegistered());
4521 RegisterEnvironmentForDeoptimization(environment); 4396 RegisterEnvironmentForDeoptimization(environment);
4522 ASSERT(osr_pc_offset_ == -1); 4397 ASSERT(osr_pc_offset_ == -1);
4523 osr_pc_offset_ = masm()->pc_offset(); 4398 osr_pc_offset_ = masm()->pc_offset();
4524 } 4399 }
4525 4400
4526 4401
4527 4402
4528 4403
4529 #undef __ 4404 #undef __
4530 4405
4531 } } // namespace v8::internal 4406 } } // 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