| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_MIPS. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_MIPS. |
| 6 #if defined(TARGET_ARCH_MIPS) | 6 #if defined(TARGET_ARCH_MIPS) |
| 7 | 7 |
| 8 #include "vm/intermediate_language.h" | 8 #include "vm/intermediate_language.h" |
| 9 | 9 |
| 10 #include "vm/compiler.h" | 10 #include "vm/compiler.h" |
| (...skipping 11 matching lines...) Expand all Loading... |
| 22 #include "vm/symbols.h" | 22 #include "vm/symbols.h" |
| 23 | 23 |
| 24 #define __ compiler->assembler()-> | 24 #define __ compiler->assembler()-> |
| 25 #define Z (compiler->zone()) | 25 #define Z (compiler->zone()) |
| 26 | 26 |
| 27 namespace dart { | 27 namespace dart { |
| 28 | 28 |
| 29 // Generic summary for call instructions that have all arguments pushed | 29 // Generic summary for call instructions that have all arguments pushed |
| 30 // on the stack and return the result in a fixed register V0. | 30 // on the stack and return the result in a fixed register V0. |
| 31 LocationSummary* Instruction::MakeCallSummary(Zone* zone) { | 31 LocationSummary* Instruction::MakeCallSummary(Zone* zone) { |
| 32 LocationSummary* result = new(zone) LocationSummary( | 32 LocationSummary* result = |
| 33 zone, 0, 0, LocationSummary::kCall); | 33 new (zone) LocationSummary(zone, 0, 0, LocationSummary::kCall); |
| 34 result->set_out(0, Location::RegisterLocation(V0)); | 34 result->set_out(0, Location::RegisterLocation(V0)); |
| 35 return result; | 35 return result; |
| 36 } | 36 } |
| 37 | 37 |
| 38 | 38 |
| 39 LocationSummary* PushArgumentInstr::MakeLocationSummary(Zone* zone, | 39 LocationSummary* PushArgumentInstr::MakeLocationSummary(Zone* zone, |
| 40 bool opt) const { | 40 bool opt) const { |
| 41 const intptr_t kNumInputs = 1; | 41 const intptr_t kNumInputs = 1; |
| 42 const intptr_t kNumTemps = 0; | 42 const intptr_t kNumTemps = 0; |
| 43 LocationSummary* locs = new(zone) LocationSummary( | 43 LocationSummary* locs = new (zone) |
| 44 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 44 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 45 locs->set_in(0, Location::AnyOrConstant(value())); | 45 locs->set_in(0, Location::AnyOrConstant(value())); |
| 46 return locs; | 46 return locs; |
| 47 } | 47 } |
| 48 | 48 |
| 49 | 49 |
| 50 void PushArgumentInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 50 void PushArgumentInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 51 // In SSA mode, we need an explicit push. Nothing to do in non-SSA mode | 51 // In SSA mode, we need an explicit push. Nothing to do in non-SSA mode |
| 52 // where PushArgument is handled by BindInstr::EmitNativeCode. | 52 // where PushArgument is handled by BindInstr::EmitNativeCode. |
| 53 __ Comment("PushArgumentInstr"); | 53 __ Comment("PushArgumentInstr"); |
| 54 if (compiler->is_optimizing()) { | 54 if (compiler->is_optimizing()) { |
| 55 Location value = locs()->in(0); | 55 Location value = locs()->in(0); |
| 56 if (value.IsRegister()) { | 56 if (value.IsRegister()) { |
| 57 __ Push(value.reg()); | 57 __ Push(value.reg()); |
| 58 } else if (value.IsConstant()) { | 58 } else if (value.IsConstant()) { |
| 59 __ PushObject(value.constant()); | 59 __ PushObject(value.constant()); |
| 60 } else { | 60 } else { |
| 61 ASSERT(value.IsStackSlot()); | 61 ASSERT(value.IsStackSlot()); |
| 62 const intptr_t value_offset = value.ToStackSlotOffset(); | 62 const intptr_t value_offset = value.ToStackSlotOffset(); |
| 63 __ LoadFromOffset(TMP, FP, value_offset); | 63 __ LoadFromOffset(TMP, FP, value_offset); |
| 64 __ Push(TMP); | 64 __ Push(TMP); |
| 65 } | 65 } |
| 66 } | 66 } |
| 67 } | 67 } |
| 68 | 68 |
| 69 | 69 |
| 70 LocationSummary* ReturnInstr::MakeLocationSummary(Zone* zone, | 70 LocationSummary* ReturnInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
| 71 bool opt) const { | |
| 72 const intptr_t kNumInputs = 1; | 71 const intptr_t kNumInputs = 1; |
| 73 const intptr_t kNumTemps = 0; | 72 const intptr_t kNumTemps = 0; |
| 74 LocationSummary* locs = new(zone) LocationSummary( | 73 LocationSummary* locs = new (zone) |
| 75 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 74 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 76 locs->set_in(0, Location::RegisterLocation(V0)); | 75 locs->set_in(0, Location::RegisterLocation(V0)); |
| 77 return locs; | 76 return locs; |
| 78 } | 77 } |
| 79 | 78 |
| 80 | 79 |
| 81 // Attempt optimized compilation at return instruction instead of at the entry. | 80 // Attempt optimized compilation at return instruction instead of at the entry. |
| 82 // The entry needs to be patchable, no inlined objects are allowed in the area | 81 // The entry needs to be patchable, no inlined objects are allowed in the area |
| 83 // that will be overwritten by the patch instructions: a branch macro sequence. | 82 // that will be overwritten by the patch instructions: a branch macro sequence. |
| 84 void ReturnInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 83 void ReturnInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 85 __ Comment("ReturnInstr"); | 84 __ Comment("ReturnInstr"); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 104 __ break_(0); | 103 __ break_(0); |
| 105 | 104 |
| 106 __ Bind(&stack_ok); | 105 __ Bind(&stack_ok); |
| 107 #endif | 106 #endif |
| 108 __ LeaveDartFrameAndReturn(); | 107 __ LeaveDartFrameAndReturn(); |
| 109 } | 108 } |
| 110 | 109 |
| 111 | 110 |
| 112 static Condition NegateCondition(Condition condition) { | 111 static Condition NegateCondition(Condition condition) { |
| 113 switch (condition.rel_op()) { | 112 switch (condition.rel_op()) { |
| 114 case AL: condition.set_rel_op(NV); break; | 113 case AL: |
| 115 case NV: condition.set_rel_op(AL); break; | 114 condition.set_rel_op(NV); |
| 116 case EQ: condition.set_rel_op(NE); break; | 115 break; |
| 117 case NE: condition.set_rel_op(EQ); break; | 116 case NV: |
| 118 case LT: condition.set_rel_op(GE); break; | 117 condition.set_rel_op(AL); |
| 119 case LE: condition.set_rel_op(GT); break; | 118 break; |
| 120 case GT: condition.set_rel_op(LE); break; | 119 case EQ: |
| 121 case GE: condition.set_rel_op(LT); break; | 120 condition.set_rel_op(NE); |
| 122 case ULT: condition.set_rel_op(UGE); break; | 121 break; |
| 123 case ULE: condition.set_rel_op(UGT); break; | 122 case NE: |
| 124 case UGT: condition.set_rel_op(ULE); break; | 123 condition.set_rel_op(EQ); |
| 125 case UGE: condition.set_rel_op(ULT); break; | 124 break; |
| 125 case LT: |
| 126 condition.set_rel_op(GE); |
| 127 break; |
| 128 case LE: |
| 129 condition.set_rel_op(GT); |
| 130 break; |
| 131 case GT: |
| 132 condition.set_rel_op(LE); |
| 133 break; |
| 134 case GE: |
| 135 condition.set_rel_op(LT); |
| 136 break; |
| 137 case ULT: |
| 138 condition.set_rel_op(UGE); |
| 139 break; |
| 140 case ULE: |
| 141 condition.set_rel_op(UGT); |
| 142 break; |
| 143 case UGT: |
| 144 condition.set_rel_op(ULE); |
| 145 break; |
| 146 case UGE: |
| 147 condition.set_rel_op(ULT); |
| 148 break; |
| 126 default: | 149 default: |
| 127 UNREACHABLE(); | 150 UNREACHABLE(); |
| 128 } | 151 } |
| 129 return condition; | 152 return condition; |
| 130 } | 153 } |
| 131 | 154 |
| 132 | 155 |
| 133 LocationSummary* IfThenElseInstr::MakeLocationSummary(Zone* zone, | 156 LocationSummary* IfThenElseInstr::MakeLocationSummary(Zone* zone, |
| 134 bool opt) const { | 157 bool opt) const { |
| 135 comparison()->InitializeLocationSummary(zone, opt); | 158 comparison()->InitializeLocationSummary(zone, opt); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 148 intptr_t temp = true_value; | 171 intptr_t temp = true_value; |
| 149 true_value = false_value; | 172 true_value = false_value; |
| 150 false_value = temp; | 173 false_value = temp; |
| 151 swapped = true; | 174 swapped = true; |
| 152 } | 175 } |
| 153 | 176 |
| 154 // Initialize result with the true value. | 177 // Initialize result with the true value. |
| 155 __ LoadImmediate(result, Smi::RawValue(true_value)); | 178 __ LoadImmediate(result, Smi::RawValue(true_value)); |
| 156 | 179 |
| 157 // Emit comparison code. This must not overwrite the result register. | 180 // Emit comparison code. This must not overwrite the result register. |
| 158 BranchLabels labels = { NULL, NULL, NULL }; // Emit branch-free code. | 181 BranchLabels labels = {NULL, NULL, NULL}; // Emit branch-free code. |
| 159 Condition true_condition = comparison()->EmitComparisonCode(compiler, labels); | 182 Condition true_condition = comparison()->EmitComparisonCode(compiler, labels); |
| 160 if (swapped) { | 183 if (swapped) { |
| 161 true_condition = NegateCondition(true_condition); | 184 true_condition = NegateCondition(true_condition); |
| 162 } | 185 } |
| 163 | 186 |
| 164 // Evaluate condition and provide result in CMPRES1. | 187 // Evaluate condition and provide result in CMPRES1. |
| 165 Register left = true_condition.left(); | 188 Register left = true_condition.left(); |
| 166 Register right = true_condition.right(); | 189 Register right = true_condition.right(); |
| 167 bool zero_is_false = true; // Zero in CMPRES1 indicates a false condition. | 190 bool zero_is_false = true; // Zero in CMPRES1 indicates a false condition. |
| 168 switch (true_condition.rel_op()) { | 191 switch (true_condition.rel_op()) { |
| 169 case AL: return; // Result holds true_value. | 192 case AL: |
| 170 case NV: __ LoadImmediate(result, false_value); return; | 193 return; // Result holds true_value. |
| 194 case NV: |
| 195 __ LoadImmediate(result, false_value); |
| 196 return; |
| 171 case EQ: | 197 case EQ: |
| 172 zero_is_false = false; | 198 zero_is_false = false; |
| 173 // fall through. | 199 // fall through. |
| 174 case NE: { | 200 case NE: { |
| 175 if (left == IMM) { | 201 if (left == IMM) { |
| 176 __ XorImmediate(CMPRES1, right, true_condition.imm()); | 202 __ XorImmediate(CMPRES1, right, true_condition.imm()); |
| 177 } else if (right == IMM) { | 203 } else if (right == IMM) { |
| 178 __ XorImmediate(CMPRES1, left, true_condition.imm()); | 204 __ XorImmediate(CMPRES1, left, true_condition.imm()); |
| 179 } else { | 205 } else { |
| 180 __ xor_(CMPRES1, left, right); | 206 __ xor_(CMPRES1, left, right); |
| 181 } | 207 } |
| 182 break; | 208 break; |
| 183 } | 209 } |
| 184 case GE: | 210 case GE: |
| 185 zero_is_false = false; | 211 zero_is_false = false; |
| 186 // fall through. | 212 // fall through. |
| 187 case LT: { | 213 case LT: { |
| 188 if (left == IMM) { | 214 if (left == IMM) { |
| 189 __ slti(CMPRES1, right, Immediate(true_condition.imm() + 1)); | 215 __ slti(CMPRES1, right, Immediate(true_condition.imm() + 1)); |
| 190 zero_is_false = !zero_is_false; | 216 zero_is_false = !zero_is_false; |
| 191 } else if (right == IMM) { | 217 } else if (right == IMM) { |
| 192 __ slti(CMPRES1, left, Immediate(true_condition.imm())); | 218 __ slti(CMPRES1, left, Immediate(true_condition.imm())); |
| 193 } else { | 219 } else { |
| 194 __ slt(CMPRES1, left, right); | 220 __ slt(CMPRES1, left, right); |
| 195 } | 221 } |
| 196 break; | 222 break; |
| 197 } | 223 } |
| 198 case LE: | 224 case LE: |
| 199 zero_is_false = false; | 225 zero_is_false = false; |
| 200 // fall through. | 226 // fall through. |
| 201 case GT: { | 227 case GT: { |
| 202 if (left == IMM) { | 228 if (left == IMM) { |
| 203 __ slti(CMPRES1, right, Immediate(true_condition.imm())); | 229 __ slti(CMPRES1, right, Immediate(true_condition.imm())); |
| 204 } else if (right == IMM) { | 230 } else if (right == IMM) { |
| 205 __ slti(CMPRES1, left, Immediate(true_condition.imm() + 1)); | 231 __ slti(CMPRES1, left, Immediate(true_condition.imm() + 1)); |
| 206 zero_is_false = !zero_is_false; | 232 zero_is_false = !zero_is_false; |
| 207 } else { | 233 } else { |
| 208 __ slt(CMPRES1, right, left); | 234 __ slt(CMPRES1, right, left); |
| 209 } | 235 } |
| 210 break; | 236 break; |
| 211 } | 237 } |
| 212 case UGE: | 238 case UGE: |
| 213 zero_is_false = false; | 239 zero_is_false = false; |
| 214 // fall through. | 240 // fall through. |
| 215 case ULT: { | 241 case ULT: { |
| 216 ASSERT((left != IMM) && (right != IMM)); // No unsigned constants used. | 242 ASSERT((left != IMM) && (right != IMM)); // No unsigned constants used. |
| 217 __ sltu(CMPRES1, left, right); | 243 __ sltu(CMPRES1, left, right); |
| 218 break; | 244 break; |
| 219 } | 245 } |
| 220 case ULE: | 246 case ULE: |
| 221 zero_is_false = false; | 247 zero_is_false = false; |
| 222 // fall through. | 248 // fall through. |
| 223 case UGT: { | 249 case UGT: { |
| 224 ASSERT((left != IMM) && (right != IMM)); // No unsigned constants used. | 250 ASSERT((left != IMM) && (right != IMM)); // No unsigned constants used. |
| 225 __ sltu(CMPRES1, right, left); | 251 __ sltu(CMPRES1, right, left); |
| 226 break; | 252 break; |
| 227 } | 253 } |
| 228 default: | 254 default: |
| 229 UNREACHABLE(); | 255 UNREACHABLE(); |
| 230 } | 256 } |
| 231 | 257 |
| 232 // CMPRES1 is the evaluated condition, zero or non-zero, as specified by the | 258 // CMPRES1 is the evaluated condition, zero or non-zero, as specified by the |
| (...skipping 10 matching lines...) Expand all Loading... |
| 243 } else { | 269 } else { |
| 244 __ movn(result, false_value_reg, CMPRES1); | 270 __ movn(result, false_value_reg, CMPRES1); |
| 245 } | 271 } |
| 246 } | 272 } |
| 247 | 273 |
| 248 | 274 |
| 249 LocationSummary* ClosureCallInstr::MakeLocationSummary(Zone* zone, | 275 LocationSummary* ClosureCallInstr::MakeLocationSummary(Zone* zone, |
| 250 bool opt) const { | 276 bool opt) const { |
| 251 const intptr_t kNumInputs = 1; | 277 const intptr_t kNumInputs = 1; |
| 252 const intptr_t kNumTemps = 0; | 278 const intptr_t kNumTemps = 0; |
| 253 LocationSummary* summary = new(zone) LocationSummary( | 279 LocationSummary* summary = new (zone) |
| 254 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 280 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
| 255 summary->set_in(0, Location::RegisterLocation(T0)); // Function. | 281 summary->set_in(0, Location::RegisterLocation(T0)); // Function. |
| 256 summary->set_out(0, Location::RegisterLocation(V0)); | 282 summary->set_out(0, Location::RegisterLocation(V0)); |
| 257 return summary; | 283 return summary; |
| 258 } | 284 } |
| 259 | 285 |
| 260 | 286 |
| 261 void ClosureCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 287 void ClosureCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 262 // Load arguments descriptor in S4. | 288 // Load arguments descriptor in S4. |
| 263 int argument_count = ArgumentCount(); | 289 int argument_count = ArgumentCount(); |
| 264 const Array& arguments_descriptor = | 290 const Array& arguments_descriptor = Array::ZoneHandle( |
| 265 Array::ZoneHandle(ArgumentsDescriptor::New(argument_count, | 291 ArgumentsDescriptor::New(argument_count, argument_names())); |
| 266 argument_names())); | |
| 267 __ LoadObject(S4, arguments_descriptor); | 292 __ LoadObject(S4, arguments_descriptor); |
| 268 | 293 |
| 269 // Load closure function code in T2. | 294 // Load closure function code in T2. |
| 270 // S4: arguments descriptor array. | 295 // S4: arguments descriptor array. |
| 271 // S5: Smi 0 (no IC data; the lazy-compile stub expects a GC-safe value). | 296 // S5: Smi 0 (no IC data; the lazy-compile stub expects a GC-safe value). |
| 272 ASSERT(locs()->in(0).reg() == T0); | 297 ASSERT(locs()->in(0).reg() == T0); |
| 273 __ LoadImmediate(S5, 0); | 298 __ LoadImmediate(S5, 0); |
| 274 __ lw(T2, FieldAddress(T0, Function::entry_point_offset())); | 299 __ lw(T2, FieldAddress(T0, Function::entry_point_offset())); |
| 275 __ lw(CODE_REG, FieldAddress(T0, Function::code_offset())); | 300 __ lw(CODE_REG, FieldAddress(T0, Function::code_offset())); |
| 276 __ jalr(T2); | 301 __ jalr(T2); |
| 277 compiler->RecordSafepoint(locs()); | 302 compiler->RecordSafepoint(locs()); |
| 278 // Marks either the continuation point in unoptimized code or the | 303 // Marks either the continuation point in unoptimized code or the |
| 279 // deoptimization point in optimized code, after call. | 304 // deoptimization point in optimized code, after call. |
| 280 const intptr_t deopt_id_after = Thread::ToDeoptAfter(deopt_id()); | 305 const intptr_t deopt_id_after = Thread::ToDeoptAfter(deopt_id()); |
| 281 if (compiler->is_optimizing()) { | 306 if (compiler->is_optimizing()) { |
| 282 compiler->AddDeoptIndexAtCall(deopt_id_after); | 307 compiler->AddDeoptIndexAtCall(deopt_id_after); |
| 283 } | 308 } |
| 284 // Add deoptimization continuation point after the call and before the | 309 // Add deoptimization continuation point after the call and before the |
| 285 // arguments are removed. | 310 // arguments are removed. |
| 286 // In optimized code this descriptor is needed for exception handling. | 311 // In optimized code this descriptor is needed for exception handling. |
| 287 compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt, | 312 compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt, deopt_id_after, |
| 288 deopt_id_after, | |
| 289 token_pos()); | 313 token_pos()); |
| 290 __ Drop(argument_count); | 314 __ Drop(argument_count); |
| 291 } | 315 } |
| 292 | 316 |
| 293 | 317 |
| 294 LocationSummary* LoadLocalInstr::MakeLocationSummary(Zone* zone, | 318 LocationSummary* LoadLocalInstr::MakeLocationSummary(Zone* zone, |
| 295 bool opt) const { | 319 bool opt) const { |
| 296 return LocationSummary::Make(zone, | 320 return LocationSummary::Make(zone, 0, Location::RequiresRegister(), |
| 297 0, | |
| 298 Location::RequiresRegister(), | |
| 299 LocationSummary::kNoCall); | 321 LocationSummary::kNoCall); |
| 300 } | 322 } |
| 301 | 323 |
| 302 | 324 |
| 303 void LoadLocalInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 325 void LoadLocalInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 304 __ Comment("LoadLocalInstr"); | 326 __ Comment("LoadLocalInstr"); |
| 305 Register result = locs()->out(0).reg(); | 327 Register result = locs()->out(0).reg(); |
| 306 __ LoadFromOffset(result, FP, local().index() * kWordSize); | 328 __ LoadFromOffset(result, FP, local().index() * kWordSize); |
| 307 } | 329 } |
| 308 | 330 |
| 309 | 331 |
| 310 LocationSummary* StoreLocalInstr::MakeLocationSummary(Zone* zone, | 332 LocationSummary* StoreLocalInstr::MakeLocationSummary(Zone* zone, |
| 311 bool opt) const { | 333 bool opt) const { |
| 312 return LocationSummary::Make(zone, | 334 return LocationSummary::Make(zone, 1, Location::SameAsFirstInput(), |
| 313 1, | |
| 314 Location::SameAsFirstInput(), | |
| 315 LocationSummary::kNoCall); | 335 LocationSummary::kNoCall); |
| 316 } | 336 } |
| 317 | 337 |
| 318 | 338 |
| 319 void StoreLocalInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 339 void StoreLocalInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 320 __ Comment("StoreLocalInstr"); | 340 __ Comment("StoreLocalInstr"); |
| 321 Register value = locs()->in(0).reg(); | 341 Register value = locs()->in(0).reg(); |
| 322 Register result = locs()->out(0).reg(); | 342 Register result = locs()->out(0).reg(); |
| 323 ASSERT(result == value); // Assert that register assignment is correct. | 343 ASSERT(result == value); // Assert that register assignment is correct. |
| 324 __ StoreToOffset(value, FP, local().index() * kWordSize); | 344 __ StoreToOffset(value, FP, local().index() * kWordSize); |
| 325 } | 345 } |
| 326 | 346 |
| 327 | 347 |
| 328 LocationSummary* ConstantInstr::MakeLocationSummary(Zone* zone, | 348 LocationSummary* ConstantInstr::MakeLocationSummary(Zone* zone, |
| 329 bool opt) const { | 349 bool opt) const { |
| 330 return LocationSummary::Make(zone, | 350 return LocationSummary::Make(zone, 0, Location::RequiresRegister(), |
| 331 0, | |
| 332 Location::RequiresRegister(), | |
| 333 LocationSummary::kNoCall); | 351 LocationSummary::kNoCall); |
| 334 } | 352 } |
| 335 | 353 |
| 336 | 354 |
| 337 void ConstantInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 355 void ConstantInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 338 // The register allocator drops constant definitions that have no uses. | 356 // The register allocator drops constant definitions that have no uses. |
| 339 if (!locs()->out(0).IsInvalid()) { | 357 if (!locs()->out(0).IsInvalid()) { |
| 340 __ Comment("ConstantInstr"); | 358 __ Comment("ConstantInstr"); |
| 341 Register result = locs()->out(0).reg(); | 359 Register result = locs()->out(0).reg(); |
| 342 __ LoadObject(result, value()); | 360 __ LoadObject(result, value()); |
| 343 } | 361 } |
| 344 } | 362 } |
| 345 | 363 |
| 346 | 364 |
| 347 LocationSummary* UnboxedConstantInstr::MakeLocationSummary(Zone* zone, | 365 LocationSummary* UnboxedConstantInstr::MakeLocationSummary(Zone* zone, |
| 348 bool opt) const { | 366 bool opt) const { |
| 349 const intptr_t kNumInputs = 0; | 367 const intptr_t kNumInputs = 0; |
| 350 const intptr_t kNumTemps = (representation_ == kUnboxedInt32) ? 0 : 1; | 368 const intptr_t kNumTemps = (representation_ == kUnboxedInt32) ? 0 : 1; |
| 351 LocationSummary* locs = new(zone) LocationSummary( | 369 LocationSummary* locs = new (zone) |
| 352 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 370 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 353 if (representation_ == kUnboxedInt32) { | 371 if (representation_ == kUnboxedInt32) { |
| 354 locs->set_out(0, Location::RequiresRegister()); | 372 locs->set_out(0, Location::RequiresRegister()); |
| 355 } else { | 373 } else { |
| 356 ASSERT(representation_ == kUnboxedDouble); | 374 ASSERT(representation_ == kUnboxedDouble); |
| 357 locs->set_out(0, Location::RequiresFpuRegister()); | 375 locs->set_out(0, Location::RequiresFpuRegister()); |
| 358 } | 376 } |
| 359 if (kNumTemps > 0) { | 377 if (kNumTemps > 0) { |
| 360 locs->set_temp(0, Location::RequiresRegister()); | 378 locs->set_temp(0, Location::RequiresRegister()); |
| 361 } | 379 } |
| 362 return locs; | 380 return locs; |
| 363 } | 381 } |
| 364 | 382 |
| 365 | 383 |
| 366 void UnboxedConstantInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 384 void UnboxedConstantInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 367 // The register allocator drops constant definitions that have no uses. | 385 // The register allocator drops constant definitions that have no uses. |
| 368 if (!locs()->out(0).IsInvalid()) { | 386 if (!locs()->out(0).IsInvalid()) { |
| 369 switch (representation_) { | 387 switch (representation_) { |
| 370 case kUnboxedDouble: { | 388 case kUnboxedDouble: { |
| 371 ASSERT(value().IsDouble()); | 389 ASSERT(value().IsDouble()); |
| 372 const Register const_value = locs()->temp(0).reg(); | 390 const Register const_value = locs()->temp(0).reg(); |
| 373 const DRegister result = locs()->out(0).fpu_reg(); | 391 const DRegister result = locs()->out(0).fpu_reg(); |
| 374 __ LoadObject(const_value, value()); | 392 __ LoadObject(const_value, value()); |
| 375 __ LoadDFromOffset(result, const_value, | 393 __ LoadDFromOffset(result, const_value, |
| 376 Double::value_offset() - kHeapObjectTag); | 394 Double::value_offset() - kHeapObjectTag); |
| 377 break; | 395 break; |
| 378 } | 396 } |
| 379 | 397 |
| 380 case kUnboxedInt32: | 398 case kUnboxedInt32: |
| 381 __ LoadImmediate(locs()->out(0).reg(), | 399 __ LoadImmediate(locs()->out(0).reg(), Smi::Cast(value()).Value()); |
| 382 Smi::Cast(value()).Value()); | |
| 383 break; | 400 break; |
| 384 | 401 |
| 385 default: | 402 default: |
| 386 UNREACHABLE(); | 403 UNREACHABLE(); |
| 387 } | 404 } |
| 388 } | 405 } |
| 389 } | 406 } |
| 390 | 407 |
| 391 | 408 |
| 392 LocationSummary* AssertAssignableInstr::MakeLocationSummary(Zone* zone, | 409 LocationSummary* AssertAssignableInstr::MakeLocationSummary(Zone* zone, |
| 393 bool opt) const { | 410 bool opt) const { |
| 394 const intptr_t kNumInputs = 2; | 411 const intptr_t kNumInputs = 2; |
| 395 const intptr_t kNumTemps = 0; | 412 const intptr_t kNumTemps = 0; |
| 396 LocationSummary* summary = new(zone) LocationSummary( | 413 LocationSummary* summary = new (zone) |
| 397 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 414 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
| 398 summary->set_in(0, Location::RegisterLocation(A0)); // Value. | 415 summary->set_in(0, Location::RegisterLocation(A0)); // Value. |
| 399 summary->set_in(1, Location::RegisterLocation(A1)); // Type arguments. | 416 summary->set_in(1, Location::RegisterLocation(A1)); // Type arguments. |
| 400 summary->set_out(0, Location::RegisterLocation(A0)); | 417 summary->set_out(0, Location::RegisterLocation(A0)); |
| 401 return summary; | 418 return summary; |
| 402 } | 419 } |
| 403 | 420 |
| 404 | 421 |
| 405 LocationSummary* AssertBooleanInstr::MakeLocationSummary(Zone* zone, | 422 LocationSummary* AssertBooleanInstr::MakeLocationSummary(Zone* zone, |
| 406 bool opt) const { | 423 bool opt) const { |
| 407 const intptr_t kNumInputs = 1; | 424 const intptr_t kNumInputs = 1; |
| 408 const intptr_t kNumTemps = 0; | 425 const intptr_t kNumTemps = 0; |
| 409 LocationSummary* locs = new(zone) LocationSummary( | 426 LocationSummary* locs = new (zone) |
| 410 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 427 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
| 411 locs->set_in(0, Location::RegisterLocation(A0)); | 428 locs->set_in(0, Location::RegisterLocation(A0)); |
| 412 locs->set_out(0, Location::RegisterLocation(A0)); | 429 locs->set_out(0, Location::RegisterLocation(A0)); |
| 413 return locs; | 430 return locs; |
| 414 } | 431 } |
| 415 | 432 |
| 416 | 433 |
| 417 static void EmitAssertBoolean(Register reg, | 434 static void EmitAssertBoolean(Register reg, |
| 418 TokenPosition token_pos, | 435 TokenPosition token_pos, |
| 419 intptr_t deopt_id, | 436 intptr_t deopt_id, |
| 420 LocationSummary* locs, | 437 LocationSummary* locs, |
| 421 FlowGraphCompiler* compiler) { | 438 FlowGraphCompiler* compiler) { |
| 422 // Check that the type of the value is allowed in conditional context. | 439 // Check that the type of the value is allowed in conditional context. |
| 423 // Call the runtime if the object is not bool::true or bool::false. | 440 // Call the runtime if the object is not bool::true or bool::false. |
| 424 ASSERT(locs->always_calls()); | 441 ASSERT(locs->always_calls()); |
| 425 Label done; | 442 Label done; |
| 426 | 443 |
| 427 if (Isolate::Current()->type_checks()) { | 444 if (Isolate::Current()->type_checks()) { |
| 428 __ BranchEqual(reg, Bool::True(), &done); | 445 __ BranchEqual(reg, Bool::True(), &done); |
| 429 __ BranchEqual(reg, Bool::False(), &done); | 446 __ BranchEqual(reg, Bool::False(), &done); |
| 430 } else { | 447 } else { |
| 431 ASSERT(Isolate::Current()->asserts()); | 448 ASSERT(Isolate::Current()->asserts()); |
| 432 __ BranchNotEqual(reg, Object::null_instance(), &done); | 449 __ BranchNotEqual(reg, Object::null_instance(), &done); |
| 433 } | 450 } |
| 434 | 451 |
| 435 __ Push(reg); // Push the source object. | 452 __ Push(reg); // Push the source object. |
| 436 compiler->GenerateRuntimeCall(token_pos, | 453 compiler->GenerateRuntimeCall(token_pos, deopt_id, |
| 437 deopt_id, | 454 kNonBoolTypeErrorRuntimeEntry, 1, locs); |
| 438 kNonBoolTypeErrorRuntimeEntry, | |
| 439 1, | |
| 440 locs); | |
| 441 // We should never return here. | 455 // We should never return here. |
| 442 __ break_(0); | 456 __ break_(0); |
| 443 __ Bind(&done); | 457 __ Bind(&done); |
| 444 } | 458 } |
| 445 | 459 |
| 446 | 460 |
| 447 void AssertBooleanInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 461 void AssertBooleanInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 448 Register obj = locs()->in(0).reg(); | 462 Register obj = locs()->in(0).reg(); |
| 449 Register result = locs()->out(0).reg(); | 463 Register result = locs()->out(0).reg(); |
| 450 | 464 |
| 451 __ Comment("AssertBooleanInstr"); | 465 __ Comment("AssertBooleanInstr"); |
| 452 EmitAssertBoolean(obj, token_pos(), deopt_id(), locs(), compiler); | 466 EmitAssertBoolean(obj, token_pos(), deopt_id(), locs(), compiler); |
| 453 ASSERT(obj == result); | 467 ASSERT(obj == result); |
| 454 } | 468 } |
| 455 | 469 |
| 456 | 470 |
| 457 LocationSummary* EqualityCompareInstr::MakeLocationSummary(Zone* zone, | 471 LocationSummary* EqualityCompareInstr::MakeLocationSummary(Zone* zone, |
| 458 bool opt) const { | 472 bool opt) const { |
| 459 const intptr_t kNumInputs = 2; | 473 const intptr_t kNumInputs = 2; |
| 460 if (operation_cid() == kMintCid) { | 474 if (operation_cid() == kMintCid) { |
| 461 const intptr_t kNumTemps = 0; | 475 const intptr_t kNumTemps = 0; |
| 462 LocationSummary* locs = new(zone) LocationSummary( | 476 LocationSummary* locs = new (zone) |
| 463 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 477 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 464 locs->set_in(0, Location::Pair(Location::RequiresRegister(), | 478 locs->set_in(0, Location::Pair(Location::RequiresRegister(), |
| 465 Location::RequiresRegister())); | 479 Location::RequiresRegister())); |
| 466 locs->set_in(1, Location::Pair(Location::RequiresRegister(), | 480 locs->set_in(1, Location::Pair(Location::RequiresRegister(), |
| 467 Location::RequiresRegister())); | 481 Location::RequiresRegister())); |
| 468 locs->set_out(0, Location::RequiresRegister()); | 482 locs->set_out(0, Location::RequiresRegister()); |
| 469 return locs; | 483 return locs; |
| 470 } | 484 } |
| 471 if (operation_cid() == kDoubleCid) { | 485 if (operation_cid() == kDoubleCid) { |
| 472 const intptr_t kNumTemps = 0; | 486 const intptr_t kNumTemps = 0; |
| 473 LocationSummary* locs = new(zone) LocationSummary( | 487 LocationSummary* locs = new (zone) |
| 474 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 488 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 475 locs->set_in(0, Location::RequiresFpuRegister()); | 489 locs->set_in(0, Location::RequiresFpuRegister()); |
| 476 locs->set_in(1, Location::RequiresFpuRegister()); | 490 locs->set_in(1, Location::RequiresFpuRegister()); |
| 477 locs->set_out(0, Location::RequiresRegister()); | 491 locs->set_out(0, Location::RequiresRegister()); |
| 478 return locs; | 492 return locs; |
| 479 } | 493 } |
| 480 if (operation_cid() == kSmiCid) { | 494 if (operation_cid() == kSmiCid) { |
| 481 const intptr_t kNumTemps = 0; | 495 const intptr_t kNumTemps = 0; |
| 482 LocationSummary* locs = new(zone) LocationSummary( | 496 LocationSummary* locs = new (zone) |
| 483 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 497 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 484 locs->set_in(0, Location::RegisterOrConstant(left())); | 498 locs->set_in(0, Location::RegisterOrConstant(left())); |
| 485 // Only one input can be a constant operand. The case of two constant | 499 // Only one input can be a constant operand. The case of two constant |
| 486 // operands should be handled by constant propagation. | 500 // operands should be handled by constant propagation. |
| 487 locs->set_in(1, locs->in(0).IsConstant() | 501 locs->set_in(1, locs->in(0).IsConstant() |
| 488 ? Location::RequiresRegister() | 502 ? Location::RequiresRegister() |
| 489 : Location::RegisterOrConstant(right())); | 503 : Location::RegisterOrConstant(right())); |
| 490 locs->set_out(0, Location::RequiresRegister()); | 504 locs->set_out(0, Location::RequiresRegister()); |
| 491 return locs; | 505 return locs; |
| 492 } | 506 } |
| 493 UNREACHABLE(); | 507 UNREACHABLE(); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 510 } else { | 524 } else { |
| 511 __ beq(CMPRES1, ZR, value_is_smi); | 525 __ beq(CMPRES1, ZR, value_is_smi); |
| 512 } | 526 } |
| 513 __ LoadClassId(value_cid_reg, value_reg); | 527 __ LoadClassId(value_cid_reg, value_reg); |
| 514 __ Bind(&done); | 528 __ Bind(&done); |
| 515 } | 529 } |
| 516 | 530 |
| 517 | 531 |
| 518 static RelationOperator TokenKindToIntRelOp(Token::Kind kind) { | 532 static RelationOperator TokenKindToIntRelOp(Token::Kind kind) { |
| 519 switch (kind) { | 533 switch (kind) { |
| 520 case Token::kEQ: return EQ; | 534 case Token::kEQ: |
| 521 case Token::kNE: return NE; | 535 return EQ; |
| 522 case Token::kLT: return LT; | 536 case Token::kNE: |
| 523 case Token::kGT: return GT; | 537 return NE; |
| 524 case Token::kLTE: return LE; | 538 case Token::kLT: |
| 525 case Token::kGTE: return GE; | 539 return LT; |
| 540 case Token::kGT: |
| 541 return GT; |
| 542 case Token::kLTE: |
| 543 return LE; |
| 544 case Token::kGTE: |
| 545 return GE; |
| 526 default: | 546 default: |
| 527 UNREACHABLE(); | 547 UNREACHABLE(); |
| 528 return NV; | 548 return NV; |
| 529 } | 549 } |
| 530 } | 550 } |
| 531 | 551 |
| 532 | 552 |
| 533 static RelationOperator TokenKindToUintRelOp(Token::Kind kind) { | 553 static RelationOperator TokenKindToUintRelOp(Token::Kind kind) { |
| 534 switch (kind) { | 554 switch (kind) { |
| 535 case Token::kEQ: return EQ; | 555 case Token::kEQ: |
| 536 case Token::kNE: return NE; | 556 return EQ; |
| 537 case Token::kLT: return ULT; | 557 case Token::kNE: |
| 538 case Token::kGT: return UGT; | 558 return NE; |
| 539 case Token::kLTE: return ULE; | 559 case Token::kLT: |
| 540 case Token::kGTE: return UGE; | 560 return ULT; |
| 561 case Token::kGT: |
| 562 return UGT; |
| 563 case Token::kLTE: |
| 564 return ULE; |
| 565 case Token::kGTE: |
| 566 return UGE; |
| 541 default: | 567 default: |
| 542 UNREACHABLE(); | 568 UNREACHABLE(); |
| 543 return NV; | 569 return NV; |
| 544 } | 570 } |
| 545 } | 571 } |
| 546 | 572 |
| 547 | 573 |
| 548 // The comparison code to emit is specified by true_condition. | 574 // The comparison code to emit is specified by true_condition. |
| 549 static void EmitBranchOnCondition(FlowGraphCompiler* compiler, | 575 static void EmitBranchOnCondition(FlowGraphCompiler* compiler, |
| 550 Condition true_condition, | 576 Condition true_condition, |
| (...skipping 18 matching lines...) Expand all Loading... |
| 569 const LocationSummary& locs, | 595 const LocationSummary& locs, |
| 570 Token::Kind kind) { | 596 Token::Kind kind) { |
| 571 __ Comment("EmitSmiComparisonOp"); | 597 __ Comment("EmitSmiComparisonOp"); |
| 572 const Location left = locs.in(0); | 598 const Location left = locs.in(0); |
| 573 const Location right = locs.in(1); | 599 const Location right = locs.in(1); |
| 574 ASSERT(!left.IsConstant() || !right.IsConstant()); | 600 ASSERT(!left.IsConstant() || !right.IsConstant()); |
| 575 ASSERT(left.IsRegister() || left.IsConstant()); | 601 ASSERT(left.IsRegister() || left.IsConstant()); |
| 576 ASSERT(right.IsRegister() || right.IsConstant()); | 602 ASSERT(right.IsRegister() || right.IsConstant()); |
| 577 | 603 |
| 578 int16_t imm = 0; | 604 int16_t imm = 0; |
| 579 const Register left_reg = left.IsRegister() ? | 605 const Register left_reg = |
| 580 left.reg() : __ LoadConditionOperand(CMPRES1, left.constant(), &imm); | 606 left.IsRegister() ? left.reg() : __ LoadConditionOperand( |
| 581 const Register right_reg = right.IsRegister() ? | 607 CMPRES1, left.constant(), &imm); |
| 582 right.reg() : __ LoadConditionOperand(CMPRES2, right.constant(), &imm); | 608 const Register right_reg = |
| 609 right.IsRegister() ? right.reg() : __ LoadConditionOperand( |
| 610 CMPRES2, right.constant(), &imm); |
| 583 return Condition(left_reg, right_reg, TokenKindToIntRelOp(kind), imm); | 611 return Condition(left_reg, right_reg, TokenKindToIntRelOp(kind), imm); |
| 584 } | 612 } |
| 585 | 613 |
| 586 | 614 |
| 587 static Condition EmitUnboxedMintEqualityOp(FlowGraphCompiler* compiler, | 615 static Condition EmitUnboxedMintEqualityOp(FlowGraphCompiler* compiler, |
| 588 const LocationSummary& locs, | 616 const LocationSummary& locs, |
| 589 Token::Kind kind, | 617 Token::Kind kind, |
| 590 BranchLabels labels) { | 618 BranchLabels labels) { |
| 591 __ Comment("EmitUnboxedMintEqualityOp"); | 619 __ Comment("EmitUnboxedMintEqualityOp"); |
| 592 ASSERT(Token::IsEqualityOperator(kind)); | 620 ASSERT(Token::IsEqualityOperator(kind)); |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 670 static Condition EmitDoubleComparisonOp(FlowGraphCompiler* compiler, | 698 static Condition EmitDoubleComparisonOp(FlowGraphCompiler* compiler, |
| 671 const LocationSummary& locs, | 699 const LocationSummary& locs, |
| 672 Token::Kind kind, | 700 Token::Kind kind, |
| 673 BranchLabels labels) { | 701 BranchLabels labels) { |
| 674 DRegister left = locs.in(0).fpu_reg(); | 702 DRegister left = locs.in(0).fpu_reg(); |
| 675 DRegister right = locs.in(1).fpu_reg(); | 703 DRegister right = locs.in(1).fpu_reg(); |
| 676 | 704 |
| 677 __ Comment("DoubleComparisonOp(left=%d, right=%d)", left, right); | 705 __ Comment("DoubleComparisonOp(left=%d, right=%d)", left, right); |
| 678 | 706 |
| 679 __ cund(left, right); | 707 __ cund(left, right); |
| 680 Label* nan_label = (kind == Token::kNE) | 708 Label* nan_label = |
| 681 ? labels.true_label : labels.false_label; | 709 (kind == Token::kNE) ? labels.true_label : labels.false_label; |
| 682 __ bc1t(nan_label); | 710 __ bc1t(nan_label); |
| 683 | 711 |
| 684 switch (kind) { | 712 switch (kind) { |
| 685 case Token::kEQ: __ ceqd(left, right); break; | 713 case Token::kEQ: |
| 686 case Token::kNE: __ ceqd(left, right); break; | 714 __ ceqd(left, right); |
| 687 case Token::kLT: __ coltd(left, right); break; | 715 break; |
| 688 case Token::kLTE: __ coled(left, right); break; | 716 case Token::kNE: |
| 689 case Token::kGT: __ coltd(right, left); break; | 717 __ ceqd(left, right); |
| 690 case Token::kGTE: __ coled(right, left); break; | 718 break; |
| 719 case Token::kLT: |
| 720 __ coltd(left, right); |
| 721 break; |
| 722 case Token::kLTE: |
| 723 __ coled(left, right); |
| 724 break; |
| 725 case Token::kGT: |
| 726 __ coltd(right, left); |
| 727 break; |
| 728 case Token::kGTE: |
| 729 __ coled(right, left); |
| 730 break; |
| 691 default: { | 731 default: { |
| 692 // We should only be passing the above conditions to this function. | 732 // We should only be passing the above conditions to this function. |
| 693 UNREACHABLE(); | 733 UNREACHABLE(); |
| 694 break; | 734 break; |
| 695 } | 735 } |
| 696 } | 736 } |
| 697 | 737 |
| 698 if (labels.false_label == NULL) { | 738 if (labels.false_label == NULL) { |
| 699 // Generate branch-free code and return result in condition. | 739 // Generate branch-free code and return result in condition. |
| 700 __ LoadImmediate(CMPRES1, 1); | 740 __ LoadImmediate(CMPRES1, 1); |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 737 return EmitDoubleComparisonOp(compiler, *locs(), kind(), labels); | 777 return EmitDoubleComparisonOp(compiler, *locs(), kind(), labels); |
| 738 } | 778 } |
| 739 } | 779 } |
| 740 | 780 |
| 741 | 781 |
| 742 void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 782 void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 743 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ)); | 783 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ)); |
| 744 __ Comment("EqualityCompareInstr"); | 784 __ Comment("EqualityCompareInstr"); |
| 745 | 785 |
| 746 Label is_true, is_false; | 786 Label is_true, is_false; |
| 747 BranchLabels labels = { &is_true, &is_false, &is_false }; | 787 BranchLabels labels = {&is_true, &is_false, &is_false}; |
| 748 Condition true_condition = EmitComparisonCode(compiler, labels); | 788 Condition true_condition = EmitComparisonCode(compiler, labels); |
| 749 EmitBranchOnCondition(compiler, true_condition, labels); | 789 EmitBranchOnCondition(compiler, true_condition, labels); |
| 750 | 790 |
| 751 Register result = locs()->out(0).reg(); | 791 Register result = locs()->out(0).reg(); |
| 752 Label done; | 792 Label done; |
| 753 __ Bind(&is_false); | 793 __ Bind(&is_false); |
| 754 __ LoadObject(result, Bool::False()); | 794 __ LoadObject(result, Bool::False()); |
| 755 __ b(&done); | 795 __ b(&done); |
| 756 __ Bind(&is_true); | 796 __ Bind(&is_true); |
| 757 __ LoadObject(result, Bool::True()); | 797 __ LoadObject(result, Bool::True()); |
| 758 __ Bind(&done); | 798 __ Bind(&done); |
| 759 } | 799 } |
| 760 | 800 |
| 761 | 801 |
| 762 void EqualityCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 802 void EqualityCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
| 763 BranchInstr* branch) { | 803 BranchInstr* branch) { |
| 764 __ Comment("EqualityCompareInstr::EmitBranchCode"); | 804 __ Comment("EqualityCompareInstr::EmitBranchCode"); |
| 765 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ)); | 805 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ)); |
| 766 | 806 |
| 767 BranchLabels labels = compiler->CreateBranchLabels(branch); | 807 BranchLabels labels = compiler->CreateBranchLabels(branch); |
| 768 Condition true_condition = EmitComparisonCode(compiler, labels); | 808 Condition true_condition = EmitComparisonCode(compiler, labels); |
| 769 EmitBranchOnCondition(compiler, true_condition, labels); | 809 EmitBranchOnCondition(compiler, true_condition, labels); |
| 770 } | 810 } |
| 771 | 811 |
| 772 | 812 |
| 773 LocationSummary* TestSmiInstr::MakeLocationSummary(Zone* zone, | 813 LocationSummary* TestSmiInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
| 774 bool opt) const { | |
| 775 const intptr_t kNumInputs = 2; | 814 const intptr_t kNumInputs = 2; |
| 776 const intptr_t kNumTemps = 0; | 815 const intptr_t kNumTemps = 0; |
| 777 LocationSummary* locs = new(zone) LocationSummary( | 816 LocationSummary* locs = new (zone) |
| 778 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 817 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 779 locs->set_in(0, Location::RequiresRegister()); | 818 locs->set_in(0, Location::RequiresRegister()); |
| 780 // Only one input can be a constant operand. The case of two constant | 819 // Only one input can be a constant operand. The case of two constant |
| 781 // operands should be handled by constant propagation. | 820 // operands should be handled by constant propagation. |
| 782 locs->set_in(1, Location::RegisterOrConstant(right())); | 821 locs->set_in(1, Location::RegisterOrConstant(right())); |
| 783 return locs; | 822 return locs; |
| 784 } | 823 } |
| 785 | 824 |
| 786 | 825 |
| 787 Condition TestSmiInstr::EmitComparisonCode(FlowGraphCompiler* compiler, | 826 Condition TestSmiInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
| 788 BranchLabels labels) { | 827 BranchLabels labels) { |
| 789 Register left = locs()->in(0).reg(); | 828 Register left = locs()->in(0).reg(); |
| 790 Location right = locs()->in(1); | 829 Location right = locs()->in(1); |
| 791 if (right.IsConstant()) { | 830 if (right.IsConstant()) { |
| 792 ASSERT(right.constant().IsSmi()); | 831 ASSERT(right.constant().IsSmi()); |
| 793 const int32_t imm = | 832 const int32_t imm = reinterpret_cast<int32_t>(right.constant().raw()); |
| 794 reinterpret_cast<int32_t>(right.constant().raw()); | |
| 795 __ AndImmediate(CMPRES1, left, imm); | 833 __ AndImmediate(CMPRES1, left, imm); |
| 796 } else { | 834 } else { |
| 797 __ and_(CMPRES1, left, right.reg()); | 835 __ and_(CMPRES1, left, right.reg()); |
| 798 } | 836 } |
| 799 return Condition(CMPRES1, ZR, (kind() == Token::kNE) ? NE : EQ); | 837 return Condition(CMPRES1, ZR, (kind() == Token::kNE) ? NE : EQ); |
| 800 } | 838 } |
| 801 | 839 |
| 802 | 840 |
| 803 void TestSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 841 void TestSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 804 // Never emitted outside of the BranchInstr. | 842 // Never emitted outside of the BranchInstr. |
| 805 UNREACHABLE(); | 843 UNREACHABLE(); |
| 806 } | 844 } |
| 807 | 845 |
| 808 | 846 |
| 809 void TestSmiInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 847 void TestSmiInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
| 810 BranchInstr* branch) { | 848 BranchInstr* branch) { |
| 811 BranchLabels labels = compiler->CreateBranchLabels(branch); | 849 BranchLabels labels = compiler->CreateBranchLabels(branch); |
| 812 Condition true_condition = EmitComparisonCode(compiler, labels); | 850 Condition true_condition = EmitComparisonCode(compiler, labels); |
| 813 EmitBranchOnCondition(compiler, true_condition, labels); | 851 EmitBranchOnCondition(compiler, true_condition, labels); |
| 814 } | 852 } |
| 815 | 853 |
| 816 | 854 |
| 817 LocationSummary* TestCidsInstr::MakeLocationSummary(Zone* zone, | 855 LocationSummary* TestCidsInstr::MakeLocationSummary(Zone* zone, |
| 818 bool opt) const { | 856 bool opt) const { |
| 819 const intptr_t kNumInputs = 1; | 857 const intptr_t kNumInputs = 1; |
| 820 const intptr_t kNumTemps = 1; | 858 const intptr_t kNumTemps = 1; |
| 821 LocationSummary* locs = new(zone) LocationSummary( | 859 LocationSummary* locs = new (zone) |
| 822 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 860 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 823 locs->set_in(0, Location::RequiresRegister()); | 861 locs->set_in(0, Location::RequiresRegister()); |
| 824 locs->set_temp(0, Location::RequiresRegister()); | 862 locs->set_temp(0, Location::RequiresRegister()); |
| 825 locs->set_out(0, Location::RequiresRegister()); | 863 locs->set_out(0, Location::RequiresRegister()); |
| 826 return locs; | 864 return locs; |
| 827 } | 865 } |
| 828 | 866 |
| 829 | 867 |
| 830 Condition TestCidsInstr::EmitComparisonCode(FlowGraphCompiler* compiler, | 868 Condition TestCidsInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
| 831 BranchLabels labels) { | 869 BranchLabels labels) { |
| 832 ASSERT((kind() == Token::kIS) || (kind() == Token::kISNOT)); | 870 ASSERT((kind() == Token::kIS) || (kind() == Token::kISNOT)); |
| 833 Register val_reg = locs()->in(0).reg(); | 871 Register val_reg = locs()->in(0).reg(); |
| 834 Register cid_reg = locs()->temp(0).reg(); | 872 Register cid_reg = locs()->temp(0).reg(); |
| 835 | 873 |
| 836 Label* deopt = CanDeoptimize() | 874 Label* deopt = |
| 837 ? compiler->AddDeoptStub(deopt_id(), | 875 CanDeoptimize() |
| 838 ICData::kDeoptTestCids, | 876 ? compiler->AddDeoptStub(deopt_id(), ICData::kDeoptTestCids, |
| 839 licm_hoisted_ ? ICData::kHoisted : 0) | 877 licm_hoisted_ ? ICData::kHoisted : 0) |
| 840 : NULL; | 878 : NULL; |
| 841 | 879 |
| 842 const intptr_t true_result = (kind() == Token::kIS) ? 1 : 0; | 880 const intptr_t true_result = (kind() == Token::kIS) ? 1 : 0; |
| 843 const ZoneGrowableArray<intptr_t>& data = cid_results(); | 881 const ZoneGrowableArray<intptr_t>& data = cid_results(); |
| 844 ASSERT(data[0] == kSmiCid); | 882 ASSERT(data[0] == kSmiCid); |
| 845 bool result = data[1] == true_result; | 883 bool result = data[1] == true_result; |
| 846 __ andi(CMPRES1, val_reg, Immediate(kSmiTagMask)); | 884 __ andi(CMPRES1, val_reg, Immediate(kSmiTagMask)); |
| 847 __ beq(CMPRES1, ZR, result ? labels.true_label : labels.false_label); | 885 __ beq(CMPRES1, ZR, result ? labels.true_label : labels.false_label); |
| 848 | 886 |
| 849 __ LoadClassId(cid_reg, val_reg); | 887 __ LoadClassId(cid_reg, val_reg); |
| 850 for (intptr_t i = 2; i < data.length(); i += 2) { | 888 for (intptr_t i = 2; i < data.length(); i += 2) { |
| (...skipping 20 matching lines...) Expand all Loading... |
| 871 void TestCidsInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 909 void TestCidsInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
| 872 BranchInstr* branch) { | 910 BranchInstr* branch) { |
| 873 BranchLabels labels = compiler->CreateBranchLabels(branch); | 911 BranchLabels labels = compiler->CreateBranchLabels(branch); |
| 874 EmitComparisonCode(compiler, labels); | 912 EmitComparisonCode(compiler, labels); |
| 875 } | 913 } |
| 876 | 914 |
| 877 | 915 |
| 878 void TestCidsInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 916 void TestCidsInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 879 Register result_reg = locs()->out(0).reg(); | 917 Register result_reg = locs()->out(0).reg(); |
| 880 Label is_true, is_false, done; | 918 Label is_true, is_false, done; |
| 881 BranchLabels labels = { &is_true, &is_false, &is_false }; | 919 BranchLabels labels = {&is_true, &is_false, &is_false}; |
| 882 EmitComparisonCode(compiler, labels); | 920 EmitComparisonCode(compiler, labels); |
| 883 __ Bind(&is_false); | 921 __ Bind(&is_false); |
| 884 __ LoadObject(result_reg, Bool::False()); | 922 __ LoadObject(result_reg, Bool::False()); |
| 885 __ b(&done); | 923 __ b(&done); |
| 886 __ Bind(&is_true); | 924 __ Bind(&is_true); |
| 887 __ LoadObject(result_reg, Bool::True()); | 925 __ LoadObject(result_reg, Bool::True()); |
| 888 __ Bind(&done); | 926 __ Bind(&done); |
| 889 } | 927 } |
| 890 | 928 |
| 891 | 929 |
| 892 LocationSummary* RelationalOpInstr::MakeLocationSummary(Zone* zone, | 930 LocationSummary* RelationalOpInstr::MakeLocationSummary(Zone* zone, |
| 893 bool opt) const { | 931 bool opt) const { |
| 894 const intptr_t kNumInputs = 2; | 932 const intptr_t kNumInputs = 2; |
| 895 const intptr_t kNumTemps = 0; | 933 const intptr_t kNumTemps = 0; |
| 896 if (operation_cid() == kMintCid) { | 934 if (operation_cid() == kMintCid) { |
| 897 const intptr_t kNumTemps = 0; | 935 const intptr_t kNumTemps = 0; |
| 898 LocationSummary* locs = new(zone) LocationSummary( | 936 LocationSummary* locs = new (zone) |
| 899 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 937 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 900 locs->set_in(0, Location::Pair(Location::RequiresRegister(), | 938 locs->set_in(0, Location::Pair(Location::RequiresRegister(), |
| 901 Location::RequiresRegister())); | 939 Location::RequiresRegister())); |
| 902 locs->set_in(1, Location::Pair(Location::RequiresRegister(), | 940 locs->set_in(1, Location::Pair(Location::RequiresRegister(), |
| 903 Location::RequiresRegister())); | 941 Location::RequiresRegister())); |
| 904 locs->set_out(0, Location::RequiresRegister()); | 942 locs->set_out(0, Location::RequiresRegister()); |
| 905 return locs; | 943 return locs; |
| 906 } | 944 } |
| 907 if (operation_cid() == kDoubleCid) { | 945 if (operation_cid() == kDoubleCid) { |
| 908 LocationSummary* summary = new(zone) LocationSummary( | 946 LocationSummary* summary = new (zone) |
| 909 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 947 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 910 summary->set_in(0, Location::RequiresFpuRegister()); | 948 summary->set_in(0, Location::RequiresFpuRegister()); |
| 911 summary->set_in(1, Location::RequiresFpuRegister()); | 949 summary->set_in(1, Location::RequiresFpuRegister()); |
| 912 summary->set_out(0, Location::RequiresRegister()); | 950 summary->set_out(0, Location::RequiresRegister()); |
| 913 return summary; | 951 return summary; |
| 914 } | 952 } |
| 915 ASSERT(operation_cid() == kSmiCid); | 953 ASSERT(operation_cid() == kSmiCid); |
| 916 LocationSummary* summary = new(zone) LocationSummary( | 954 LocationSummary* summary = new (zone) |
| 917 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 955 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 918 summary->set_in(0, Location::RegisterOrConstant(left())); | 956 summary->set_in(0, Location::RegisterOrConstant(left())); |
| 919 // Only one input can be a constant operand. The case of two constant | 957 // Only one input can be a constant operand. The case of two constant |
| 920 // operands should be handled by constant propagation. | 958 // operands should be handled by constant propagation. |
| 921 summary->set_in(1, summary->in(0).IsConstant() | 959 summary->set_in(1, summary->in(0).IsConstant() |
| 922 ? Location::RequiresRegister() | 960 ? Location::RequiresRegister() |
| 923 : Location::RegisterOrConstant(right())); | 961 : Location::RegisterOrConstant(right())); |
| 924 summary->set_out(0, Location::RequiresRegister()); | 962 summary->set_out(0, Location::RequiresRegister()); |
| 925 return summary; | 963 return summary; |
| 926 } | 964 } |
| 927 | 965 |
| 928 | 966 |
| 929 Condition RelationalOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler, | 967 Condition RelationalOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
| 930 BranchLabels labels) { | 968 BranchLabels labels) { |
| 931 if (operation_cid() == kSmiCid) { | 969 if (operation_cid() == kSmiCid) { |
| 932 return EmitSmiComparisonOp(compiler, *locs(), kind()); | 970 return EmitSmiComparisonOp(compiler, *locs(), kind()); |
| 933 } else if (operation_cid() == kMintCid) { | 971 } else if (operation_cid() == kMintCid) { |
| 934 return EmitUnboxedMintComparisonOp(compiler, *locs(), kind(), labels); | 972 return EmitUnboxedMintComparisonOp(compiler, *locs(), kind(), labels); |
| 935 } else { | 973 } else { |
| 936 ASSERT(operation_cid() == kDoubleCid); | 974 ASSERT(operation_cid() == kDoubleCid); |
| 937 return EmitDoubleComparisonOp(compiler, *locs(), kind(), labels); | 975 return EmitDoubleComparisonOp(compiler, *locs(), kind(), labels); |
| 938 } | 976 } |
| 939 } | 977 } |
| 940 | 978 |
| 941 | 979 |
| 942 void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 980 void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 943 __ Comment("RelationalOpInstr"); | 981 __ Comment("RelationalOpInstr"); |
| 944 | 982 |
| 945 Label is_true, is_false; | 983 Label is_true, is_false; |
| 946 BranchLabels labels = { &is_true, &is_false, &is_false }; | 984 BranchLabels labels = {&is_true, &is_false, &is_false}; |
| 947 Condition true_condition = EmitComparisonCode(compiler, labels); | 985 Condition true_condition = EmitComparisonCode(compiler, labels); |
| 948 EmitBranchOnCondition(compiler, true_condition, labels); | 986 EmitBranchOnCondition(compiler, true_condition, labels); |
| 949 | 987 |
| 950 Register result = locs()->out(0).reg(); | 988 Register result = locs()->out(0).reg(); |
| 951 Label done; | 989 Label done; |
| 952 __ Bind(&is_false); | 990 __ Bind(&is_false); |
| 953 __ LoadObject(result, Bool::False()); | 991 __ LoadObject(result, Bool::False()); |
| 954 __ b(&done); | 992 __ b(&done); |
| 955 __ Bind(&is_true); | 993 __ Bind(&is_true); |
| 956 __ LoadObject(result, Bool::True()); | 994 __ LoadObject(result, Bool::True()); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 976 | 1014 |
| 977 void NativeCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1015 void NativeCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 978 SetupNative(); | 1016 SetupNative(); |
| 979 __ Comment("NativeCallInstr"); | 1017 __ Comment("NativeCallInstr"); |
| 980 Register result = locs()->out(0).reg(); | 1018 Register result = locs()->out(0).reg(); |
| 981 | 1019 |
| 982 // Push the result place holder initialized to NULL. | 1020 // Push the result place holder initialized to NULL. |
| 983 __ PushObject(Object::null_object()); | 1021 __ PushObject(Object::null_object()); |
| 984 // Pass a pointer to the first argument in A2. | 1022 // Pass a pointer to the first argument in A2. |
| 985 if (!function().HasOptionalParameters()) { | 1023 if (!function().HasOptionalParameters()) { |
| 986 __ AddImmediate(A2, FP, (kParamEndSlotFromFp + | 1024 __ AddImmediate( |
| 987 function().NumParameters()) * kWordSize); | 1025 A2, FP, (kParamEndSlotFromFp + function().NumParameters()) * kWordSize); |
| 988 } else { | 1026 } else { |
| 989 __ AddImmediate(A2, FP, kFirstLocalSlotFromFp * kWordSize); | 1027 __ AddImmediate(A2, FP, kFirstLocalSlotFromFp * kWordSize); |
| 990 } | 1028 } |
| 991 // Compute the effective address. When running under the simulator, | 1029 // Compute the effective address. When running under the simulator, |
| 992 // this is a redirection address that forces the simulator to call | 1030 // this is a redirection address that forces the simulator to call |
| 993 // into the runtime system. | 1031 // into the runtime system. |
| 994 uword entry; | 1032 uword entry; |
| 995 const intptr_t argc_tag = NativeArguments::ComputeArgcTag(function()); | 1033 const intptr_t argc_tag = NativeArguments::ComputeArgcTag(function()); |
| 996 const StubEntry* stub_entry; | 1034 const StubEntry* stub_entry; |
| 997 if (link_lazily()) { | 1035 if (link_lazily()) { |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1008 } else { | 1046 } else { |
| 1009 // In the case of non bootstrap native methods the CallNativeCFunction | 1047 // In the case of non bootstrap native methods the CallNativeCFunction |
| 1010 // stub generates the redirection address when running under the simulator | 1048 // stub generates the redirection address when running under the simulator |
| 1011 // and hence we do not change 'entry' here. | 1049 // and hence we do not change 'entry' here. |
| 1012 stub_entry = StubCode::CallNativeCFunction_entry(); | 1050 stub_entry = StubCode::CallNativeCFunction_entry(); |
| 1013 } | 1051 } |
| 1014 } | 1052 } |
| 1015 __ LoadImmediate(A1, argc_tag); | 1053 __ LoadImmediate(A1, argc_tag); |
| 1016 ExternalLabel label(entry); | 1054 ExternalLabel label(entry); |
| 1017 __ LoadNativeEntry(T5, &label, kNotPatchable); | 1055 __ LoadNativeEntry(T5, &label, kNotPatchable); |
| 1018 compiler->GenerateCall(token_pos(), | 1056 compiler->GenerateCall(token_pos(), *stub_entry, RawPcDescriptors::kOther, |
| 1019 *stub_entry, | |
| 1020 RawPcDescriptors::kOther, | |
| 1021 locs()); | 1057 locs()); |
| 1022 __ Pop(result); | 1058 __ Pop(result); |
| 1023 } | 1059 } |
| 1024 | 1060 |
| 1025 | 1061 |
| 1026 LocationSummary* OneByteStringFromCharCodeInstr::MakeLocationSummary( | 1062 LocationSummary* OneByteStringFromCharCodeInstr::MakeLocationSummary( |
| 1027 Zone* zone, bool opt) const { | 1063 Zone* zone, |
| 1064 bool opt) const { |
| 1028 const intptr_t kNumInputs = 1; | 1065 const intptr_t kNumInputs = 1; |
| 1029 // TODO(fschneider): Allow immediate operands for the char code. | 1066 // TODO(fschneider): Allow immediate operands for the char code. |
| 1030 return LocationSummary::Make(zone, | 1067 return LocationSummary::Make(zone, kNumInputs, Location::RequiresRegister(), |
| 1031 kNumInputs, | |
| 1032 Location::RequiresRegister(), | |
| 1033 LocationSummary::kNoCall); | 1068 LocationSummary::kNoCall); |
| 1034 } | 1069 } |
| 1035 | 1070 |
| 1036 | 1071 |
| 1037 void OneByteStringFromCharCodeInstr::EmitNativeCode( | 1072 void OneByteStringFromCharCodeInstr::EmitNativeCode( |
| 1038 FlowGraphCompiler* compiler) { | 1073 FlowGraphCompiler* compiler) { |
| 1039 ASSERT(compiler->is_optimizing()); | 1074 ASSERT(compiler->is_optimizing()); |
| 1040 Register char_code = locs()->in(0).reg(); | 1075 Register char_code = locs()->in(0).reg(); |
| 1041 Register result = locs()->out(0).reg(); | 1076 Register result = locs()->out(0).reg(); |
| 1042 | 1077 |
| 1043 __ lw(result, Address(THR, Thread::predefined_symbols_address_offset())); | 1078 __ lw(result, Address(THR, Thread::predefined_symbols_address_offset())); |
| 1044 __ AddImmediate(result, Symbols::kNullCharCodeSymbolOffset * kWordSize); | 1079 __ AddImmediate(result, Symbols::kNullCharCodeSymbolOffset * kWordSize); |
| 1045 __ sll(TMP, char_code, 1); // Char code is a smi. | 1080 __ sll(TMP, char_code, 1); // Char code is a smi. |
| 1046 __ addu(TMP, TMP, result); | 1081 __ addu(TMP, TMP, result); |
| 1047 __ lw(result, Address(TMP)); | 1082 __ lw(result, Address(TMP)); |
| 1048 } | 1083 } |
| 1049 | 1084 |
| 1050 | 1085 |
| 1051 LocationSummary* StringToCharCodeInstr::MakeLocationSummary(Zone* zone, | 1086 LocationSummary* StringToCharCodeInstr::MakeLocationSummary(Zone* zone, |
| 1052 bool opt) const { | 1087 bool opt) const { |
| 1053 const intptr_t kNumInputs = 1; | 1088 const intptr_t kNumInputs = 1; |
| 1054 return LocationSummary::Make(zone, | 1089 return LocationSummary::Make(zone, kNumInputs, Location::RequiresRegister(), |
| 1055 kNumInputs, | |
| 1056 Location::RequiresRegister(), | |
| 1057 LocationSummary::kNoCall); | 1090 LocationSummary::kNoCall); |
| 1058 } | 1091 } |
| 1059 | 1092 |
| 1060 | 1093 |
| 1061 void StringToCharCodeInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1094 void StringToCharCodeInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1062 __ Comment("StringToCharCodeInstr"); | 1095 __ Comment("StringToCharCodeInstr"); |
| 1063 | 1096 |
| 1064 ASSERT(cid_ == kOneByteStringCid); | 1097 ASSERT(cid_ == kOneByteStringCid); |
| 1065 Register str = locs()->in(0).reg(); | 1098 Register str = locs()->in(0).reg(); |
| 1066 Register result = locs()->out(0).reg(); | 1099 Register result = locs()->out(0).reg(); |
| 1067 ASSERT(str != result); | 1100 ASSERT(str != result); |
| 1068 Label done; | 1101 Label done; |
| 1069 __ lw(result, FieldAddress(str, String::length_offset())); | 1102 __ lw(result, FieldAddress(str, String::length_offset())); |
| 1070 __ BranchNotEqual(result, Immediate(Smi::RawValue(1)), &done); | 1103 __ BranchNotEqual(result, Immediate(Smi::RawValue(1)), &done); |
| 1071 __ delay_slot()->addiu(result, ZR, Immediate(Smi::RawValue(-1))); | 1104 __ delay_slot()->addiu(result, ZR, Immediate(Smi::RawValue(-1))); |
| 1072 __ lbu(result, FieldAddress(str, OneByteString::data_offset())); | 1105 __ lbu(result, FieldAddress(str, OneByteString::data_offset())); |
| 1073 __ SmiTag(result); | 1106 __ SmiTag(result); |
| 1074 __ Bind(&done); | 1107 __ Bind(&done); |
| 1075 } | 1108 } |
| 1076 | 1109 |
| 1077 | 1110 |
| 1078 LocationSummary* StringInterpolateInstr::MakeLocationSummary(Zone* zone, | 1111 LocationSummary* StringInterpolateInstr::MakeLocationSummary(Zone* zone, |
| 1079 bool opt) const { | 1112 bool opt) const { |
| 1080 const intptr_t kNumInputs = 1; | 1113 const intptr_t kNumInputs = 1; |
| 1081 const intptr_t kNumTemps = 0; | 1114 const intptr_t kNumTemps = 0; |
| 1082 LocationSummary* summary = new(zone) LocationSummary( | 1115 LocationSummary* summary = new (zone) |
| 1083 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 1116 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
| 1084 summary->set_in(0, Location::RegisterLocation(A0)); | 1117 summary->set_in(0, Location::RegisterLocation(A0)); |
| 1085 summary->set_out(0, Location::RegisterLocation(V0)); | 1118 summary->set_out(0, Location::RegisterLocation(V0)); |
| 1086 return summary; | 1119 return summary; |
| 1087 } | 1120 } |
| 1088 | 1121 |
| 1089 | 1122 |
| 1090 void StringInterpolateInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1123 void StringInterpolateInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1091 Register array = locs()->in(0).reg(); | 1124 Register array = locs()->in(0).reg(); |
| 1092 __ Push(array); | 1125 __ Push(array); |
| 1093 const int kNumberOfArguments = 1; | 1126 const int kNumberOfArguments = 1; |
| 1094 const Array& kNoArgumentNames = Object::null_array(); | 1127 const Array& kNoArgumentNames = Object::null_array(); |
| 1095 compiler->GenerateStaticCall(deopt_id(), | 1128 compiler->GenerateStaticCall(deopt_id(), token_pos(), CallFunction(), |
| 1096 token_pos(), | 1129 kNumberOfArguments, kNoArgumentNames, locs(), |
| 1097 CallFunction(), | |
| 1098 kNumberOfArguments, | |
| 1099 kNoArgumentNames, | |
| 1100 locs(), | |
| 1101 ICData::Handle()); | 1130 ICData::Handle()); |
| 1102 ASSERT(locs()->out(0).reg() == V0); | 1131 ASSERT(locs()->out(0).reg() == V0); |
| 1103 } | 1132 } |
| 1104 | 1133 |
| 1105 | 1134 |
| 1106 LocationSummary* LoadUntaggedInstr::MakeLocationSummary(Zone* zone, | 1135 LocationSummary* LoadUntaggedInstr::MakeLocationSummary(Zone* zone, |
| 1107 bool opt) const { | 1136 bool opt) const { |
| 1108 const intptr_t kNumInputs = 1; | 1137 const intptr_t kNumInputs = 1; |
| 1109 return LocationSummary::Make(zone, | 1138 return LocationSummary::Make(zone, kNumInputs, Location::RequiresRegister(), |
| 1110 kNumInputs, | |
| 1111 Location::RequiresRegister(), | |
| 1112 LocationSummary::kNoCall); | 1139 LocationSummary::kNoCall); |
| 1113 } | 1140 } |
| 1114 | 1141 |
| 1115 | 1142 |
| 1116 void LoadUntaggedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1143 void LoadUntaggedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1117 Register obj = locs()->in(0).reg(); | 1144 Register obj = locs()->in(0).reg(); |
| 1118 Register result = locs()->out(0).reg(); | 1145 Register result = locs()->out(0).reg(); |
| 1119 if (object()->definition()->representation() == kUntagged) { | 1146 if (object()->definition()->representation() == kUntagged) { |
| 1120 __ LoadFromOffset(result, obj, offset()); | 1147 __ LoadFromOffset(result, obj, offset()); |
| 1121 } else { | 1148 } else { |
| 1122 ASSERT(object()->definition()->representation() == kTagged); | 1149 ASSERT(object()->definition()->representation() == kTagged); |
| 1123 __ LoadFieldFromOffset(result, obj, offset()); | 1150 __ LoadFieldFromOffset(result, obj, offset()); |
| 1124 } | 1151 } |
| 1125 } | 1152 } |
| 1126 | 1153 |
| 1127 | 1154 |
| 1128 LocationSummary* LoadClassIdInstr::MakeLocationSummary(Zone* zone, | 1155 LocationSummary* LoadClassIdInstr::MakeLocationSummary(Zone* zone, |
| 1129 bool opt) const { | 1156 bool opt) const { |
| 1130 const intptr_t kNumInputs = 1; | 1157 const intptr_t kNumInputs = 1; |
| 1131 return LocationSummary::Make(zone, | 1158 return LocationSummary::Make(zone, kNumInputs, Location::RequiresRegister(), |
| 1132 kNumInputs, | |
| 1133 Location::RequiresRegister(), | |
| 1134 LocationSummary::kNoCall); | 1159 LocationSummary::kNoCall); |
| 1135 } | 1160 } |
| 1136 | 1161 |
| 1137 | 1162 |
| 1138 void LoadClassIdInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1163 void LoadClassIdInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1139 Register object = locs()->in(0).reg(); | 1164 Register object = locs()->in(0).reg(); |
| 1140 Register result = locs()->out(0).reg(); | 1165 Register result = locs()->out(0).reg(); |
| 1141 const AbstractType& value_type = *this->object()->Type()->ToAbstractType(); | 1166 const AbstractType& value_type = *this->object()->Type()->ToAbstractType(); |
| 1142 if (CompileType::Smi().IsAssignableTo(value_type) || | 1167 if (CompileType::Smi().IsAssignableTo(value_type) || |
| 1143 value_type.IsTypeParameter()) { | 1168 value_type.IsTypeParameter()) { |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1221 } | 1246 } |
| 1222 | 1247 |
| 1223 | 1248 |
| 1224 static bool CanBeImmediateIndex(Value* value, intptr_t cid, bool is_external) { | 1249 static bool CanBeImmediateIndex(Value* value, intptr_t cid, bool is_external) { |
| 1225 ConstantInstr* constant = value->definition()->AsConstant(); | 1250 ConstantInstr* constant = value->definition()->AsConstant(); |
| 1226 if ((constant == NULL) || !Assembler::IsSafeSmi(constant->value())) { | 1251 if ((constant == NULL) || !Assembler::IsSafeSmi(constant->value())) { |
| 1227 return false; | 1252 return false; |
| 1228 } | 1253 } |
| 1229 const int64_t index = Smi::Cast(constant->value()).AsInt64Value(); | 1254 const int64_t index = Smi::Cast(constant->value()).AsInt64Value(); |
| 1230 const intptr_t scale = Instance::ElementSizeFor(cid); | 1255 const intptr_t scale = Instance::ElementSizeFor(cid); |
| 1231 const int64_t offset = index * scale + | 1256 const int64_t offset = |
| 1257 index * scale + |
| 1232 (is_external ? 0 : (Instance::DataOffsetFor(cid) - kHeapObjectTag)); | 1258 (is_external ? 0 : (Instance::DataOffsetFor(cid) - kHeapObjectTag)); |
| 1233 if (!Utils::IsInt(32, offset)) { | 1259 if (!Utils::IsInt(32, offset)) { |
| 1234 return false; | 1260 return false; |
| 1235 } | 1261 } |
| 1236 return Address::CanHoldOffset(static_cast<int32_t>(offset)); | 1262 return Address::CanHoldOffset(static_cast<int32_t>(offset)); |
| 1237 } | 1263 } |
| 1238 | 1264 |
| 1239 | 1265 |
| 1240 LocationSummary* LoadIndexedInstr::MakeLocationSummary(Zone* zone, | 1266 LocationSummary* LoadIndexedInstr::MakeLocationSummary(Zone* zone, |
| 1241 bool opt) const { | 1267 bool opt) const { |
| 1242 const intptr_t kNumInputs = 2; | 1268 const intptr_t kNumInputs = 2; |
| 1243 const intptr_t kNumTemps = aligned() ? 0 : 1; | 1269 const intptr_t kNumTemps = aligned() ? 0 : 1; |
| 1244 LocationSummary* locs = new(zone) LocationSummary( | 1270 LocationSummary* locs = new (zone) |
| 1245 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1271 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 1246 locs->set_in(0, Location::RequiresRegister()); | 1272 locs->set_in(0, Location::RequiresRegister()); |
| 1247 if (CanBeImmediateIndex(index(), class_id(), IsExternal())) { | 1273 if (CanBeImmediateIndex(index(), class_id(), IsExternal())) { |
| 1248 locs->set_in(1, Location::Constant(index()->definition()->AsConstant())); | 1274 locs->set_in(1, Location::Constant(index()->definition()->AsConstant())); |
| 1249 } else { | 1275 } else { |
| 1250 locs->set_in(1, Location::RequiresRegister()); | 1276 locs->set_in(1, Location::RequiresRegister()); |
| 1251 } | 1277 } |
| 1252 if ((representation() == kUnboxedDouble) || | 1278 if ((representation() == kUnboxedDouble) || |
| 1253 (representation() == kUnboxedFloat32x4) || | 1279 (representation() == kUnboxedFloat32x4) || |
| 1254 (representation() == kUnboxedInt32x4)) { | 1280 (representation() == kUnboxedInt32x4)) { |
| 1255 locs->set_out(0, Location::RequiresFpuRegister()); | 1281 locs->set_out(0, Location::RequiresFpuRegister()); |
| 1256 } else { | 1282 } else { |
| 1257 locs->set_out(0, Location::RequiresRegister()); | 1283 locs->set_out(0, Location::RequiresRegister()); |
| 1258 } | 1284 } |
| 1259 if (!aligned()) { | 1285 if (!aligned()) { |
| 1260 locs->set_temp(0, Location::RequiresRegister()); | 1286 locs->set_temp(0, Location::RequiresRegister()); |
| 1261 } | 1287 } |
| 1262 return locs; | 1288 return locs; |
| 1263 } | 1289 } |
| 1264 | 1290 |
| 1265 | 1291 |
| 1266 void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1292 void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1267 __ Comment("LoadIndexedInstr"); | 1293 __ Comment("LoadIndexedInstr"); |
| 1268 // The array register points to the backing store for external arrays. | 1294 // The array register points to the backing store for external arrays. |
| 1269 const Register array = locs()->in(0).reg(); | 1295 const Register array = locs()->in(0).reg(); |
| 1270 const Location index = locs()->in(1); | 1296 const Location index = locs()->in(1); |
| 1271 const Register address = aligned() ? kNoRegister : locs()->temp(0).reg(); | 1297 const Register address = aligned() ? kNoRegister : locs()->temp(0).reg(); |
| 1272 | 1298 |
| 1273 Address element_address(kNoRegister); | 1299 Address element_address(kNoRegister); |
| 1274 if (aligned()) { | 1300 if (aligned()) { |
| 1275 element_address = index.IsRegister() | 1301 element_address = |
| 1276 ? __ ElementAddressForRegIndex(true, // Load. | 1302 index.IsRegister() |
| 1277 IsExternal(), class_id(), index_scale(), | 1303 ? __ ElementAddressForRegIndex(true, // Load. |
| 1278 array, index.reg()) | 1304 IsExternal(), class_id(), |
| 1279 : __ ElementAddressForIntIndex( | 1305 index_scale(), array, index.reg()) |
| 1280 IsExternal(), class_id(), index_scale(), | 1306 : __ ElementAddressForIntIndex(IsExternal(), class_id(), |
| 1281 array, Smi::Cast(index.constant()).Value()); | 1307 index_scale(), array, |
| 1308 Smi::Cast(index.constant()).Value()); |
| 1282 // Warning: element_address may use register TMP as base. | 1309 // Warning: element_address may use register TMP as base. |
| 1283 } else { | 1310 } else { |
| 1284 if (index.IsRegister()) { | 1311 if (index.IsRegister()) { |
| 1285 __ LoadElementAddressForRegIndex(address, | 1312 __ LoadElementAddressForRegIndex(address, |
| 1286 true, // Load. | 1313 true, // Load. |
| 1287 IsExternal(), class_id(), index_scale(), | 1314 IsExternal(), class_id(), index_scale(), |
| 1288 array, index.reg()); | 1315 array, index.reg()); |
| 1289 } else { | 1316 } else { |
| 1290 __ LoadElementAddressForIntIndex(address, | 1317 __ LoadElementAddressForIntIndex(address, IsExternal(), class_id(), |
| 1291 IsExternal(), class_id(), index_scale(), | 1318 index_scale(), array, |
| 1292 array, | |
| 1293 Smi::Cast(index.constant()).Value()); | 1319 Smi::Cast(index.constant()).Value()); |
| 1294 } | 1320 } |
| 1295 } | 1321 } |
| 1296 | 1322 |
| 1297 if ((representation() == kUnboxedDouble) || | 1323 if ((representation() == kUnboxedDouble) || |
| 1298 (representation() == kUnboxedFloat32x4) || | 1324 (representation() == kUnboxedFloat32x4) || |
| 1299 (representation() == kUnboxedInt32x4)) { | 1325 (representation() == kUnboxedInt32x4)) { |
| 1300 DRegister result = locs()->out(0).fpu_reg(); | 1326 DRegister result = locs()->out(0).fpu_reg(); |
| 1301 switch (class_id()) { | 1327 switch (class_id()) { |
| 1302 case kTypedDataFloat32ArrayCid: | 1328 case kTypedDataFloat32ArrayCid: |
| 1303 // Load single precision float. | 1329 // Load single precision float. |
| 1304 __ lwc1(EvenFRegisterOf(result), element_address); | 1330 __ lwc1(EvenFRegisterOf(result), element_address); |
| 1305 break; | 1331 break; |
| 1306 case kTypedDataFloat64ArrayCid: | 1332 case kTypedDataFloat64ArrayCid: |
| 1307 __ LoadDFromOffset(result, | 1333 __ LoadDFromOffset(result, element_address.base(), |
| 1308 element_address.base(), element_address.offset()); | 1334 element_address.offset()); |
| 1309 break; | 1335 break; |
| 1310 case kTypedDataInt32x4ArrayCid: | 1336 case kTypedDataInt32x4ArrayCid: |
| 1311 case kTypedDataFloat32x4ArrayCid: | 1337 case kTypedDataFloat32x4ArrayCid: |
| 1312 UNIMPLEMENTED(); | 1338 UNIMPLEMENTED(); |
| 1313 break; | 1339 break; |
| 1314 } | 1340 } |
| 1315 return; | 1341 return; |
| 1316 } | 1342 } |
| 1317 | 1343 |
| 1318 if ((representation() == kUnboxedUint32) || | 1344 if ((representation() == kUnboxedUint32) || |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1384 __ lw(result, element_address); | 1410 __ lw(result, element_address); |
| 1385 break; | 1411 break; |
| 1386 } | 1412 } |
| 1387 } | 1413 } |
| 1388 | 1414 |
| 1389 | 1415 |
| 1390 LocationSummary* LoadCodeUnitsInstr::MakeLocationSummary(Zone* zone, | 1416 LocationSummary* LoadCodeUnitsInstr::MakeLocationSummary(Zone* zone, |
| 1391 bool opt) const { | 1417 bool opt) const { |
| 1392 const intptr_t kNumInputs = 2; | 1418 const intptr_t kNumInputs = 2; |
| 1393 const intptr_t kNumTemps = 0; | 1419 const intptr_t kNumTemps = 0; |
| 1394 LocationSummary* summary = new(zone) LocationSummary( | 1420 LocationSummary* summary = new (zone) |
| 1395 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1421 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 1396 summary->set_in(0, Location::RequiresRegister()); | 1422 summary->set_in(0, Location::RequiresRegister()); |
| 1397 summary->set_in(1, Location::RequiresRegister()); | 1423 summary->set_in(1, Location::RequiresRegister()); |
| 1398 | 1424 |
| 1399 // TODO(zerny): Handle mints properly once possible. | 1425 // TODO(zerny): Handle mints properly once possible. |
| 1400 ASSERT(representation() == kTagged); | 1426 ASSERT(representation() == kTagged); |
| 1401 summary->set_out(0, Location::RequiresRegister()); | 1427 summary->set_out(0, Location::RequiresRegister()); |
| 1402 | 1428 |
| 1403 return summary; | 1429 return summary; |
| 1404 } | 1430 } |
| 1405 | 1431 |
| 1406 | 1432 |
| 1407 void LoadCodeUnitsInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1433 void LoadCodeUnitsInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1408 // The string register points to the backing store for external strings. | 1434 // The string register points to the backing store for external strings. |
| 1409 const Register str = locs()->in(0).reg(); | 1435 const Register str = locs()->in(0).reg(); |
| 1410 const Location index = locs()->in(1); | 1436 const Location index = locs()->in(1); |
| 1411 | 1437 |
| 1412 Address element_address = __ ElementAddressForRegIndex( | 1438 Address element_address = __ ElementAddressForRegIndex( |
| 1413 true, IsExternal(), class_id(), index_scale(), str, index.reg()); | 1439 true, IsExternal(), class_id(), index_scale(), str, index.reg()); |
| 1414 // Warning: element_address may use register TMP as base. | 1440 // Warning: element_address may use register TMP as base. |
| 1415 | 1441 |
| 1416 ASSERT(representation() == kTagged); | 1442 ASSERT(representation() == kTagged); |
| 1417 Register result = locs()->out(0).reg(); | 1443 Register result = locs()->out(0).reg(); |
| 1418 switch (class_id()) { | 1444 switch (class_id()) { |
| 1419 case kOneByteStringCid: | 1445 case kOneByteStringCid: |
| 1420 case kExternalOneByteStringCid: | 1446 case kExternalOneByteStringCid: |
| 1421 switch (element_count()) { | 1447 switch (element_count()) { |
| 1422 case 1: __ lbu(result, element_address); break; | 1448 case 1: |
| 1423 case 2: __ lhu(result, element_address); break; | 1449 __ lbu(result, element_address); |
| 1450 break; |
| 1451 case 2: |
| 1452 __ lhu(result, element_address); |
| 1453 break; |
| 1424 case 4: // Loading multiple code units is disabled on MIPS. | 1454 case 4: // Loading multiple code units is disabled on MIPS. |
| 1425 default: UNREACHABLE(); | 1455 default: |
| 1456 UNREACHABLE(); |
| 1426 } | 1457 } |
| 1427 __ SmiTag(result); | 1458 __ SmiTag(result); |
| 1428 break; | 1459 break; |
| 1429 case kTwoByteStringCid: | 1460 case kTwoByteStringCid: |
| 1430 case kExternalTwoByteStringCid: | 1461 case kExternalTwoByteStringCid: |
| 1431 switch (element_count()) { | 1462 switch (element_count()) { |
| 1432 case 1: __ lhu(result, element_address); break; | 1463 case 1: |
| 1464 __ lhu(result, element_address); |
| 1465 break; |
| 1433 case 2: // Loading multiple code units is disabled on MIPS. | 1466 case 2: // Loading multiple code units is disabled on MIPS. |
| 1434 default: UNREACHABLE(); | 1467 default: |
| 1468 UNREACHABLE(); |
| 1435 } | 1469 } |
| 1436 __ SmiTag(result); | 1470 __ SmiTag(result); |
| 1437 break; | 1471 break; |
| 1438 default: | 1472 default: |
| 1439 UNREACHABLE(); | 1473 UNREACHABLE(); |
| 1440 break; | 1474 break; |
| 1441 } | 1475 } |
| 1442 } | 1476 } |
| 1443 | 1477 |
| 1444 | 1478 |
| 1445 Representation StoreIndexedInstr::RequiredInputRepresentation( | 1479 Representation StoreIndexedInstr::RequiredInputRepresentation( |
| 1446 intptr_t idx) const { | 1480 intptr_t idx) const { |
| 1447 // Array can be a Dart object or a pointer to external data. | 1481 // Array can be a Dart object or a pointer to external data. |
| 1448 if (idx == 0) return kNoRepresentation; // Flexible input representation. | 1482 if (idx == 0) return kNoRepresentation; // Flexible input representation. |
| 1449 if (idx == 1) return kTagged; // Index is a smi. | 1483 if (idx == 1) return kTagged; // Index is a smi. |
| 1450 ASSERT(idx == 2); | 1484 ASSERT(idx == 2); |
| 1451 switch (class_id_) { | 1485 switch (class_id_) { |
| 1452 case kArrayCid: | 1486 case kArrayCid: |
| 1453 case kOneByteStringCid: | 1487 case kOneByteStringCid: |
| 1454 case kTypedDataInt8ArrayCid: | 1488 case kTypedDataInt8ArrayCid: |
| 1455 case kTypedDataUint8ArrayCid: | 1489 case kTypedDataUint8ArrayCid: |
| 1456 case kExternalTypedDataUint8ArrayCid: | 1490 case kExternalTypedDataUint8ArrayCid: |
| 1457 case kTypedDataUint8ClampedArrayCid: | 1491 case kTypedDataUint8ClampedArrayCid: |
| 1458 case kExternalTypedDataUint8ClampedArrayCid: | 1492 case kExternalTypedDataUint8ClampedArrayCid: |
| 1459 case kTypedDataInt16ArrayCid: | 1493 case kTypedDataInt16ArrayCid: |
| (...skipping 14 matching lines...) Expand all Loading... |
| 1474 UNIMPLEMENTED(); | 1508 UNIMPLEMENTED(); |
| 1475 return kTagged; | 1509 return kTagged; |
| 1476 } | 1510 } |
| 1477 } | 1511 } |
| 1478 | 1512 |
| 1479 | 1513 |
| 1480 LocationSummary* StoreIndexedInstr::MakeLocationSummary(Zone* zone, | 1514 LocationSummary* StoreIndexedInstr::MakeLocationSummary(Zone* zone, |
| 1481 bool opt) const { | 1515 bool opt) const { |
| 1482 const intptr_t kNumInputs = 3; | 1516 const intptr_t kNumInputs = 3; |
| 1483 const intptr_t kNumTemps = aligned() ? 0 : 2; | 1517 const intptr_t kNumTemps = aligned() ? 0 : 2; |
| 1484 LocationSummary* locs = new(zone) LocationSummary( | 1518 LocationSummary* locs = new (zone) |
| 1485 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1519 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 1486 locs->set_in(0, Location::RequiresRegister()); | 1520 locs->set_in(0, Location::RequiresRegister()); |
| 1487 if (CanBeImmediateIndex(index(), class_id(), IsExternal())) { | 1521 if (CanBeImmediateIndex(index(), class_id(), IsExternal())) { |
| 1488 locs->set_in(1, Location::Constant(index()->definition()->AsConstant())); | 1522 locs->set_in(1, Location::Constant(index()->definition()->AsConstant())); |
| 1489 } else { | 1523 } else { |
| 1490 locs->set_in(1, Location::WritableRegister()); | 1524 locs->set_in(1, Location::WritableRegister()); |
| 1491 } | 1525 } |
| 1492 switch (class_id()) { | 1526 switch (class_id()) { |
| 1493 case kArrayCid: | 1527 case kArrayCid: |
| 1494 locs->set_in(2, ShouldEmitStoreBarrier() | 1528 locs->set_in(2, ShouldEmitStoreBarrier() |
| 1495 ? Location::WritableRegister() | 1529 ? Location::WritableRegister() |
| 1496 : Location::RegisterOrConstant(value())); | 1530 : Location::RegisterOrConstant(value())); |
| 1497 break; | 1531 break; |
| 1498 case kExternalTypedDataUint8ArrayCid: | 1532 case kExternalTypedDataUint8ArrayCid: |
| 1499 case kExternalTypedDataUint8ClampedArrayCid: | 1533 case kExternalTypedDataUint8ClampedArrayCid: |
| 1500 case kTypedDataInt8ArrayCid: | 1534 case kTypedDataInt8ArrayCid: |
| 1501 case kTypedDataUint8ArrayCid: | 1535 case kTypedDataUint8ArrayCid: |
| 1502 case kTypedDataUint8ClampedArrayCid: | 1536 case kTypedDataUint8ClampedArrayCid: |
| 1503 case kOneByteStringCid: | 1537 case kOneByteStringCid: |
| 1504 case kTypedDataInt16ArrayCid: | 1538 case kTypedDataInt16ArrayCid: |
| 1505 case kTypedDataUint16ArrayCid: | 1539 case kTypedDataUint16ArrayCid: |
| 1506 case kTypedDataInt32ArrayCid: | 1540 case kTypedDataInt32ArrayCid: |
| (...skipping 21 matching lines...) Expand all Loading... |
| 1528 void StoreIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1562 void StoreIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1529 __ Comment("StoreIndexedInstr"); | 1563 __ Comment("StoreIndexedInstr"); |
| 1530 // The array register points to the backing store for external arrays. | 1564 // The array register points to the backing store for external arrays. |
| 1531 const Register array = locs()->in(0).reg(); | 1565 const Register array = locs()->in(0).reg(); |
| 1532 const Location index = locs()->in(1); | 1566 const Location index = locs()->in(1); |
| 1533 const Register address = aligned() ? kNoRegister : locs()->temp(0).reg(); | 1567 const Register address = aligned() ? kNoRegister : locs()->temp(0).reg(); |
| 1534 const Register scratch = aligned() ? kNoRegister : locs()->temp(1).reg(); | 1568 const Register scratch = aligned() ? kNoRegister : locs()->temp(1).reg(); |
| 1535 | 1569 |
| 1536 Address element_address(kNoRegister); | 1570 Address element_address(kNoRegister); |
| 1537 if (aligned()) { | 1571 if (aligned()) { |
| 1538 element_address = index.IsRegister() | 1572 element_address = |
| 1539 ? __ ElementAddressForRegIndex(false, // Store. | 1573 index.IsRegister() |
| 1540 IsExternal(), class_id(), index_scale(), | 1574 ? __ ElementAddressForRegIndex(false, // Store. |
| 1541 array, index.reg()) | 1575 IsExternal(), class_id(), |
| 1542 : __ ElementAddressForIntIndex( | 1576 index_scale(), array, index.reg()) |
| 1543 IsExternal(), class_id(), index_scale(), | 1577 : __ ElementAddressForIntIndex(IsExternal(), class_id(), |
| 1544 array, Smi::Cast(index.constant()).Value()); | 1578 index_scale(), array, |
| 1579 Smi::Cast(index.constant()).Value()); |
| 1545 ASSERT(element_address.base() != TMP); // Allowed for load only. | 1580 ASSERT(element_address.base() != TMP); // Allowed for load only. |
| 1546 } else { | 1581 } else { |
| 1547 if (index.IsRegister()) { | 1582 if (index.IsRegister()) { |
| 1548 __ LoadElementAddressForRegIndex(address, | 1583 __ LoadElementAddressForRegIndex(address, |
| 1549 false, // Store. | 1584 false, // Store. |
| 1550 IsExternal(), class_id(), index_scale(), | 1585 IsExternal(), class_id(), index_scale(), |
| 1551 array, index.reg()); | 1586 array, index.reg()); |
| 1552 } else { | 1587 } else { |
| 1553 __ LoadElementAddressForIntIndex(address, | 1588 __ LoadElementAddressForIntIndex(address, IsExternal(), class_id(), |
| 1554 IsExternal(), class_id(), index_scale(), | 1589 index_scale(), array, |
| 1555 array, | |
| 1556 Smi::Cast(index.constant()).Value()); | 1590 Smi::Cast(index.constant()).Value()); |
| 1557 } | 1591 } |
| 1558 } | 1592 } |
| 1559 | 1593 |
| 1560 switch (class_id()) { | 1594 switch (class_id()) { |
| 1561 case kArrayCid: | 1595 case kArrayCid: |
| 1562 ASSERT(aligned()); | 1596 ASSERT(aligned()); |
| 1563 if (ShouldEmitStoreBarrier()) { | 1597 if (ShouldEmitStoreBarrier()) { |
| 1564 Register value = locs()->in(2).reg(); | 1598 Register value = locs()->in(2).reg(); |
| 1565 __ StoreIntoObject(array, element_address, value); | 1599 __ StoreIntoObject(array, element_address, value); |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1635 break; | 1669 break; |
| 1636 } | 1670 } |
| 1637 case kTypedDataFloat32ArrayCid: { | 1671 case kTypedDataFloat32ArrayCid: { |
| 1638 ASSERT(aligned()); | 1672 ASSERT(aligned()); |
| 1639 FRegister value = EvenFRegisterOf(locs()->in(2).fpu_reg()); | 1673 FRegister value = EvenFRegisterOf(locs()->in(2).fpu_reg()); |
| 1640 __ swc1(value, element_address); | 1674 __ swc1(value, element_address); |
| 1641 break; | 1675 break; |
| 1642 } | 1676 } |
| 1643 case kTypedDataFloat64ArrayCid: | 1677 case kTypedDataFloat64ArrayCid: |
| 1644 ASSERT(aligned()); | 1678 ASSERT(aligned()); |
| 1645 __ StoreDToOffset(locs()->in(2).fpu_reg(), | 1679 __ StoreDToOffset(locs()->in(2).fpu_reg(), element_address.base(), |
| 1646 element_address.base(), element_address.offset()); | 1680 element_address.offset()); |
| 1647 break; | 1681 break; |
| 1648 case kTypedDataInt32x4ArrayCid: | 1682 case kTypedDataInt32x4ArrayCid: |
| 1649 case kTypedDataFloat32x4ArrayCid: | 1683 case kTypedDataFloat32x4ArrayCid: |
| 1650 UNIMPLEMENTED(); | 1684 UNIMPLEMENTED(); |
| 1651 break; | 1685 break; |
| 1652 default: | 1686 default: |
| 1653 UNREACHABLE(); | 1687 UNREACHABLE(); |
| 1654 } | 1688 } |
| 1655 } | 1689 } |
| 1656 | 1690 |
| 1657 | 1691 |
| 1658 LocationSummary* GuardFieldClassInstr::MakeLocationSummary(Zone* zone, | 1692 LocationSummary* GuardFieldClassInstr::MakeLocationSummary(Zone* zone, |
| 1659 bool opt) const { | 1693 bool opt) const { |
| 1660 const intptr_t kNumInputs = 1; | 1694 const intptr_t kNumInputs = 1; |
| 1661 | 1695 |
| 1662 const intptr_t value_cid = value()->Type()->ToCid(); | 1696 const intptr_t value_cid = value()->Type()->ToCid(); |
| 1663 const intptr_t field_cid = field().guarded_cid(); | 1697 const intptr_t field_cid = field().guarded_cid(); |
| 1664 | 1698 |
| 1665 const bool emit_full_guard = !opt || (field_cid == kIllegalCid); | 1699 const bool emit_full_guard = !opt || (field_cid == kIllegalCid); |
| 1666 const bool needs_value_cid_temp_reg = | 1700 const bool needs_value_cid_temp_reg = |
| 1667 (value_cid == kDynamicCid) && (emit_full_guard || (field_cid != kSmiCid)); | 1701 (value_cid == kDynamicCid) && (emit_full_guard || (field_cid != kSmiCid)); |
| 1668 const bool needs_field_temp_reg = emit_full_guard; | 1702 const bool needs_field_temp_reg = emit_full_guard; |
| 1669 | 1703 |
| 1670 intptr_t num_temps = 0; | 1704 intptr_t num_temps = 0; |
| 1671 if (needs_value_cid_temp_reg) { | 1705 if (needs_value_cid_temp_reg) { |
| 1672 num_temps++; | 1706 num_temps++; |
| 1673 } | 1707 } |
| 1674 if (needs_field_temp_reg) { | 1708 if (needs_field_temp_reg) { |
| 1675 num_temps++; | 1709 num_temps++; |
| 1676 } | 1710 } |
| 1677 | 1711 |
| 1678 LocationSummary* summary = new(zone) LocationSummary( | 1712 LocationSummary* summary = new (zone) |
| 1679 zone, kNumInputs, num_temps, LocationSummary::kNoCall); | 1713 LocationSummary(zone, kNumInputs, num_temps, LocationSummary::kNoCall); |
| 1680 summary->set_in(0, Location::RequiresRegister()); | 1714 summary->set_in(0, Location::RequiresRegister()); |
| 1681 | 1715 |
| 1682 for (intptr_t i = 0; i < num_temps; i++) { | 1716 for (intptr_t i = 0; i < num_temps; i++) { |
| 1683 summary->set_temp(i, Location::RequiresRegister()); | 1717 summary->set_temp(i, Location::RequiresRegister()); |
| 1684 } | 1718 } |
| 1685 | 1719 |
| 1686 return summary; | 1720 return summary; |
| 1687 } | 1721 } |
| 1688 | 1722 |
| 1689 | 1723 |
| 1690 void GuardFieldClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1724 void GuardFieldClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1691 ASSERT(sizeof(classid_t) == kInt16Size); | 1725 ASSERT(sizeof(classid_t) == kInt16Size); |
| 1692 __ Comment("GuardFieldClassInstr"); | 1726 __ Comment("GuardFieldClassInstr"); |
| 1693 | 1727 |
| 1694 const intptr_t value_cid = value()->Type()->ToCid(); | 1728 const intptr_t value_cid = value()->Type()->ToCid(); |
| 1695 const intptr_t field_cid = field().guarded_cid(); | 1729 const intptr_t field_cid = field().guarded_cid(); |
| 1696 const intptr_t nullability = field().is_nullable() ? kNullCid : kIllegalCid; | 1730 const intptr_t nullability = field().is_nullable() ? kNullCid : kIllegalCid; |
| 1697 | 1731 |
| 1698 if (field_cid == kDynamicCid) { | 1732 if (field_cid == kDynamicCid) { |
| 1699 if (Compiler::IsBackgroundCompilation()) { | 1733 if (Compiler::IsBackgroundCompilation()) { |
| 1700 // Field state changed while compiling. | 1734 // Field state changed while compiling. |
| 1701 Compiler::AbortBackgroundCompilation(deopt_id(), | 1735 Compiler::AbortBackgroundCompilation( |
| 1736 deopt_id(), |
| 1702 "GuardFieldClassInstr: field state changed while compiling"); | 1737 "GuardFieldClassInstr: field state changed while compiling"); |
| 1703 } | 1738 } |
| 1704 ASSERT(!compiler->is_optimizing()); | 1739 ASSERT(!compiler->is_optimizing()); |
| 1705 return; // Nothing to emit. | 1740 return; // Nothing to emit. |
| 1706 } | 1741 } |
| 1707 | 1742 |
| 1708 const bool emit_full_guard = | 1743 const bool emit_full_guard = |
| 1709 !compiler->is_optimizing() || (field_cid == kIllegalCid); | 1744 !compiler->is_optimizing() || (field_cid == kIllegalCid); |
| 1710 | 1745 |
| 1711 const bool needs_value_cid_temp_reg = | 1746 const bool needs_value_cid_temp_reg = |
| 1712 (value_cid == kDynamicCid) && (emit_full_guard || (field_cid != kSmiCid)); | 1747 (value_cid == kDynamicCid) && (emit_full_guard || (field_cid != kSmiCid)); |
| 1713 | 1748 |
| 1714 const bool needs_field_temp_reg = emit_full_guard; | 1749 const bool needs_field_temp_reg = emit_full_guard; |
| 1715 | 1750 |
| 1716 const Register value_reg = locs()->in(0).reg(); | 1751 const Register value_reg = locs()->in(0).reg(); |
| 1717 | 1752 |
| 1718 const Register value_cid_reg = needs_value_cid_temp_reg ? | 1753 const Register value_cid_reg = |
| 1719 locs()->temp(0).reg() : kNoRegister; | 1754 needs_value_cid_temp_reg ? locs()->temp(0).reg() : kNoRegister; |
| 1720 | 1755 |
| 1721 const Register field_reg = needs_field_temp_reg ? | 1756 const Register field_reg = needs_field_temp_reg |
| 1722 locs()->temp(locs()->temp_count() - 1).reg() : kNoRegister; | 1757 ? locs()->temp(locs()->temp_count() - 1).reg() |
| 1758 : kNoRegister; |
| 1723 | 1759 |
| 1724 Label ok, fail_label; | 1760 Label ok, fail_label; |
| 1725 | 1761 |
| 1726 Label* deopt = compiler->is_optimizing() ? | 1762 Label* deopt = |
| 1727 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptGuardField) : NULL; | 1763 compiler->is_optimizing() |
| 1764 ? compiler->AddDeoptStub(deopt_id(), ICData::kDeoptGuardField) |
| 1765 : NULL; |
| 1728 | 1766 |
| 1729 Label* fail = (deopt != NULL) ? deopt : &fail_label; | 1767 Label* fail = (deopt != NULL) ? deopt : &fail_label; |
| 1730 | 1768 |
| 1731 if (emit_full_guard) { | 1769 if (emit_full_guard) { |
| 1732 __ LoadObject(field_reg, Field::ZoneHandle(field().Original())); | 1770 __ LoadObject(field_reg, Field::ZoneHandle(field().Original())); |
| 1733 | 1771 |
| 1734 FieldAddress field_cid_operand(field_reg, Field::guarded_cid_offset()); | 1772 FieldAddress field_cid_operand(field_reg, Field::guarded_cid_offset()); |
| 1735 FieldAddress field_nullability_operand( | 1773 FieldAddress field_nullability_operand(field_reg, |
| 1736 field_reg, Field::is_nullable_offset()); | 1774 Field::is_nullable_offset()); |
| 1737 | 1775 |
| 1738 if (value_cid == kDynamicCid) { | 1776 if (value_cid == kDynamicCid) { |
| 1739 LoadValueCid(compiler, value_cid_reg, value_reg); | 1777 LoadValueCid(compiler, value_cid_reg, value_reg); |
| 1740 | 1778 |
| 1741 __ lhu(CMPRES1, field_cid_operand); | 1779 __ lhu(CMPRES1, field_cid_operand); |
| 1742 __ beq(value_cid_reg, CMPRES1, &ok); | 1780 __ beq(value_cid_reg, CMPRES1, &ok); |
| 1743 __ lhu(TMP, field_nullability_operand); | 1781 __ lhu(TMP, field_nullability_operand); |
| 1744 __ subu(CMPRES1, value_cid_reg, TMP); | 1782 __ subu(CMPRES1, value_cid_reg, TMP); |
| 1745 } else if (value_cid == kNullCid) { | 1783 } else if (value_cid == kNullCid) { |
| 1746 __ lhu(TMP, field_nullability_operand); | 1784 __ lhu(TMP, field_nullability_operand); |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1830 __ Bind(&ok); | 1868 __ Bind(&ok); |
| 1831 } | 1869 } |
| 1832 | 1870 |
| 1833 | 1871 |
| 1834 LocationSummary* GuardFieldLengthInstr::MakeLocationSummary(Zone* zone, | 1872 LocationSummary* GuardFieldLengthInstr::MakeLocationSummary(Zone* zone, |
| 1835 bool opt) const { | 1873 bool opt) const { |
| 1836 const intptr_t kNumInputs = 1; | 1874 const intptr_t kNumInputs = 1; |
| 1837 | 1875 |
| 1838 if (!opt || (field().guarded_list_length() == Field::kUnknownFixedLength)) { | 1876 if (!opt || (field().guarded_list_length() == Field::kUnknownFixedLength)) { |
| 1839 const intptr_t kNumTemps = 1; | 1877 const intptr_t kNumTemps = 1; |
| 1840 LocationSummary* summary = new(zone) LocationSummary( | 1878 LocationSummary* summary = new (zone) |
| 1841 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1879 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 1842 summary->set_in(0, Location::RequiresRegister()); | 1880 summary->set_in(0, Location::RequiresRegister()); |
| 1843 // We need temporaries for field object. | 1881 // We need temporaries for field object. |
| 1844 summary->set_temp(0, Location::RequiresRegister()); | 1882 summary->set_temp(0, Location::RequiresRegister()); |
| 1845 return summary; | 1883 return summary; |
| 1846 } | 1884 } |
| 1847 LocationSummary* summary = new(zone) LocationSummary( | 1885 LocationSummary* summary = |
| 1848 zone, kNumInputs, 0, LocationSummary::kNoCall); | 1886 new (zone) LocationSummary(zone, kNumInputs, 0, LocationSummary::kNoCall); |
| 1849 summary->set_in(0, Location::RequiresRegister()); | 1887 summary->set_in(0, Location::RequiresRegister()); |
| 1850 return summary; | 1888 return summary; |
| 1851 } | 1889 } |
| 1852 | 1890 |
| 1853 | 1891 |
| 1854 void GuardFieldLengthInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1892 void GuardFieldLengthInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1855 if (field().guarded_list_length() == Field::kNoFixedLength) { | 1893 if (field().guarded_list_length() == Field::kNoFixedLength) { |
| 1856 if (Compiler::IsBackgroundCompilation()) { | 1894 if (Compiler::IsBackgroundCompilation()) { |
| 1857 // Field state changed while compiling. | 1895 // Field state changed while compiling. |
| 1858 Compiler::AbortBackgroundCompilation(deopt_id(), | 1896 Compiler::AbortBackgroundCompilation( |
| 1897 deopt_id(), |
| 1859 "GuardFieldLengthInstr: field state changed while compiling"); | 1898 "GuardFieldLengthInstr: field state changed while compiling"); |
| 1860 } | 1899 } |
| 1861 ASSERT(!compiler->is_optimizing()); | 1900 ASSERT(!compiler->is_optimizing()); |
| 1862 return; // Nothing to emit. | 1901 return; // Nothing to emit. |
| 1863 } | 1902 } |
| 1864 | 1903 |
| 1865 Label* deopt = compiler->is_optimizing() ? | 1904 Label* deopt = |
| 1866 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptGuardField) : NULL; | 1905 compiler->is_optimizing() |
| 1906 ? compiler->AddDeoptStub(deopt_id(), ICData::kDeoptGuardField) |
| 1907 : NULL; |
| 1867 | 1908 |
| 1868 const Register value_reg = locs()->in(0).reg(); | 1909 const Register value_reg = locs()->in(0).reg(); |
| 1869 | 1910 |
| 1870 if (!compiler->is_optimizing() || | 1911 if (!compiler->is_optimizing() || |
| 1871 (field().guarded_list_length() == Field::kUnknownFixedLength)) { | 1912 (field().guarded_list_length() == Field::kUnknownFixedLength)) { |
| 1872 const Register field_reg = locs()->temp(0).reg(); | 1913 const Register field_reg = locs()->temp(0).reg(); |
| 1873 | 1914 |
| 1874 Label ok; | 1915 Label ok; |
| 1875 | 1916 |
| 1876 __ LoadObject(field_reg, Field::ZoneHandle(field().Original())); | 1917 __ LoadObject(field_reg, Field::ZoneHandle(field().Original())); |
| 1877 | 1918 |
| 1878 __ lb(CMPRES1, FieldAddress(field_reg, | 1919 __ lb(CMPRES1, |
| 1879 Field::guarded_list_length_in_object_offset_offset())); | 1920 FieldAddress(field_reg, |
| 1921 Field::guarded_list_length_in_object_offset_offset())); |
| 1880 __ blez(CMPRES1, &ok); | 1922 __ blez(CMPRES1, &ok); |
| 1881 | 1923 |
| 1882 __ lw(CMPRES2, FieldAddress(field_reg, | 1924 __ lw(CMPRES2, |
| 1883 Field::guarded_list_length_offset())); | 1925 FieldAddress(field_reg, Field::guarded_list_length_offset())); |
| 1884 | 1926 |
| 1885 // Load the length from the value. GuardFieldClass already verified that | 1927 // Load the length from the value. GuardFieldClass already verified that |
| 1886 // value's class matches guarded class id of the field. | 1928 // value's class matches guarded class id of the field. |
| 1887 // CMPRES1 contains offset already corrected by -kHeapObjectTag that is | 1929 // CMPRES1 contains offset already corrected by -kHeapObjectTag that is |
| 1888 // why we can use Address instead of FieldAddress. | 1930 // why we can use Address instead of FieldAddress. |
| 1889 __ addu(TMP, value_reg, CMPRES1); | 1931 __ addu(TMP, value_reg, CMPRES1); |
| 1890 __ lw(TMP, Address(TMP)); | 1932 __ lw(TMP, Address(TMP)); |
| 1891 | 1933 |
| 1892 if (deopt == NULL) { | 1934 if (deopt == NULL) { |
| 1893 __ beq(CMPRES2, TMP, &ok); | 1935 __ beq(CMPRES2, TMP, &ok); |
| 1894 | 1936 |
| 1895 __ addiu(SP, SP, Immediate(-2 * kWordSize)); | 1937 __ addiu(SP, SP, Immediate(-2 * kWordSize)); |
| 1896 __ sw(field_reg, Address(SP, 1 * kWordSize)); | 1938 __ sw(field_reg, Address(SP, 1 * kWordSize)); |
| 1897 __ sw(value_reg, Address(SP, 0 * kWordSize)); | 1939 __ sw(value_reg, Address(SP, 0 * kWordSize)); |
| 1898 __ CallRuntime(kUpdateFieldCidRuntimeEntry, 2); | 1940 __ CallRuntime(kUpdateFieldCidRuntimeEntry, 2); |
| 1899 __ Drop(2); // Drop the field and the value. | 1941 __ Drop(2); // Drop the field and the value. |
| 1900 } else { | 1942 } else { |
| 1901 __ bne(CMPRES2, TMP, deopt); | 1943 __ bne(CMPRES2, TMP, deopt); |
| 1902 } | 1944 } |
| 1903 | 1945 |
| 1904 __ Bind(&ok); | 1946 __ Bind(&ok); |
| 1905 } else { | 1947 } else { |
| 1906 ASSERT(compiler->is_optimizing()); | 1948 ASSERT(compiler->is_optimizing()); |
| 1907 ASSERT(field().guarded_list_length() >= 0); | 1949 ASSERT(field().guarded_list_length() >= 0); |
| 1908 ASSERT(field().guarded_list_length_in_object_offset() != | 1950 ASSERT(field().guarded_list_length_in_object_offset() != |
| 1909 Field::kUnknownLengthOffset); | 1951 Field::kUnknownLengthOffset); |
| 1910 | 1952 |
| 1911 __ lw(CMPRES1, | 1953 __ lw(CMPRES1, |
| 1912 FieldAddress(value_reg, | 1954 FieldAddress(value_reg, |
| 1913 field().guarded_list_length_in_object_offset())); | 1955 field().guarded_list_length_in_object_offset())); |
| 1914 __ LoadImmediate(TMP, Smi::RawValue(field().guarded_list_length())); | 1956 __ LoadImmediate(TMP, Smi::RawValue(field().guarded_list_length())); |
| 1915 __ bne(CMPRES1, TMP, deopt); | 1957 __ bne(CMPRES1, TMP, deopt); |
| 1916 } | 1958 } |
| 1917 } | 1959 } |
| 1918 | 1960 |
| 1919 | 1961 |
| 1920 class BoxAllocationSlowPath : public SlowPathCode { | 1962 class BoxAllocationSlowPath : public SlowPathCode { |
| 1921 public: | 1963 public: |
| 1922 BoxAllocationSlowPath(Instruction* instruction, | 1964 BoxAllocationSlowPath(Instruction* instruction, |
| 1923 const Class& cls, | 1965 const Class& cls, |
| 1924 Register result) | 1966 Register result) |
| 1925 : instruction_(instruction), | 1967 : instruction_(instruction), cls_(cls), result_(result) {} |
| 1926 cls_(cls), | |
| 1927 result_(result) { } | |
| 1928 | 1968 |
| 1929 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { | 1969 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1930 if (Assembler::EmittingComments()) { | 1970 if (Assembler::EmittingComments()) { |
| 1931 __ Comment("%s slow path allocation of %s", | 1971 __ Comment("%s slow path allocation of %s", instruction_->DebugName(), |
| 1932 instruction_->DebugName(), | |
| 1933 String::Handle(cls_.ScrubbedName()).ToCString()); | 1972 String::Handle(cls_.ScrubbedName()).ToCString()); |
| 1934 } | 1973 } |
| 1935 __ Bind(entry_label()); | 1974 __ Bind(entry_label()); |
| 1936 const Code& stub = Code::ZoneHandle( | 1975 const Code& stub = Code::ZoneHandle( |
| 1937 compiler->zone(), StubCode::GetAllocationStubForClass(cls_)); | 1976 compiler->zone(), StubCode::GetAllocationStubForClass(cls_)); |
| 1938 const StubEntry stub_entry(stub); | 1977 const StubEntry stub_entry(stub); |
| 1939 | 1978 |
| 1940 LocationSummary* locs = instruction_->locs(); | 1979 LocationSummary* locs = instruction_->locs(); |
| 1941 locs->live_registers()->Remove(Location::RegisterLocation(result_)); | 1980 locs->live_registers()->Remove(Location::RegisterLocation(result_)); |
| 1942 | 1981 |
| 1943 compiler->SaveLiveRegisters(locs); | 1982 compiler->SaveLiveRegisters(locs); |
| 1944 compiler->GenerateCall(TokenPosition::kNoSource, // No token position. | 1983 compiler->GenerateCall(TokenPosition::kNoSource, // No token position. |
| 1945 stub_entry, | 1984 stub_entry, RawPcDescriptors::kOther, locs); |
| 1946 RawPcDescriptors::kOther, | |
| 1947 locs); | |
| 1948 compiler->AddStubCallTarget(stub); | 1985 compiler->AddStubCallTarget(stub); |
| 1949 if (result_ != V0) { | 1986 if (result_ != V0) { |
| 1950 __ mov(result_, V0); | 1987 __ mov(result_, V0); |
| 1951 } | 1988 } |
| 1952 compiler->RestoreLiveRegisters(locs); | 1989 compiler->RestoreLiveRegisters(locs); |
| 1953 __ b(exit_label()); | 1990 __ b(exit_label()); |
| 1954 } | 1991 } |
| 1955 | 1992 |
| 1956 static void Allocate(FlowGraphCompiler* compiler, | 1993 static void Allocate(FlowGraphCompiler* compiler, |
| 1957 Instruction* instruction, | 1994 Instruction* instruction, |
| 1958 const Class& cls, | 1995 const Class& cls, |
| 1959 Register result, | 1996 Register result, |
| 1960 Register temp) { | 1997 Register temp) { |
| 1961 if (compiler->intrinsic_mode()) { | 1998 if (compiler->intrinsic_mode()) { |
| 1962 __ TryAllocate(cls, | 1999 __ TryAllocate(cls, compiler->intrinsic_slow_path_label(), result, temp); |
| 1963 compiler->intrinsic_slow_path_label(), | |
| 1964 result, | |
| 1965 temp); | |
| 1966 } else { | 2000 } else { |
| 1967 BoxAllocationSlowPath* slow_path = | 2001 BoxAllocationSlowPath* slow_path = |
| 1968 new BoxAllocationSlowPath(instruction, cls, result); | 2002 new BoxAllocationSlowPath(instruction, cls, result); |
| 1969 compiler->AddSlowPathCode(slow_path); | 2003 compiler->AddSlowPathCode(slow_path); |
| 1970 | 2004 |
| 1971 __ TryAllocate(cls, | 2005 __ TryAllocate(cls, slow_path->entry_label(), result, temp); |
| 1972 slow_path->entry_label(), | |
| 1973 result, | |
| 1974 temp); | |
| 1975 __ Bind(slow_path->exit_label()); | 2006 __ Bind(slow_path->exit_label()); |
| 1976 } | 2007 } |
| 1977 } | 2008 } |
| 1978 | 2009 |
| 1979 private: | 2010 private: |
| 1980 Instruction* instruction_; | 2011 Instruction* instruction_; |
| 1981 const Class& cls_; | 2012 const Class& cls_; |
| 1982 const Register result_; | 2013 const Register result_; |
| 1983 }; | 2014 }; |
| 1984 | 2015 |
| 1985 | 2016 |
| 1986 LocationSummary* StoreInstanceFieldInstr::MakeLocationSummary(Zone* zone, | 2017 LocationSummary* StoreInstanceFieldInstr::MakeLocationSummary(Zone* zone, |
| 1987 bool opt) const { | 2018 bool opt) const { |
| 1988 const intptr_t kNumInputs = 2; | 2019 const intptr_t kNumInputs = 2; |
| 1989 const intptr_t kNumTemps = | 2020 const intptr_t kNumTemps = |
| 1990 (IsUnboxedStore() && opt) ? 2 : | 2021 (IsUnboxedStore() && opt) ? 2 : ((IsPotentialUnboxedStore()) ? 3 : 0); |
| 1991 ((IsPotentialUnboxedStore()) ? 3 : 0); | 2022 LocationSummary* summary = new (zone) |
| 1992 LocationSummary* summary = new(zone) LocationSummary( | 2023 LocationSummary(zone, kNumInputs, kNumTemps, |
| 1993 zone, kNumInputs, kNumTemps, | 2024 ((IsUnboxedStore() && opt && is_initialization()) || |
| 1994 ((IsUnboxedStore() && opt && is_initialization()) || | 2025 IsPotentialUnboxedStore()) |
| 1995 IsPotentialUnboxedStore()) | 2026 ? LocationSummary::kCallOnSlowPath |
| 1996 ? LocationSummary::kCallOnSlowPath | 2027 : LocationSummary::kNoCall); |
| 1997 : LocationSummary::kNoCall); | |
| 1998 | 2028 |
| 1999 summary->set_in(0, Location::RequiresRegister()); | 2029 summary->set_in(0, Location::RequiresRegister()); |
| 2000 if (IsUnboxedStore() && opt) { | 2030 if (IsUnboxedStore() && opt) { |
| 2001 summary->set_in(1, Location::RequiresFpuRegister()); | 2031 summary->set_in(1, Location::RequiresFpuRegister()); |
| 2002 summary->set_temp(0, Location::RequiresRegister()); | 2032 summary->set_temp(0, Location::RequiresRegister()); |
| 2003 summary->set_temp(1, Location::RequiresRegister()); | 2033 summary->set_temp(1, Location::RequiresRegister()); |
| 2004 } else if (IsPotentialUnboxedStore()) { | 2034 } else if (IsPotentialUnboxedStore()) { |
| 2005 summary->set_in(1, ShouldEmitStoreBarrier() | 2035 summary->set_in(1, ShouldEmitStoreBarrier() ? Location::WritableRegister() |
| 2006 ? Location::WritableRegister() | 2036 : Location::RequiresRegister()); |
| 2007 : Location::RequiresRegister()); | |
| 2008 summary->set_temp(0, Location::RequiresRegister()); | 2037 summary->set_temp(0, Location::RequiresRegister()); |
| 2009 summary->set_temp(1, Location::RequiresRegister()); | 2038 summary->set_temp(1, Location::RequiresRegister()); |
| 2010 summary->set_temp(2, opt ? Location::RequiresFpuRegister() | 2039 summary->set_temp(2, opt ? Location::RequiresFpuRegister() |
| 2011 : Location::FpuRegisterLocation(D1)); | 2040 : Location::FpuRegisterLocation(D1)); |
| 2012 } else { | 2041 } else { |
| 2013 summary->set_in(1, ShouldEmitStoreBarrier() | 2042 summary->set_in(1, ShouldEmitStoreBarrier() |
| 2014 ? Location::WritableRegister() | 2043 ? Location::WritableRegister() |
| 2015 : Location::RegisterOrConstant(value())); | 2044 : Location::RegisterOrConstant(value())); |
| 2016 } | 2045 } |
| 2017 return summary; | 2046 return summary; |
| 2018 } | 2047 } |
| 2019 | 2048 |
| 2020 | 2049 |
| 2021 static void EnsureMutableBox(FlowGraphCompiler* compiler, | 2050 static void EnsureMutableBox(FlowGraphCompiler* compiler, |
| 2022 StoreInstanceFieldInstr* instruction, | 2051 StoreInstanceFieldInstr* instruction, |
| 2023 Register box_reg, | 2052 Register box_reg, |
| 2024 const Class& cls, | 2053 const Class& cls, |
| 2025 Register instance_reg, | 2054 Register instance_reg, |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2059 | 2088 |
| 2060 BoxAllocationSlowPath::Allocate(compiler, this, *cls, temp, temp2); | 2089 BoxAllocationSlowPath::Allocate(compiler, this, *cls, temp, temp2); |
| 2061 __ mov(temp2, temp); | 2090 __ mov(temp2, temp); |
| 2062 __ StoreIntoObjectOffset(instance_reg, offset_in_bytes_, temp2); | 2091 __ StoreIntoObjectOffset(instance_reg, offset_in_bytes_, temp2); |
| 2063 } else { | 2092 } else { |
| 2064 __ lw(temp, FieldAddress(instance_reg, offset_in_bytes_)); | 2093 __ lw(temp, FieldAddress(instance_reg, offset_in_bytes_)); |
| 2065 } | 2094 } |
| 2066 switch (cid) { | 2095 switch (cid) { |
| 2067 case kDoubleCid: | 2096 case kDoubleCid: |
| 2068 __ StoreDToOffset(value, temp, Double::value_offset() - kHeapObjectTag); | 2097 __ StoreDToOffset(value, temp, Double::value_offset() - kHeapObjectTag); |
| 2069 break; | 2098 break; |
| 2070 default: | 2099 default: |
| 2071 UNREACHABLE(); | 2100 UNREACHABLE(); |
| 2072 } | 2101 } |
| 2073 return; | 2102 return; |
| 2074 } | 2103 } |
| 2075 | 2104 |
| 2076 if (IsPotentialUnboxedStore()) { | 2105 if (IsPotentialUnboxedStore()) { |
| 2077 Register value_reg = locs()->in(1).reg(); | 2106 Register value_reg = locs()->in(1).reg(); |
| 2078 Register temp = locs()->temp(0).reg(); | 2107 Register temp = locs()->temp(0).reg(); |
| 2079 Register temp2 = locs()->temp(1).reg(); | 2108 Register temp2 = locs()->temp(1).reg(); |
| (...skipping 23 matching lines...) Expand all Loading... |
| 2103 // Fall through. | 2132 // Fall through. |
| 2104 __ b(&store_pointer); | 2133 __ b(&store_pointer); |
| 2105 | 2134 |
| 2106 if (!compiler->is_optimizing()) { | 2135 if (!compiler->is_optimizing()) { |
| 2107 locs()->live_registers()->Add(locs()->in(0)); | 2136 locs()->live_registers()->Add(locs()->in(0)); |
| 2108 locs()->live_registers()->Add(locs()->in(1)); | 2137 locs()->live_registers()->Add(locs()->in(1)); |
| 2109 } | 2138 } |
| 2110 | 2139 |
| 2111 { | 2140 { |
| 2112 __ Bind(&store_double); | 2141 __ Bind(&store_double); |
| 2113 EnsureMutableBox(compiler, | 2142 EnsureMutableBox(compiler, this, temp, compiler->double_class(), |
| 2114 this, | 2143 instance_reg, offset_in_bytes_, temp2); |
| 2115 temp, | 2144 __ LoadDFromOffset(fpu_temp, value_reg, |
| 2116 compiler->double_class(), | |
| 2117 instance_reg, | |
| 2118 offset_in_bytes_, | |
| 2119 temp2); | |
| 2120 __ LoadDFromOffset(fpu_temp, | |
| 2121 value_reg, | |
| 2122 Double::value_offset() - kHeapObjectTag); | 2145 Double::value_offset() - kHeapObjectTag); |
| 2123 __ StoreDToOffset(fpu_temp, temp, | 2146 __ StoreDToOffset(fpu_temp, temp, |
| 2124 Double::value_offset() - kHeapObjectTag); | 2147 Double::value_offset() - kHeapObjectTag); |
| 2125 __ b(&skip_store); | 2148 __ b(&skip_store); |
| 2126 } | 2149 } |
| 2127 | 2150 |
| 2128 __ Bind(&store_pointer); | 2151 __ Bind(&store_pointer); |
| 2129 } | 2152 } |
| 2130 | 2153 |
| 2131 if (ShouldEmitStoreBarrier()) { | 2154 if (ShouldEmitStoreBarrier()) { |
| 2132 Register value_reg = locs()->in(1).reg(); | 2155 Register value_reg = locs()->in(1).reg(); |
| 2133 __ StoreIntoObjectOffset(instance_reg, | 2156 __ StoreIntoObjectOffset(instance_reg, offset_in_bytes_, value_reg, |
| 2134 offset_in_bytes_, | |
| 2135 value_reg, | |
| 2136 CanValueBeSmi()); | 2157 CanValueBeSmi()); |
| 2137 } else { | 2158 } else { |
| 2138 if (locs()->in(1).IsConstant()) { | 2159 if (locs()->in(1).IsConstant()) { |
| 2139 __ StoreIntoObjectNoBarrierOffset( | 2160 __ StoreIntoObjectNoBarrierOffset(instance_reg, offset_in_bytes_, |
| 2140 instance_reg, | 2161 locs()->in(1).constant()); |
| 2141 offset_in_bytes_, | |
| 2142 locs()->in(1).constant()); | |
| 2143 } else { | 2162 } else { |
| 2144 Register value_reg = locs()->in(1).reg(); | 2163 Register value_reg = locs()->in(1).reg(); |
| 2145 __ StoreIntoObjectNoBarrierOffset(instance_reg, | 2164 __ StoreIntoObjectNoBarrierOffset(instance_reg, offset_in_bytes_, |
| 2146 offset_in_bytes_, | |
| 2147 value_reg); | 2165 value_reg); |
| 2148 } | 2166 } |
| 2149 } | 2167 } |
| 2150 __ Bind(&skip_store); | 2168 __ Bind(&skip_store); |
| 2151 } | 2169 } |
| 2152 | 2170 |
| 2153 | 2171 |
| 2154 LocationSummary* LoadStaticFieldInstr::MakeLocationSummary(Zone* zone, | 2172 LocationSummary* LoadStaticFieldInstr::MakeLocationSummary(Zone* zone, |
| 2155 bool opt) const { | 2173 bool opt) const { |
| 2156 const intptr_t kNumInputs = 1; | 2174 const intptr_t kNumInputs = 1; |
| 2157 const intptr_t kNumTemps = 0; | 2175 const intptr_t kNumTemps = 0; |
| 2158 LocationSummary* summary = new(zone) LocationSummary( | 2176 LocationSummary* summary = new (zone) |
| 2159 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 2177 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 2160 summary->set_in(0, Location::RequiresRegister()); | 2178 summary->set_in(0, Location::RequiresRegister()); |
| 2161 summary->set_out(0, Location::RequiresRegister()); | 2179 summary->set_out(0, Location::RequiresRegister()); |
| 2162 return summary; | 2180 return summary; |
| 2163 } | 2181 } |
| 2164 | 2182 |
| 2165 | 2183 |
| 2166 // When the parser is building an implicit static getter for optimization, | 2184 // When the parser is building an implicit static getter for optimization, |
| 2167 // it can generate a function body where deoptimization ids do not line up | 2185 // it can generate a function body where deoptimization ids do not line up |
| 2168 // with the unoptimized code. | 2186 // with the unoptimized code. |
| 2169 // | 2187 // |
| 2170 // This is safe only so long as LoadStaticFieldInstr cannot deoptimize. | 2188 // This is safe only so long as LoadStaticFieldInstr cannot deoptimize. |
| 2171 void LoadStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2189 void LoadStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2172 __ Comment("LoadStaticFieldInstr"); | 2190 __ Comment("LoadStaticFieldInstr"); |
| 2173 Register field = locs()->in(0).reg(); | 2191 Register field = locs()->in(0).reg(); |
| 2174 Register result = locs()->out(0).reg(); | 2192 Register result = locs()->out(0).reg(); |
| 2175 __ LoadFromOffset(result, | 2193 __ LoadFromOffset(result, field, |
| 2176 field, | |
| 2177 Field::static_value_offset() - kHeapObjectTag); | 2194 Field::static_value_offset() - kHeapObjectTag); |
| 2178 } | 2195 } |
| 2179 | 2196 |
| 2180 | 2197 |
| 2181 LocationSummary* StoreStaticFieldInstr::MakeLocationSummary(Zone* zone, | 2198 LocationSummary* StoreStaticFieldInstr::MakeLocationSummary(Zone* zone, |
| 2182 bool opt) const { | 2199 bool opt) const { |
| 2183 LocationSummary* locs = new(zone) LocationSummary( | 2200 LocationSummary* locs = |
| 2184 zone, 1, 1, LocationSummary::kNoCall); | 2201 new (zone) LocationSummary(zone, 1, 1, LocationSummary::kNoCall); |
| 2185 locs->set_in(0, value()->NeedsStoreBuffer() ? Location::WritableRegister() | 2202 locs->set_in(0, value()->NeedsStoreBuffer() ? Location::WritableRegister() |
| 2186 : Location::RequiresRegister()); | 2203 : Location::RequiresRegister()); |
| 2187 locs->set_temp(0, Location::RequiresRegister()); | 2204 locs->set_temp(0, Location::RequiresRegister()); |
| 2188 return locs; | 2205 return locs; |
| 2189 } | 2206 } |
| 2190 | 2207 |
| 2191 | 2208 |
| 2192 void StoreStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2209 void StoreStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2193 __ Comment("StoreStaticFieldInstr"); | 2210 __ Comment("StoreStaticFieldInstr"); |
| 2194 Register value = locs()->in(0).reg(); | 2211 Register value = locs()->in(0).reg(); |
| 2195 Register temp = locs()->temp(0).reg(); | 2212 Register temp = locs()->temp(0).reg(); |
| 2196 | 2213 |
| 2197 __ LoadObject(temp, Field::ZoneHandle(Z, field().Original())); | 2214 __ LoadObject(temp, Field::ZoneHandle(Z, field().Original())); |
| 2198 if (this->value()->NeedsStoreBuffer()) { | 2215 if (this->value()->NeedsStoreBuffer()) { |
| 2199 __ StoreIntoObject(temp, | 2216 __ StoreIntoObject(temp, FieldAddress(temp, Field::static_value_offset()), |
| 2200 FieldAddress(temp, Field::static_value_offset()), | 2217 value, CanValueBeSmi()); |
| 2201 value, | |
| 2202 CanValueBeSmi()); | |
| 2203 } else { | 2218 } else { |
| 2204 __ StoreIntoObjectNoBarrier( | 2219 __ StoreIntoObjectNoBarrier( |
| 2205 temp, FieldAddress(temp, Field::static_value_offset()), value); | 2220 temp, FieldAddress(temp, Field::static_value_offset()), value); |
| 2206 } | 2221 } |
| 2207 } | 2222 } |
| 2208 | 2223 |
| 2209 | 2224 |
| 2210 LocationSummary* InstanceOfInstr::MakeLocationSummary(Zone* zone, | 2225 LocationSummary* InstanceOfInstr::MakeLocationSummary(Zone* zone, |
| 2211 bool opt) const { | 2226 bool opt) const { |
| 2212 const intptr_t kNumInputs = 2; | 2227 const intptr_t kNumInputs = 2; |
| 2213 const intptr_t kNumTemps = 0; | 2228 const intptr_t kNumTemps = 0; |
| 2214 LocationSummary* summary = new(zone) LocationSummary( | 2229 LocationSummary* summary = new (zone) |
| 2215 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 2230 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
| 2216 summary->set_in(0, Location::RegisterLocation(A0)); | 2231 summary->set_in(0, Location::RegisterLocation(A0)); |
| 2217 summary->set_in(1, Location::RegisterLocation(A1)); | 2232 summary->set_in(1, Location::RegisterLocation(A1)); |
| 2218 summary->set_out(0, Location::RegisterLocation(V0)); | 2233 summary->set_out(0, Location::RegisterLocation(V0)); |
| 2219 return summary; | 2234 return summary; |
| 2220 } | 2235 } |
| 2221 | 2236 |
| 2222 | 2237 |
| 2223 void InstanceOfInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2238 void InstanceOfInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2224 ASSERT(locs()->in(0).reg() == A0); // Value. | 2239 ASSERT(locs()->in(0).reg() == A0); // Value. |
| 2225 ASSERT(locs()->in(1).reg() == A1); // Instantiator type arguments. | 2240 ASSERT(locs()->in(1).reg() == A1); // Instantiator type arguments. |
| 2226 | 2241 |
| 2227 __ Comment("InstanceOfInstr"); | 2242 __ Comment("InstanceOfInstr"); |
| 2228 compiler->GenerateInstanceOf(token_pos(), | 2243 compiler->GenerateInstanceOf(token_pos(), deopt_id(), type(), negate_result(), |
| 2229 deopt_id(), | |
| 2230 type(), | |
| 2231 negate_result(), | |
| 2232 locs()); | 2244 locs()); |
| 2233 ASSERT(locs()->out(0).reg() == V0); | 2245 ASSERT(locs()->out(0).reg() == V0); |
| 2234 } | 2246 } |
| 2235 | 2247 |
| 2236 | 2248 |
| 2237 LocationSummary* CreateArrayInstr::MakeLocationSummary(Zone* zone, | 2249 LocationSummary* CreateArrayInstr::MakeLocationSummary(Zone* zone, |
| 2238 bool opt) const { | 2250 bool opt) const { |
| 2239 const intptr_t kNumInputs = 2; | 2251 const intptr_t kNumInputs = 2; |
| 2240 const intptr_t kNumTemps = 0; | 2252 const intptr_t kNumTemps = 0; |
| 2241 LocationSummary* locs = new(zone) LocationSummary( | 2253 LocationSummary* locs = new (zone) |
| 2242 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 2254 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
| 2243 locs->set_in(0, Location::RegisterLocation(A0)); | 2255 locs->set_in(0, Location::RegisterLocation(A0)); |
| 2244 locs->set_in(1, Location::RegisterLocation(A1)); | 2256 locs->set_in(1, Location::RegisterLocation(A1)); |
| 2245 locs->set_out(0, Location::RegisterLocation(V0)); | 2257 locs->set_out(0, Location::RegisterLocation(V0)); |
| 2246 return locs; | 2258 return locs; |
| 2247 } | 2259 } |
| 2248 | 2260 |
| 2249 | 2261 |
| 2250 // Inlines array allocation for known constant values. | 2262 // Inlines array allocation for known constant values. |
| 2251 static void InlineArrayAllocation(FlowGraphCompiler* compiler, | 2263 static void InlineArrayAllocation(FlowGraphCompiler* compiler, |
| 2252 intptr_t num_elements, | 2264 intptr_t num_elements, |
| 2253 Label* slow_path, | 2265 Label* slow_path, |
| 2254 Label* done) { | 2266 Label* done) { |
| 2255 const int kInlineArraySize = 12; // Same as kInlineInstanceSize. | 2267 const int kInlineArraySize = 12; // Same as kInlineInstanceSize. |
| 2256 const Register kLengthReg = A1; | 2268 const Register kLengthReg = A1; |
| 2257 const Register kElemTypeReg = A0; | 2269 const Register kElemTypeReg = A0; |
| 2258 const intptr_t instance_size = Array::InstanceSize(num_elements); | 2270 const intptr_t instance_size = Array::InstanceSize(num_elements); |
| 2259 | 2271 |
| 2260 __ TryAllocateArray(kArrayCid, instance_size, slow_path, | 2272 __ TryAllocateArray(kArrayCid, instance_size, slow_path, |
| 2261 V0, // instance | 2273 V0, // instance |
| 2262 T1, // end address | 2274 T1, // end address |
| 2263 T2, | 2275 T2, T3); |
| 2264 T3); | |
| 2265 // V0: new object start as a tagged pointer. | 2276 // V0: new object start as a tagged pointer. |
| 2266 // T1: new object end address. | 2277 // T1: new object end address. |
| 2267 | 2278 |
| 2268 // Store the type argument field. | 2279 // Store the type argument field. |
| 2269 __ StoreIntoObjectNoBarrier(V0, | 2280 __ StoreIntoObjectNoBarrier( |
| 2270 FieldAddress(V0, Array::type_arguments_offset()), | 2281 V0, FieldAddress(V0, Array::type_arguments_offset()), kElemTypeReg); |
| 2271 kElemTypeReg); | |
| 2272 | 2282 |
| 2273 // Set the length field. | 2283 // Set the length field. |
| 2274 __ StoreIntoObjectNoBarrier(V0, | 2284 __ StoreIntoObjectNoBarrier(V0, FieldAddress(V0, Array::length_offset()), |
| 2275 FieldAddress(V0, Array::length_offset()), | |
| 2276 kLengthReg); | 2285 kLengthReg); |
| 2277 | 2286 |
| 2278 // Initialize all array elements to raw_null. | 2287 // Initialize all array elements to raw_null. |
| 2279 // V0: new object start as a tagged pointer. | 2288 // V0: new object start as a tagged pointer. |
| 2280 // T1: new object end address. | 2289 // T1: new object end address. |
| 2281 // T2: iterator which initially points to the start of the variable | 2290 // T2: iterator which initially points to the start of the variable |
| 2282 // data area to be initialized. | 2291 // data area to be initialized. |
| 2283 // T7: null. | 2292 // T7: null. |
| 2284 if (num_elements > 0) { | 2293 if (num_elements > 0) { |
| 2285 const intptr_t array_size = instance_size - sizeof(RawArray); | 2294 const intptr_t array_size = instance_size - sizeof(RawArray); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 2305 | 2314 |
| 2306 void CreateArrayInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2315 void CreateArrayInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2307 __ Comment("CreateArrayInstr"); | 2316 __ Comment("CreateArrayInstr"); |
| 2308 const Register kLengthReg = A1; | 2317 const Register kLengthReg = A1; |
| 2309 const Register kElemTypeReg = A0; | 2318 const Register kElemTypeReg = A0; |
| 2310 const Register kResultReg = V0; | 2319 const Register kResultReg = V0; |
| 2311 ASSERT(locs()->in(0).reg() == kElemTypeReg); | 2320 ASSERT(locs()->in(0).reg() == kElemTypeReg); |
| 2312 ASSERT(locs()->in(1).reg() == kLengthReg); | 2321 ASSERT(locs()->in(1).reg() == kLengthReg); |
| 2313 | 2322 |
| 2314 Label slow_path, done; | 2323 Label slow_path, done; |
| 2315 if (compiler->is_optimizing() && | 2324 if (compiler->is_optimizing() && !FLAG_precompiled_mode && |
| 2316 !FLAG_precompiled_mode && | |
| 2317 num_elements()->BindsToConstant() && | 2325 num_elements()->BindsToConstant() && |
| 2318 num_elements()->BoundConstant().IsSmi()) { | 2326 num_elements()->BoundConstant().IsSmi()) { |
| 2319 const intptr_t length = Smi::Cast(num_elements()->BoundConstant()).Value(); | 2327 const intptr_t length = Smi::Cast(num_elements()->BoundConstant()).Value(); |
| 2320 if ((length >= 0) && (length <= Array::kMaxElements)) { | 2328 if ((length >= 0) && (length <= Array::kMaxElements)) { |
| 2321 Label slow_path, done; | 2329 Label slow_path, done; |
| 2322 InlineArrayAllocation(compiler, length, &slow_path, &done); | 2330 InlineArrayAllocation(compiler, length, &slow_path, &done); |
| 2323 __ Bind(&slow_path); | 2331 __ Bind(&slow_path); |
| 2324 __ PushObject(Object::null_object()); // Make room for the result. | 2332 __ PushObject(Object::null_object()); // Make room for the result. |
| 2325 __ Push(kLengthReg); // length. | 2333 __ Push(kLengthReg); // length. |
| 2326 __ Push(kElemTypeReg); | 2334 __ Push(kElemTypeReg); |
| 2327 compiler->GenerateRuntimeCall(token_pos(), | 2335 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), |
| 2328 deopt_id(), | 2336 kAllocateArrayRuntimeEntry, 2, locs()); |
| 2329 kAllocateArrayRuntimeEntry, | |
| 2330 2, | |
| 2331 locs()); | |
| 2332 __ Drop(2); | 2337 __ Drop(2); |
| 2333 __ Pop(kResultReg); | 2338 __ Pop(kResultReg); |
| 2334 __ Bind(&done); | 2339 __ Bind(&done); |
| 2335 return; | 2340 return; |
| 2336 } | 2341 } |
| 2337 } | 2342 } |
| 2338 | 2343 |
| 2339 __ Bind(&slow_path); | 2344 __ Bind(&slow_path); |
| 2340 const Code& stub = Code::ZoneHandle(compiler->zone(), | 2345 const Code& stub = Code::ZoneHandle(compiler->zone(), |
| 2341 StubCode::AllocateArray_entry()->code()); | 2346 StubCode::AllocateArray_entry()->code()); |
| 2342 compiler->AddStubCallTarget(stub); | 2347 compiler->AddStubCallTarget(stub); |
| 2343 compiler->GenerateCall(token_pos(), | 2348 compiler->GenerateCall(token_pos(), *StubCode::AllocateArray_entry(), |
| 2344 *StubCode::AllocateArray_entry(), | 2349 RawPcDescriptors::kOther, locs()); |
| 2345 RawPcDescriptors::kOther, | |
| 2346 locs()); | |
| 2347 __ Bind(&done); | 2350 __ Bind(&done); |
| 2348 ASSERT(locs()->out(0).reg() == kResultReg); | 2351 ASSERT(locs()->out(0).reg() == kResultReg); |
| 2349 } | 2352 } |
| 2350 | 2353 |
| 2351 | 2354 |
| 2352 LocationSummary* LoadFieldInstr::MakeLocationSummary(Zone* zone, | 2355 LocationSummary* LoadFieldInstr::MakeLocationSummary(Zone* zone, |
| 2353 bool opt) const { | 2356 bool opt) const { |
| 2354 const intptr_t kNumInputs = 1; | 2357 const intptr_t kNumInputs = 1; |
| 2355 const intptr_t kNumTemps = | 2358 const intptr_t kNumTemps = |
| 2356 (IsUnboxedLoad() && opt) ? 1 : | 2359 (IsUnboxedLoad() && opt) ? 1 : ((IsPotentialUnboxedLoad()) ? 2 : 0); |
| 2357 ((IsPotentialUnboxedLoad()) ? 2 : 0); | 2360 LocationSummary* locs = new (zone) LocationSummary( |
| 2358 LocationSummary* locs = new(zone) LocationSummary( | 2361 zone, kNumInputs, kNumTemps, (opt && !IsPotentialUnboxedLoad()) |
| 2359 zone, kNumInputs, kNumTemps, | 2362 ? LocationSummary::kNoCall |
| 2360 (opt && !IsPotentialUnboxedLoad()) | 2363 : LocationSummary::kCallOnSlowPath); |
| 2361 ? LocationSummary::kNoCall | |
| 2362 : LocationSummary::kCallOnSlowPath); | |
| 2363 | 2364 |
| 2364 locs->set_in(0, Location::RequiresRegister()); | 2365 locs->set_in(0, Location::RequiresRegister()); |
| 2365 | 2366 |
| 2366 if (IsUnboxedLoad() && opt) { | 2367 if (IsUnboxedLoad() && opt) { |
| 2367 locs->set_temp(0, Location::RequiresRegister()); | 2368 locs->set_temp(0, Location::RequiresRegister()); |
| 2368 } else if (IsPotentialUnboxedLoad()) { | 2369 } else if (IsPotentialUnboxedLoad()) { |
| 2369 locs->set_temp(0, opt ? Location::RequiresFpuRegister() | 2370 locs->set_temp(0, opt ? Location::RequiresFpuRegister() |
| 2370 : Location::FpuRegisterLocation(D1)); | 2371 : Location::FpuRegisterLocation(D1)); |
| 2371 locs->set_temp(1, Location::RequiresRegister()); | 2372 locs->set_temp(1, Location::RequiresRegister()); |
| 2372 } | 2373 } |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2418 | 2419 |
| 2419 // Fall through. | 2420 // Fall through. |
| 2420 __ b(&load_pointer); | 2421 __ b(&load_pointer); |
| 2421 | 2422 |
| 2422 if (!compiler->is_optimizing()) { | 2423 if (!compiler->is_optimizing()) { |
| 2423 locs()->live_registers()->Add(locs()->in(0)); | 2424 locs()->live_registers()->Add(locs()->in(0)); |
| 2424 } | 2425 } |
| 2425 | 2426 |
| 2426 { | 2427 { |
| 2427 __ Bind(&load_double); | 2428 __ Bind(&load_double); |
| 2428 BoxAllocationSlowPath::Allocate( | 2429 BoxAllocationSlowPath::Allocate(compiler, this, compiler->double_class(), |
| 2429 compiler, this, compiler->double_class(), result_reg, temp); | 2430 result_reg, temp); |
| 2430 __ lw(temp, FieldAddress(instance_reg, offset_in_bytes())); | 2431 __ lw(temp, FieldAddress(instance_reg, offset_in_bytes())); |
| 2431 __ LoadDFromOffset(value, temp, Double::value_offset() - kHeapObjectTag); | 2432 __ LoadDFromOffset(value, temp, Double::value_offset() - kHeapObjectTag); |
| 2432 __ StoreDToOffset(value, | 2433 __ StoreDToOffset(value, result_reg, |
| 2433 result_reg, | |
| 2434 Double::value_offset() - kHeapObjectTag); | 2434 Double::value_offset() - kHeapObjectTag); |
| 2435 __ b(&done); | 2435 __ b(&done); |
| 2436 } | 2436 } |
| 2437 | 2437 |
| 2438 __ Bind(&load_pointer); | 2438 __ Bind(&load_pointer); |
| 2439 } | 2439 } |
| 2440 __ LoadFieldFromOffset(result_reg, instance_reg, offset_in_bytes()); | 2440 __ LoadFieldFromOffset(result_reg, instance_reg, offset_in_bytes()); |
| 2441 __ Bind(&done); | 2441 __ Bind(&done); |
| 2442 } | 2442 } |
| 2443 | 2443 |
| 2444 | 2444 |
| 2445 LocationSummary* InstantiateTypeInstr::MakeLocationSummary(Zone* zone, | 2445 LocationSummary* InstantiateTypeInstr::MakeLocationSummary(Zone* zone, |
| 2446 bool opt) const { | 2446 bool opt) const { |
| 2447 const intptr_t kNumInputs = 1; | 2447 const intptr_t kNumInputs = 1; |
| 2448 const intptr_t kNumTemps = 0; | 2448 const intptr_t kNumTemps = 0; |
| 2449 LocationSummary* locs = new(zone) LocationSummary( | 2449 LocationSummary* locs = new (zone) |
| 2450 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 2450 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
| 2451 locs->set_in(0, Location::RegisterLocation(T0)); | 2451 locs->set_in(0, Location::RegisterLocation(T0)); |
| 2452 locs->set_out(0, Location::RegisterLocation(T0)); | 2452 locs->set_out(0, Location::RegisterLocation(T0)); |
| 2453 return locs; | 2453 return locs; |
| 2454 } | 2454 } |
| 2455 | 2455 |
| 2456 | 2456 |
| 2457 void InstantiateTypeInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2457 void InstantiateTypeInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2458 __ Comment("InstantiateTypeInstr"); | 2458 __ Comment("InstantiateTypeInstr"); |
| 2459 Register instantiator_reg = locs()->in(0).reg(); | 2459 Register instantiator_reg = locs()->in(0).reg(); |
| 2460 Register result_reg = locs()->out(0).reg(); | 2460 Register result_reg = locs()->out(0).reg(); |
| 2461 | 2461 |
| 2462 // 'instantiator_reg' is the instantiator TypeArguments object (or null). | 2462 // 'instantiator_reg' is the instantiator TypeArguments object (or null). |
| 2463 // A runtime call to instantiate the type is required. | 2463 // A runtime call to instantiate the type is required. |
| 2464 __ addiu(SP, SP, Immediate(-3 * kWordSize)); | 2464 __ addiu(SP, SP, Immediate(-3 * kWordSize)); |
| 2465 __ LoadObject(TMP, Object::null_object()); | 2465 __ LoadObject(TMP, Object::null_object()); |
| 2466 __ sw(TMP, Address(SP, 2 * kWordSize)); // Make room for the result. | 2466 __ sw(TMP, Address(SP, 2 * kWordSize)); // Make room for the result. |
| 2467 __ LoadObject(TMP, type()); | 2467 __ LoadObject(TMP, type()); |
| 2468 __ sw(TMP, Address(SP, 1 * kWordSize)); | 2468 __ sw(TMP, Address(SP, 1 * kWordSize)); |
| 2469 // Push instantiator type arguments. | 2469 // Push instantiator type arguments. |
| 2470 __ sw(instantiator_reg, Address(SP, 0 * kWordSize)); | 2470 __ sw(instantiator_reg, Address(SP, 0 * kWordSize)); |
| 2471 | 2471 |
| 2472 compiler->GenerateRuntimeCall(token_pos(), | 2472 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), |
| 2473 deopt_id(), | 2473 kInstantiateTypeRuntimeEntry, 2, locs()); |
| 2474 kInstantiateTypeRuntimeEntry, | |
| 2475 2, | |
| 2476 locs()); | |
| 2477 // Pop instantiated type. | 2474 // Pop instantiated type. |
| 2478 __ lw(result_reg, Address(SP, 2 * kWordSize)); | 2475 __ lw(result_reg, Address(SP, 2 * kWordSize)); |
| 2479 // Drop instantiator and uninstantiated type. | 2476 // Drop instantiator and uninstantiated type. |
| 2480 __ addiu(SP, SP, Immediate(3 * kWordSize)); | 2477 __ addiu(SP, SP, Immediate(3 * kWordSize)); |
| 2481 ASSERT(instantiator_reg == result_reg); | 2478 ASSERT(instantiator_reg == result_reg); |
| 2482 } | 2479 } |
| 2483 | 2480 |
| 2484 | 2481 |
| 2485 LocationSummary* InstantiateTypeArgumentsInstr::MakeLocationSummary( | 2482 LocationSummary* InstantiateTypeArgumentsInstr::MakeLocationSummary( |
| 2486 Zone* zone, bool opt) const { | 2483 Zone* zone, |
| 2484 bool opt) const { |
| 2487 const intptr_t kNumInputs = 1; | 2485 const intptr_t kNumInputs = 1; |
| 2488 const intptr_t kNumTemps = 0; | 2486 const intptr_t kNumTemps = 0; |
| 2489 LocationSummary* locs = new(zone) LocationSummary( | 2487 LocationSummary* locs = new (zone) |
| 2490 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 2488 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
| 2491 locs->set_in(0, Location::RegisterLocation(T0)); | 2489 locs->set_in(0, Location::RegisterLocation(T0)); |
| 2492 locs->set_out(0, Location::RegisterLocation(T0)); | 2490 locs->set_out(0, Location::RegisterLocation(T0)); |
| 2493 return locs; | 2491 return locs; |
| 2494 } | 2492 } |
| 2495 | 2493 |
| 2496 | 2494 |
| 2497 void InstantiateTypeArgumentsInstr::EmitNativeCode( | 2495 void InstantiateTypeArgumentsInstr::EmitNativeCode( |
| 2498 FlowGraphCompiler* compiler) { | 2496 FlowGraphCompiler* compiler) { |
| 2499 __ Comment("InstantiateTypeArgumentsInstr"); | 2497 __ Comment("InstantiateTypeArgumentsInstr"); |
| 2500 Register instantiator_reg = locs()->in(0).reg(); | 2498 Register instantiator_reg = locs()->in(0).reg(); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 2518 | 2516 |
| 2519 __ LoadObject(T2, type_arguments()); | 2517 __ LoadObject(T2, type_arguments()); |
| 2520 __ lw(T2, FieldAddress(T2, TypeArguments::instantiations_offset())); | 2518 __ lw(T2, FieldAddress(T2, TypeArguments::instantiations_offset())); |
| 2521 __ AddImmediate(T2, Array::data_offset() - kHeapObjectTag); | 2519 __ AddImmediate(T2, Array::data_offset() - kHeapObjectTag); |
| 2522 // The instantiations cache is initialized with Object::zero_array() and is | 2520 // The instantiations cache is initialized with Object::zero_array() and is |
| 2523 // therefore guaranteed to contain kNoInstantiator. No length check needed. | 2521 // therefore guaranteed to contain kNoInstantiator. No length check needed. |
| 2524 Label loop, found, slow_case; | 2522 Label loop, found, slow_case; |
| 2525 __ Bind(&loop); | 2523 __ Bind(&loop); |
| 2526 __ lw(T1, Address(T2, 0 * kWordSize)); // Cached instantiator. | 2524 __ lw(T1, Address(T2, 0 * kWordSize)); // Cached instantiator. |
| 2527 __ beq(T1, T0, &found); | 2525 __ beq(T1, T0, &found); |
| 2528 __ BranchNotEqual( | 2526 __ BranchNotEqual(T1, Immediate(Smi::RawValue(StubCode::kNoInstantiator)), |
| 2529 T1, Immediate(Smi::RawValue(StubCode::kNoInstantiator)), &loop); | 2527 &loop); |
| 2530 __ delay_slot()->addiu(T2, T2, Immediate(2 * kWordSize)); | 2528 __ delay_slot()->addiu(T2, T2, Immediate(2 * kWordSize)); |
| 2531 __ b(&slow_case); | 2529 __ b(&slow_case); |
| 2532 __ Bind(&found); | 2530 __ Bind(&found); |
| 2533 __ lw(T0, Address(T2, 1 * kWordSize)); // Cached instantiated args. | 2531 __ lw(T0, Address(T2, 1 * kWordSize)); // Cached instantiated args. |
| 2534 __ b(&type_arguments_instantiated); | 2532 __ b(&type_arguments_instantiated); |
| 2535 | 2533 |
| 2536 __ Bind(&slow_case); | 2534 __ Bind(&slow_case); |
| 2537 // Instantiate non-null type arguments. | 2535 // Instantiate non-null type arguments. |
| 2538 // A runtime call to instantiate the type arguments is required. | 2536 // A runtime call to instantiate the type arguments is required. |
| 2539 __ addiu(SP, SP, Immediate(-3 * kWordSize)); | 2537 __ addiu(SP, SP, Immediate(-3 * kWordSize)); |
| 2540 __ LoadObject(TMP, Object::null_object()); | 2538 __ LoadObject(TMP, Object::null_object()); |
| 2541 __ sw(TMP, Address(SP, 2 * kWordSize)); // Make room for the result. | 2539 __ sw(TMP, Address(SP, 2 * kWordSize)); // Make room for the result. |
| 2542 __ LoadObject(TMP, type_arguments()); | 2540 __ LoadObject(TMP, type_arguments()); |
| 2543 __ sw(TMP, Address(SP, 1 * kWordSize)); | 2541 __ sw(TMP, Address(SP, 1 * kWordSize)); |
| 2544 // Push instantiator type arguments. | 2542 // Push instantiator type arguments. |
| 2545 __ sw(instantiator_reg, Address(SP, 0 * kWordSize)); | 2543 __ sw(instantiator_reg, Address(SP, 0 * kWordSize)); |
| 2546 | 2544 |
| 2547 compiler->GenerateRuntimeCall(token_pos(), | 2545 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), |
| 2548 deopt_id(), | 2546 kInstantiateTypeArgumentsRuntimeEntry, 2, |
| 2549 kInstantiateTypeArgumentsRuntimeEntry, | |
| 2550 2, | |
| 2551 locs()); | 2547 locs()); |
| 2552 // Pop instantiated type arguments. | 2548 // Pop instantiated type arguments. |
| 2553 __ lw(result_reg, Address(SP, 2 * kWordSize)); | 2549 __ lw(result_reg, Address(SP, 2 * kWordSize)); |
| 2554 // Drop instantiator and uninstantiated type arguments. | 2550 // Drop instantiator and uninstantiated type arguments. |
| 2555 __ addiu(SP, SP, Immediate(3 * kWordSize)); | 2551 __ addiu(SP, SP, Immediate(3 * kWordSize)); |
| 2556 __ Bind(&type_arguments_instantiated); | 2552 __ Bind(&type_arguments_instantiated); |
| 2557 } | 2553 } |
| 2558 | 2554 |
| 2559 | 2555 |
| 2560 LocationSummary* AllocateUninitializedContextInstr::MakeLocationSummary( | 2556 LocationSummary* AllocateUninitializedContextInstr::MakeLocationSummary( |
| 2561 Zone* zone, | 2557 Zone* zone, |
| 2562 bool opt) const { | 2558 bool opt) const { |
| 2563 ASSERT(opt); | 2559 ASSERT(opt); |
| 2564 const intptr_t kNumInputs = 0; | 2560 const intptr_t kNumInputs = 0; |
| 2565 const intptr_t kNumTemps = 3; | 2561 const intptr_t kNumTemps = 3; |
| 2566 LocationSummary* locs = new(zone) LocationSummary( | 2562 LocationSummary* locs = new (zone) LocationSummary( |
| 2567 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); | 2563 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); |
| 2568 locs->set_temp(0, Location::RegisterLocation(T1)); | 2564 locs->set_temp(0, Location::RegisterLocation(T1)); |
| 2569 locs->set_temp(1, Location::RegisterLocation(T2)); | 2565 locs->set_temp(1, Location::RegisterLocation(T2)); |
| 2570 locs->set_temp(2, Location::RegisterLocation(T3)); | 2566 locs->set_temp(2, Location::RegisterLocation(T3)); |
| 2571 locs->set_out(0, Location::RegisterLocation(V0)); | 2567 locs->set_out(0, Location::RegisterLocation(V0)); |
| 2572 return locs; | 2568 return locs; |
| 2573 } | 2569 } |
| 2574 | 2570 |
| 2575 | 2571 |
| 2576 class AllocateContextSlowPath : public SlowPathCode { | 2572 class AllocateContextSlowPath : public SlowPathCode { |
| 2577 public: | 2573 public: |
| 2578 explicit AllocateContextSlowPath( | 2574 explicit AllocateContextSlowPath( |
| 2579 AllocateUninitializedContextInstr* instruction) | 2575 AllocateUninitializedContextInstr* instruction) |
| 2580 : instruction_(instruction) { } | 2576 : instruction_(instruction) {} |
| 2581 | 2577 |
| 2582 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { | 2578 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2583 __ Comment("AllocateContextSlowPath"); | 2579 __ Comment("AllocateContextSlowPath"); |
| 2584 __ Bind(entry_label()); | 2580 __ Bind(entry_label()); |
| 2585 | 2581 |
| 2586 LocationSummary* locs = instruction_->locs(); | 2582 LocationSummary* locs = instruction_->locs(); |
| 2587 locs->live_registers()->Remove(locs->out(0)); | 2583 locs->live_registers()->Remove(locs->out(0)); |
| 2588 | 2584 |
| 2589 compiler->SaveLiveRegisters(locs); | 2585 compiler->SaveLiveRegisters(locs); |
| 2590 | 2586 |
| 2591 __ LoadImmediate(T1, instruction_->num_context_variables()); | 2587 __ LoadImmediate(T1, instruction_->num_context_variables()); |
| 2592 const Code& stub = Code::ZoneHandle( | 2588 const Code& stub = Code::ZoneHandle( |
| 2593 compiler->zone(), StubCode::AllocateContext_entry()->code()); | 2589 compiler->zone(), StubCode::AllocateContext_entry()->code()); |
| 2594 compiler->AddStubCallTarget(stub); | 2590 compiler->AddStubCallTarget(stub); |
| 2595 compiler->GenerateCall(instruction_->token_pos(), | 2591 compiler->GenerateCall(instruction_->token_pos(), |
| 2596 *StubCode::AllocateContext_entry(), | 2592 *StubCode::AllocateContext_entry(), |
| 2597 RawPcDescriptors::kOther, | 2593 RawPcDescriptors::kOther, locs); |
| 2598 locs); | |
| 2599 ASSERT(instruction_->locs()->out(0).reg() == V0); | 2594 ASSERT(instruction_->locs()->out(0).reg() == V0); |
| 2600 compiler->RestoreLiveRegisters(instruction_->locs()); | 2595 compiler->RestoreLiveRegisters(instruction_->locs()); |
| 2601 __ b(exit_label()); | 2596 __ b(exit_label()); |
| 2602 } | 2597 } |
| 2603 | 2598 |
| 2604 private: | 2599 private: |
| 2605 AllocateUninitializedContextInstr* instruction_; | 2600 AllocateUninitializedContextInstr* instruction_; |
| 2606 }; | 2601 }; |
| 2607 | 2602 |
| 2608 | 2603 |
| 2609 void AllocateUninitializedContextInstr::EmitNativeCode( | 2604 void AllocateUninitializedContextInstr::EmitNativeCode( |
| 2610 FlowGraphCompiler* compiler) { | 2605 FlowGraphCompiler* compiler) { |
| 2611 Register temp0 = locs()->temp(0).reg(); | 2606 Register temp0 = locs()->temp(0).reg(); |
| 2612 Register temp1 = locs()->temp(1).reg(); | 2607 Register temp1 = locs()->temp(1).reg(); |
| 2613 Register temp2 = locs()->temp(2).reg(); | 2608 Register temp2 = locs()->temp(2).reg(); |
| 2614 Register result = locs()->out(0).reg(); | 2609 Register result = locs()->out(0).reg(); |
| 2615 // Try allocate the object. | 2610 // Try allocate the object. |
| 2616 AllocateContextSlowPath* slow_path = new AllocateContextSlowPath(this); | 2611 AllocateContextSlowPath* slow_path = new AllocateContextSlowPath(this); |
| 2617 compiler->AddSlowPathCode(slow_path); | 2612 compiler->AddSlowPathCode(slow_path); |
| 2618 intptr_t instance_size = Context::InstanceSize(num_context_variables()); | 2613 intptr_t instance_size = Context::InstanceSize(num_context_variables()); |
| 2619 | 2614 |
| 2620 __ TryAllocateArray(kContextCid, instance_size, slow_path->entry_label(), | 2615 __ TryAllocateArray(kContextCid, instance_size, slow_path->entry_label(), |
| 2621 result, // instance | 2616 result, // instance |
| 2622 temp0, | 2617 temp0, temp1, temp2); |
| 2623 temp1, | |
| 2624 temp2); | |
| 2625 | 2618 |
| 2626 // Setup up number of context variables field. | 2619 // Setup up number of context variables field. |
| 2627 __ LoadImmediate(temp0, num_context_variables()); | 2620 __ LoadImmediate(temp0, num_context_variables()); |
| 2628 __ sw(temp0, FieldAddress(result, Context::num_variables_offset())); | 2621 __ sw(temp0, FieldAddress(result, Context::num_variables_offset())); |
| 2629 | 2622 |
| 2630 __ Bind(slow_path->exit_label()); | 2623 __ Bind(slow_path->exit_label()); |
| 2631 } | 2624 } |
| 2632 | 2625 |
| 2633 | 2626 |
| 2634 LocationSummary* AllocateContextInstr::MakeLocationSummary(Zone* zone, | 2627 LocationSummary* AllocateContextInstr::MakeLocationSummary(Zone* zone, |
| 2635 bool opt) const { | 2628 bool opt) const { |
| 2636 const intptr_t kNumInputs = 0; | 2629 const intptr_t kNumInputs = 0; |
| 2637 const intptr_t kNumTemps = 1; | 2630 const intptr_t kNumTemps = 1; |
| 2638 LocationSummary* locs = new(zone) LocationSummary( | 2631 LocationSummary* locs = new (zone) |
| 2639 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 2632 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
| 2640 locs->set_temp(0, Location::RegisterLocation(T1)); | 2633 locs->set_temp(0, Location::RegisterLocation(T1)); |
| 2641 locs->set_out(0, Location::RegisterLocation(V0)); | 2634 locs->set_out(0, Location::RegisterLocation(V0)); |
| 2642 return locs; | 2635 return locs; |
| 2643 } | 2636 } |
| 2644 | 2637 |
| 2645 | 2638 |
| 2646 void AllocateContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2639 void AllocateContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2647 ASSERT(locs()->temp(0).reg() == T1); | 2640 ASSERT(locs()->temp(0).reg() == T1); |
| 2648 ASSERT(locs()->out(0).reg() == V0); | 2641 ASSERT(locs()->out(0).reg() == V0); |
| 2649 | 2642 |
| 2650 __ Comment("AllocateContextInstr"); | 2643 __ Comment("AllocateContextInstr"); |
| 2651 __ LoadImmediate(T1, num_context_variables()); | 2644 __ LoadImmediate(T1, num_context_variables()); |
| 2652 compiler->GenerateCall(token_pos(), | 2645 compiler->GenerateCall(token_pos(), *StubCode::AllocateContext_entry(), |
| 2653 *StubCode::AllocateContext_entry(), | 2646 RawPcDescriptors::kOther, locs()); |
| 2654 RawPcDescriptors::kOther, | |
| 2655 locs()); | |
| 2656 } | 2647 } |
| 2657 | 2648 |
| 2658 | 2649 |
| 2659 LocationSummary* InitStaticFieldInstr::MakeLocationSummary(Zone* zone, | 2650 LocationSummary* InitStaticFieldInstr::MakeLocationSummary(Zone* zone, |
| 2660 bool opt) const { | 2651 bool opt) const { |
| 2661 const intptr_t kNumInputs = 1; | 2652 const intptr_t kNumInputs = 1; |
| 2662 const intptr_t kNumTemps = 1; | 2653 const intptr_t kNumTemps = 1; |
| 2663 LocationSummary* locs = new(zone) LocationSummary( | 2654 LocationSummary* locs = new (zone) |
| 2664 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 2655 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
| 2665 locs->set_in(0, Location::RegisterLocation(T0)); | 2656 locs->set_in(0, Location::RegisterLocation(T0)); |
| 2666 locs->set_temp(0, Location::RegisterLocation(T1)); | 2657 locs->set_temp(0, Location::RegisterLocation(T1)); |
| 2667 return locs; | 2658 return locs; |
| 2668 } | 2659 } |
| 2669 | 2660 |
| 2670 | 2661 |
| 2671 void InitStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2662 void InitStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2672 Register field = locs()->in(0).reg(); | 2663 Register field = locs()->in(0).reg(); |
| 2673 Register temp = locs()->temp(0).reg(); | 2664 Register temp = locs()->temp(0).reg(); |
| 2674 | 2665 |
| 2675 Label call_runtime, no_call; | 2666 Label call_runtime, no_call; |
| 2676 __ Comment("InitStaticFieldInstr"); | 2667 __ Comment("InitStaticFieldInstr"); |
| 2677 | 2668 |
| 2678 __ lw(temp, FieldAddress(field, Field::static_value_offset())); | 2669 __ lw(temp, FieldAddress(field, Field::static_value_offset())); |
| 2679 __ BranchEqual(temp, Object::sentinel(), &call_runtime); | 2670 __ BranchEqual(temp, Object::sentinel(), &call_runtime); |
| 2680 __ BranchNotEqual(temp, Object::transition_sentinel(), &no_call); | 2671 __ BranchNotEqual(temp, Object::transition_sentinel(), &no_call); |
| 2681 | 2672 |
| 2682 __ Bind(&call_runtime); | 2673 __ Bind(&call_runtime); |
| 2683 __ addiu(SP, SP, Immediate(-2 * kWordSize)); | 2674 __ addiu(SP, SP, Immediate(-2 * kWordSize)); |
| 2684 __ LoadObject(TMP, Object::null_object()); | 2675 __ LoadObject(TMP, Object::null_object()); |
| 2685 __ sw(TMP, Address(SP, 1 * kWordSize)); // Make room for (unused) result. | 2676 __ sw(TMP, Address(SP, 1 * kWordSize)); // Make room for (unused) result. |
| 2686 __ sw(field, Address(SP, 0 * kWordSize)); | 2677 __ sw(field, Address(SP, 0 * kWordSize)); |
| 2687 | 2678 |
| 2688 compiler->GenerateRuntimeCall(token_pos(), | 2679 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), |
| 2689 deopt_id(), | 2680 kInitStaticFieldRuntimeEntry, 1, locs()); |
| 2690 kInitStaticFieldRuntimeEntry, | |
| 2691 1, | |
| 2692 locs()); | |
| 2693 | 2681 |
| 2694 __ addiu(SP, SP, Immediate(2 * kWordSize)); // Purge argument and result. | 2682 __ addiu(SP, SP, Immediate(2 * kWordSize)); // Purge argument and result. |
| 2695 | 2683 |
| 2696 __ Bind(&no_call); | 2684 __ Bind(&no_call); |
| 2697 } | 2685 } |
| 2698 | 2686 |
| 2699 | 2687 |
| 2700 LocationSummary* CloneContextInstr::MakeLocationSummary(Zone* zone, | 2688 LocationSummary* CloneContextInstr::MakeLocationSummary(Zone* zone, |
| 2701 bool opt) const { | 2689 bool opt) const { |
| 2702 const intptr_t kNumInputs = 1; | 2690 const intptr_t kNumInputs = 1; |
| 2703 const intptr_t kNumTemps = 0; | 2691 const intptr_t kNumTemps = 0; |
| 2704 LocationSummary* locs = new(zone) LocationSummary( | 2692 LocationSummary* locs = new (zone) |
| 2705 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 2693 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
| 2706 locs->set_in(0, Location::RegisterLocation(T0)); | 2694 locs->set_in(0, Location::RegisterLocation(T0)); |
| 2707 locs->set_out(0, Location::RegisterLocation(T0)); | 2695 locs->set_out(0, Location::RegisterLocation(T0)); |
| 2708 return locs; | 2696 return locs; |
| 2709 } | 2697 } |
| 2710 | 2698 |
| 2711 | 2699 |
| 2712 void CloneContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2700 void CloneContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2713 Register context_value = locs()->in(0).reg(); | 2701 Register context_value = locs()->in(0).reg(); |
| 2714 Register result = locs()->out(0).reg(); | 2702 Register result = locs()->out(0).reg(); |
| 2715 | 2703 |
| 2716 __ Comment("CloneContextInstr"); | 2704 __ Comment("CloneContextInstr"); |
| 2717 | 2705 |
| 2718 __ addiu(SP, SP, Immediate(-2 * kWordSize)); | 2706 __ addiu(SP, SP, Immediate(-2 * kWordSize)); |
| 2719 __ LoadObject(TMP, Object::null_object()); // Make room for the result. | 2707 __ LoadObject(TMP, Object::null_object()); // Make room for the result. |
| 2720 __ sw(TMP, Address(SP, 1 * kWordSize)); | 2708 __ sw(TMP, Address(SP, 1 * kWordSize)); |
| 2721 __ sw(context_value, Address(SP, 0 * kWordSize)); | 2709 __ sw(context_value, Address(SP, 0 * kWordSize)); |
| 2722 | 2710 |
| 2723 compiler->GenerateRuntimeCall(token_pos(), | 2711 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), |
| 2724 deopt_id(), | 2712 kCloneContextRuntimeEntry, 1, locs()); |
| 2725 kCloneContextRuntimeEntry, | |
| 2726 1, | |
| 2727 locs()); | |
| 2728 __ lw(result, Address(SP, 1 * kWordSize)); // Get result (cloned context). | 2713 __ lw(result, Address(SP, 1 * kWordSize)); // Get result (cloned context). |
| 2729 __ addiu(SP, SP, Immediate(2 * kWordSize)); | 2714 __ addiu(SP, SP, Immediate(2 * kWordSize)); |
| 2730 } | 2715 } |
| 2731 | 2716 |
| 2732 | 2717 |
| 2733 LocationSummary* CatchBlockEntryInstr::MakeLocationSummary(Zone* zone, | 2718 LocationSummary* CatchBlockEntryInstr::MakeLocationSummary(Zone* zone, |
| 2734 bool opt) const { | 2719 bool opt) const { |
| 2735 UNREACHABLE(); | 2720 UNREACHABLE(); |
| 2736 return NULL; | 2721 return NULL; |
| 2737 } | 2722 } |
| 2738 | 2723 |
| 2739 | 2724 |
| 2740 void CatchBlockEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2725 void CatchBlockEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2741 __ Bind(compiler->GetJumpLabel(this)); | 2726 __ Bind(compiler->GetJumpLabel(this)); |
| 2742 compiler->AddExceptionHandler(catch_try_index(), | 2727 compiler->AddExceptionHandler(catch_try_index(), try_index(), |
| 2743 try_index(), | |
| 2744 compiler->assembler()->CodeSize(), | 2728 compiler->assembler()->CodeSize(), |
| 2745 catch_handler_types_, | 2729 catch_handler_types_, needs_stacktrace()); |
| 2746 needs_stacktrace()); | |
| 2747 // On lazy deoptimization we patch the optimized code here to enter the | 2730 // On lazy deoptimization we patch the optimized code here to enter the |
| 2748 // deoptimization stub. | 2731 // deoptimization stub. |
| 2749 const intptr_t deopt_id = Thread::ToDeoptAfter(GetDeoptId()); | 2732 const intptr_t deopt_id = Thread::ToDeoptAfter(GetDeoptId()); |
| 2750 if (compiler->is_optimizing()) { | 2733 if (compiler->is_optimizing()) { |
| 2751 compiler->AddDeoptIndexAtCall(deopt_id); | 2734 compiler->AddDeoptIndexAtCall(deopt_id); |
| 2752 } else { | 2735 } else { |
| 2753 compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt, | 2736 compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt, deopt_id, |
| 2754 deopt_id, | |
| 2755 TokenPosition::kNoSource); | 2737 TokenPosition::kNoSource); |
| 2756 } | 2738 } |
| 2757 if (HasParallelMove()) { | 2739 if (HasParallelMove()) { |
| 2758 compiler->parallel_move_resolver()->EmitNativeCode(parallel_move()); | 2740 compiler->parallel_move_resolver()->EmitNativeCode(parallel_move()); |
| 2759 } | 2741 } |
| 2760 // Restore SP from FP as we are coming from a throw and the code for | 2742 // Restore SP from FP as we are coming from a throw and the code for |
| 2761 // popping arguments has not been run. | 2743 // popping arguments has not been run. |
| 2762 const intptr_t fp_sp_dist = | 2744 const intptr_t fp_sp_dist = |
| 2763 (kFirstLocalSlotFromFp + 1 - compiler->StackSize()) * kWordSize; | 2745 (kFirstLocalSlotFromFp + 1 - compiler->StackSize()) * kWordSize; |
| 2764 ASSERT(fp_sp_dist <= 0); | 2746 ASSERT(fp_sp_dist <= 0); |
| 2765 __ AddImmediate(SP, FP, fp_sp_dist); | 2747 __ AddImmediate(SP, FP, fp_sp_dist); |
| 2766 | 2748 |
| 2767 // Restore stack and initialize the two exception variables: | 2749 // Restore stack and initialize the two exception variables: |
| 2768 // exception and stack trace variables. | 2750 // exception and stack trace variables. |
| 2769 __ StoreToOffset(kExceptionObjectReg, | 2751 __ StoreToOffset(kExceptionObjectReg, FP, |
| 2770 FP, exception_var().index() * kWordSize); | 2752 exception_var().index() * kWordSize); |
| 2771 __ StoreToOffset(kStackTraceObjectReg, | 2753 __ StoreToOffset(kStackTraceObjectReg, FP, |
| 2772 FP, stacktrace_var().index() * kWordSize); | 2754 stacktrace_var().index() * kWordSize); |
| 2773 } | 2755 } |
| 2774 | 2756 |
| 2775 | 2757 |
| 2776 LocationSummary* CheckStackOverflowInstr::MakeLocationSummary(Zone* zone, | 2758 LocationSummary* CheckStackOverflowInstr::MakeLocationSummary(Zone* zone, |
| 2777 bool opt) const { | 2759 bool opt) const { |
| 2778 const intptr_t kNumInputs = 0; | 2760 const intptr_t kNumInputs = 0; |
| 2779 const intptr_t kNumTemps = 1; | 2761 const intptr_t kNumTemps = 1; |
| 2780 LocationSummary* summary = new(zone) LocationSummary( | 2762 LocationSummary* summary = new (zone) LocationSummary( |
| 2781 zone, kNumInputs, | 2763 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); |
| 2782 kNumTemps, | |
| 2783 LocationSummary::kCallOnSlowPath); | |
| 2784 summary->set_temp(0, Location::RequiresRegister()); | 2764 summary->set_temp(0, Location::RequiresRegister()); |
| 2785 return summary; | 2765 return summary; |
| 2786 } | 2766 } |
| 2787 | 2767 |
| 2788 | 2768 |
| 2789 class CheckStackOverflowSlowPath : public SlowPathCode { | 2769 class CheckStackOverflowSlowPath : public SlowPathCode { |
| 2790 public: | 2770 public: |
| 2791 explicit CheckStackOverflowSlowPath(CheckStackOverflowInstr* instruction) | 2771 explicit CheckStackOverflowSlowPath(CheckStackOverflowInstr* instruction) |
| 2792 : instruction_(instruction) { } | 2772 : instruction_(instruction) {} |
| 2793 | 2773 |
| 2794 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { | 2774 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2795 if (FLAG_use_osr && osr_entry_label()->IsLinked()) { | 2775 if (FLAG_use_osr && osr_entry_label()->IsLinked()) { |
| 2796 Register value = instruction_->locs()->temp(0).reg(); | 2776 Register value = instruction_->locs()->temp(0).reg(); |
| 2797 __ Comment("CheckStackOverflowSlowPathOsr"); | 2777 __ Comment("CheckStackOverflowSlowPathOsr"); |
| 2798 __ Bind(osr_entry_label()); | 2778 __ Bind(osr_entry_label()); |
| 2799 __ LoadImmediate(value, Thread::kOsrRequest); | 2779 __ LoadImmediate(value, Thread::kOsrRequest); |
| 2800 __ sw(value, Address(THR, Thread::stack_overflow_flags_offset())); | 2780 __ sw(value, Address(THR, Thread::stack_overflow_flags_offset())); |
| 2801 } | 2781 } |
| 2802 __ Comment("CheckStackOverflowSlowPath"); | 2782 __ Comment("CheckStackOverflowSlowPath"); |
| 2803 __ Bind(entry_label()); | 2783 __ Bind(entry_label()); |
| 2804 compiler->SaveLiveRegisters(instruction_->locs()); | 2784 compiler->SaveLiveRegisters(instruction_->locs()); |
| 2805 // pending_deoptimization_env_ is needed to generate a runtime call that | 2785 // pending_deoptimization_env_ is needed to generate a runtime call that |
| 2806 // may throw an exception. | 2786 // may throw an exception. |
| 2807 ASSERT(compiler->pending_deoptimization_env_ == NULL); | 2787 ASSERT(compiler->pending_deoptimization_env_ == NULL); |
| 2808 Environment* env = compiler->SlowPathEnvironmentFor(instruction_); | 2788 Environment* env = compiler->SlowPathEnvironmentFor(instruction_); |
| 2809 compiler->pending_deoptimization_env_ = env; | 2789 compiler->pending_deoptimization_env_ = env; |
| 2810 compiler->GenerateRuntimeCall(instruction_->token_pos(), | 2790 compiler->GenerateRuntimeCall( |
| 2811 instruction_->deopt_id(), | 2791 instruction_->token_pos(), instruction_->deopt_id(), |
| 2812 kStackOverflowRuntimeEntry, | 2792 kStackOverflowRuntimeEntry, 0, instruction_->locs()); |
| 2813 0, | |
| 2814 instruction_->locs()); | |
| 2815 | 2793 |
| 2816 if (FLAG_use_osr && !compiler->is_optimizing() && instruction_->in_loop()) { | 2794 if (FLAG_use_osr && !compiler->is_optimizing() && instruction_->in_loop()) { |
| 2817 // In unoptimized code, record loop stack checks as possible OSR entries. | 2795 // In unoptimized code, record loop stack checks as possible OSR entries. |
| 2818 compiler->AddCurrentDescriptor(RawPcDescriptors::kOsrEntry, | 2796 compiler->AddCurrentDescriptor(RawPcDescriptors::kOsrEntry, |
| 2819 instruction_->deopt_id(), | 2797 instruction_->deopt_id(), |
| 2820 TokenPosition::kNoSource); | 2798 TokenPosition::kNoSource); |
| 2821 } | 2799 } |
| 2822 compiler->pending_deoptimization_env_ = NULL; | 2800 compiler->pending_deoptimization_env_ = NULL; |
| 2823 compiler->RestoreLiveRegisters(instruction_->locs()); | 2801 compiler->RestoreLiveRegisters(instruction_->locs()); |
| 2824 __ b(exit_label()); | 2802 __ b(exit_label()); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 2844 __ BranchUnsignedLessEqual(SP, CMPRES1, slow_path->entry_label()); | 2822 __ BranchUnsignedLessEqual(SP, CMPRES1, slow_path->entry_label()); |
| 2845 if (compiler->CanOSRFunction() && in_loop()) { | 2823 if (compiler->CanOSRFunction() && in_loop()) { |
| 2846 Register temp = locs()->temp(0).reg(); | 2824 Register temp = locs()->temp(0).reg(); |
| 2847 // In unoptimized code check the usage counter to trigger OSR at loop | 2825 // In unoptimized code check the usage counter to trigger OSR at loop |
| 2848 // stack checks. Use progressively higher thresholds for more deeply | 2826 // stack checks. Use progressively higher thresholds for more deeply |
| 2849 // nested loops to attempt to hit outer loops with OSR when possible. | 2827 // nested loops to attempt to hit outer loops with OSR when possible. |
| 2850 __ LoadObject(temp, compiler->parsed_function().function()); | 2828 __ LoadObject(temp, compiler->parsed_function().function()); |
| 2851 intptr_t threshold = | 2829 intptr_t threshold = |
| 2852 FLAG_optimization_counter_threshold * (loop_depth() + 1); | 2830 FLAG_optimization_counter_threshold * (loop_depth() + 1); |
| 2853 __ lw(temp, FieldAddress(temp, Function::usage_counter_offset())); | 2831 __ lw(temp, FieldAddress(temp, Function::usage_counter_offset())); |
| 2854 __ BranchSignedGreaterEqual( | 2832 __ BranchSignedGreaterEqual(temp, Immediate(threshold), |
| 2855 temp, Immediate(threshold), slow_path->osr_entry_label()); | 2833 slow_path->osr_entry_label()); |
| 2856 } | 2834 } |
| 2857 if (compiler->ForceSlowPathForStackOverflow()) { | 2835 if (compiler->ForceSlowPathForStackOverflow()) { |
| 2858 __ b(slow_path->entry_label()); | 2836 __ b(slow_path->entry_label()); |
| 2859 } | 2837 } |
| 2860 __ Bind(slow_path->exit_label()); | 2838 __ Bind(slow_path->exit_label()); |
| 2861 } | 2839 } |
| 2862 | 2840 |
| 2863 | 2841 |
| 2864 static void EmitSmiShiftLeft(FlowGraphCompiler* compiler, | 2842 static void EmitSmiShiftLeft(FlowGraphCompiler* compiler, |
| 2865 BinarySmiOpInstr* shift_left) { | 2843 BinarySmiOpInstr* shift_left) { |
| 2866 const LocationSummary& locs = *shift_left->locs(); | 2844 const LocationSummary& locs = *shift_left->locs(); |
| 2867 Register left = locs.in(0).reg(); | 2845 Register left = locs.in(0).reg(); |
| 2868 Register result = locs.out(0).reg(); | 2846 Register result = locs.out(0).reg(); |
| 2869 Label* deopt = shift_left->CanDeoptimize() ? | 2847 Label* deopt = shift_left->CanDeoptimize() |
| 2870 compiler->AddDeoptStub(shift_left->deopt_id(), ICData::kDeoptBinarySmiOp) | 2848 ? compiler->AddDeoptStub(shift_left->deopt_id(), |
| 2871 : NULL; | 2849 ICData::kDeoptBinarySmiOp) |
| 2850 : NULL; |
| 2872 | 2851 |
| 2873 __ Comment("EmitSmiShiftLeft"); | 2852 __ Comment("EmitSmiShiftLeft"); |
| 2874 | 2853 |
| 2875 if (locs.in(1).IsConstant()) { | 2854 if (locs.in(1).IsConstant()) { |
| 2876 const Object& constant = locs.in(1).constant(); | 2855 const Object& constant = locs.in(1).constant(); |
| 2877 ASSERT(constant.IsSmi()); | 2856 ASSERT(constant.IsSmi()); |
| 2878 // Immediate shift operation takes 5 bits for the count. | 2857 // Immediate shift operation takes 5 bits for the count. |
| 2879 const intptr_t kCountLimit = 0x1F; | 2858 const intptr_t kCountLimit = 0x1F; |
| 2880 const intptr_t value = Smi::Cast(constant).Value(); | 2859 const intptr_t value = Smi::Cast(constant).Value(); |
| 2881 ASSERT((0 < value) && (value < kCountLimit)); | 2860 ASSERT((0 < value) && (value < kCountLimit)); |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2923 if (!shift_left->can_overflow()) { | 2902 if (!shift_left->can_overflow()) { |
| 2924 if (right_needs_check) { | 2903 if (right_needs_check) { |
| 2925 const bool right_may_be_negative = | 2904 const bool right_may_be_negative = |
| 2926 (right_range == NULL) || !right_range->IsPositive(); | 2905 (right_range == NULL) || !right_range->IsPositive(); |
| 2927 if (right_may_be_negative) { | 2906 if (right_may_be_negative) { |
| 2928 ASSERT(shift_left->CanDeoptimize()); | 2907 ASSERT(shift_left->CanDeoptimize()); |
| 2929 __ bltz(right, deopt); | 2908 __ bltz(right, deopt); |
| 2930 } | 2909 } |
| 2931 Label done, is_not_zero; | 2910 Label done, is_not_zero; |
| 2932 | 2911 |
| 2933 __ sltiu(CMPRES1, | 2912 __ sltiu(CMPRES1, right, |
| 2934 right, Immediate(reinterpret_cast<int32_t>(Smi::New(Smi::kBits)))); | 2913 Immediate(reinterpret_cast<int32_t>(Smi::New(Smi::kBits)))); |
| 2935 __ movz(result, ZR, CMPRES1); // result = right >= kBits ? 0 : result. | 2914 __ movz(result, ZR, CMPRES1); // result = right >= kBits ? 0 : result. |
| 2936 __ sra(TMP, right, kSmiTagSize); | 2915 __ sra(TMP, right, kSmiTagSize); |
| 2937 __ sllv(TMP, left, TMP); | 2916 __ sllv(TMP, left, TMP); |
| 2938 // result = right < kBits ? left << right : result. | 2917 // result = right < kBits ? left << right : result. |
| 2939 __ movn(result, TMP, CMPRES1); | 2918 __ movn(result, TMP, CMPRES1); |
| 2940 } else { | 2919 } else { |
| 2941 __ sra(TMP, right, kSmiTagSize); | 2920 __ sra(TMP, right, kSmiTagSize); |
| 2942 __ sllv(result, left, TMP); | 2921 __ sllv(result, left, TMP); |
| 2943 } | 2922 } |
| 2944 } else { | 2923 } else { |
| (...skipping 13 matching lines...) Expand all Loading... |
| 2958 __ bne(CMPRES1, left, deopt); // Overflow. | 2937 __ bne(CMPRES1, left, deopt); // Overflow. |
| 2959 // Shift for result now we know there is no overflow. | 2938 // Shift for result now we know there is no overflow. |
| 2960 __ sllv(result, left, temp); | 2939 __ sllv(result, left, temp); |
| 2961 } | 2940 } |
| 2962 } | 2941 } |
| 2963 | 2942 |
| 2964 | 2943 |
| 2965 class CheckedSmiSlowPath : public SlowPathCode { | 2944 class CheckedSmiSlowPath : public SlowPathCode { |
| 2966 public: | 2945 public: |
| 2967 CheckedSmiSlowPath(CheckedSmiOpInstr* instruction, intptr_t try_index) | 2946 CheckedSmiSlowPath(CheckedSmiOpInstr* instruction, intptr_t try_index) |
| 2968 : instruction_(instruction), try_index_(try_index) { } | 2947 : instruction_(instruction), try_index_(try_index) {} |
| 2969 | 2948 |
| 2970 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { | 2949 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2971 if (Assembler::EmittingComments()) { | 2950 if (Assembler::EmittingComments()) { |
| 2972 __ Comment("slow path smi operation"); | 2951 __ Comment("slow path smi operation"); |
| 2973 } | 2952 } |
| 2974 __ Bind(entry_label()); | 2953 __ Bind(entry_label()); |
| 2975 LocationSummary* locs = instruction_->locs(); | 2954 LocationSummary* locs = instruction_->locs(); |
| 2976 Register result = locs->out(0).reg(); | 2955 Register result = locs->out(0).reg(); |
| 2977 locs->live_registers()->Remove(Location::RegisterLocation(result)); | 2956 locs->live_registers()->Remove(Location::RegisterLocation(result)); |
| 2978 | 2957 |
| 2979 compiler->SaveLiveRegisters(locs); | 2958 compiler->SaveLiveRegisters(locs); |
| 2980 __ Push(locs->in(0).reg()); | 2959 __ Push(locs->in(0).reg()); |
| 2981 __ Push(locs->in(1).reg()); | 2960 __ Push(locs->in(1).reg()); |
| 2982 compiler->EmitMegamorphicInstanceCall( | 2961 compiler->EmitMegamorphicInstanceCall( |
| 2983 *instruction_->call()->ic_data(), | 2962 *instruction_->call()->ic_data(), instruction_->call()->ArgumentCount(), |
| 2984 instruction_->call()->ArgumentCount(), | 2963 instruction_->call()->deopt_id(), instruction_->call()->token_pos(), |
| 2985 instruction_->call()->deopt_id(), | 2964 locs, try_index_, |
| 2986 instruction_->call()->token_pos(), | |
| 2987 locs, | |
| 2988 try_index_, | |
| 2989 /* slow_path_argument_count = */ 2); | 2965 /* slow_path_argument_count = */ 2); |
| 2990 __ mov(result, V0); | 2966 __ mov(result, V0); |
| 2991 compiler->RestoreLiveRegisters(locs); | 2967 compiler->RestoreLiveRegisters(locs); |
| 2992 __ b(exit_label()); | 2968 __ b(exit_label()); |
| 2993 } | 2969 } |
| 2994 | 2970 |
| 2995 private: | 2971 private: |
| 2996 CheckedSmiOpInstr* instruction_; | 2972 CheckedSmiOpInstr* instruction_; |
| 2997 intptr_t try_index_; | 2973 intptr_t try_index_; |
| 2998 }; | 2974 }; |
| 2999 | 2975 |
| 3000 | 2976 |
| 3001 LocationSummary* CheckedSmiOpInstr::MakeLocationSummary(Zone* zone, | 2977 LocationSummary* CheckedSmiOpInstr::MakeLocationSummary(Zone* zone, |
| 3002 bool opt) const { | 2978 bool opt) const { |
| 3003 const intptr_t kNumInputs = 2; | 2979 const intptr_t kNumInputs = 2; |
| 3004 const intptr_t kNumTemps = 0; | 2980 const intptr_t kNumTemps = 0; |
| 3005 LocationSummary* summary = new(zone) LocationSummary( | 2981 LocationSummary* summary = new (zone) LocationSummary( |
| 3006 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); | 2982 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); |
| 3007 summary->set_in(0, Location::RequiresRegister()); | 2983 summary->set_in(0, Location::RequiresRegister()); |
| 3008 summary->set_in(1, Location::RequiresRegister()); | 2984 summary->set_in(1, Location::RequiresRegister()); |
| 3009 summary->set_out(0, Location::RequiresRegister()); | 2985 summary->set_out(0, Location::RequiresRegister()); |
| 3010 return summary; | 2986 return summary; |
| 3011 } | 2987 } |
| 3012 | 2988 |
| 3013 | 2989 |
| 3014 void CheckedSmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2990 void CheckedSmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3015 CheckedSmiSlowPath* slow_path = | 2991 CheckedSmiSlowPath* slow_path = |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3072 | 3048 |
| 3073 class CheckedSmiComparisonSlowPath : public SlowPathCode { | 3049 class CheckedSmiComparisonSlowPath : public SlowPathCode { |
| 3074 public: | 3050 public: |
| 3075 CheckedSmiComparisonSlowPath(CheckedSmiComparisonInstr* instruction, | 3051 CheckedSmiComparisonSlowPath(CheckedSmiComparisonInstr* instruction, |
| 3076 intptr_t try_index, | 3052 intptr_t try_index, |
| 3077 BranchLabels labels, | 3053 BranchLabels labels, |
| 3078 bool merged) | 3054 bool merged) |
| 3079 : instruction_(instruction), | 3055 : instruction_(instruction), |
| 3080 try_index_(try_index), | 3056 try_index_(try_index), |
| 3081 labels_(labels), | 3057 labels_(labels), |
| 3082 merged_(merged) { } | 3058 merged_(merged) {} |
| 3083 | 3059 |
| 3084 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { | 3060 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3085 if (Assembler::EmittingComments()) { | 3061 if (Assembler::EmittingComments()) { |
| 3086 __ Comment("slow path smi operation"); | 3062 __ Comment("slow path smi operation"); |
| 3087 } | 3063 } |
| 3088 __ Bind(entry_label()); | 3064 __ Bind(entry_label()); |
| 3089 LocationSummary* locs = instruction_->locs(); | 3065 LocationSummary* locs = instruction_->locs(); |
| 3090 Register result = merged_ ? locs->temp(0).reg() : locs->out(0).reg(); | 3066 Register result = merged_ ? locs->temp(0).reg() : locs->out(0).reg(); |
| 3091 locs->live_registers()->Remove(Location::RegisterLocation(result)); | 3067 locs->live_registers()->Remove(Location::RegisterLocation(result)); |
| 3092 | 3068 |
| 3093 compiler->SaveLiveRegisters(locs); | 3069 compiler->SaveLiveRegisters(locs); |
| 3094 __ Push(locs->in(0).reg()); | 3070 __ Push(locs->in(0).reg()); |
| 3095 __ Push(locs->in(1).reg()); | 3071 __ Push(locs->in(1).reg()); |
| 3096 compiler->EmitMegamorphicInstanceCall( | 3072 compiler->EmitMegamorphicInstanceCall( |
| 3097 *instruction_->call()->ic_data(), | 3073 *instruction_->call()->ic_data(), instruction_->call()->ArgumentCount(), |
| 3098 instruction_->call()->ArgumentCount(), | 3074 instruction_->call()->deopt_id(), instruction_->call()->token_pos(), |
| 3099 instruction_->call()->deopt_id(), | 3075 locs, try_index_, |
| 3100 instruction_->call()->token_pos(), | |
| 3101 locs, | |
| 3102 try_index_, | |
| 3103 /* slow_path_argument_count = */ 2); | 3076 /* slow_path_argument_count = */ 2); |
| 3104 __ mov(result, V0); | 3077 __ mov(result, V0); |
| 3105 compiler->RestoreLiveRegisters(locs); | 3078 compiler->RestoreLiveRegisters(locs); |
| 3106 if (merged_) { | 3079 if (merged_) { |
| 3107 __ BranchEqual(result, Bool::True(), | 3080 __ BranchEqual(result, Bool::True(), instruction_->is_negated() |
| 3108 instruction_->is_negated() ? labels_.false_label : labels_.true_label); | 3081 ? labels_.false_label |
| 3109 __ b(instruction_->is_negated() | 3082 : labels_.true_label); |
| 3110 ? labels_.true_label : labels_.false_label); | 3083 __ b(instruction_->is_negated() ? labels_.true_label |
| 3084 : labels_.false_label); |
| 3111 } else { | 3085 } else { |
| 3112 __ b(exit_label()); | 3086 __ b(exit_label()); |
| 3113 } | 3087 } |
| 3114 } | 3088 } |
| 3115 | 3089 |
| 3116 private: | 3090 private: |
| 3117 CheckedSmiComparisonInstr* instruction_; | 3091 CheckedSmiComparisonInstr* instruction_; |
| 3118 intptr_t try_index_; | 3092 intptr_t try_index_; |
| 3119 BranchLabels labels_; | 3093 BranchLabels labels_; |
| 3120 bool merged_; | 3094 bool merged_; |
| 3121 }; | 3095 }; |
| 3122 | 3096 |
| 3123 | 3097 |
| 3124 LocationSummary* CheckedSmiComparisonInstr::MakeLocationSummary( | 3098 LocationSummary* CheckedSmiComparisonInstr::MakeLocationSummary( |
| 3125 Zone* zone, bool opt) const { | 3099 Zone* zone, |
| 3100 bool opt) const { |
| 3126 const intptr_t kNumInputs = 2; | 3101 const intptr_t kNumInputs = 2; |
| 3127 const intptr_t kNumTemps = 1; | 3102 const intptr_t kNumTemps = 1; |
| 3128 LocationSummary* summary = new(zone) LocationSummary( | 3103 LocationSummary* summary = new (zone) LocationSummary( |
| 3129 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); | 3104 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); |
| 3130 summary->set_in(0, Location::RequiresRegister()); | 3105 summary->set_in(0, Location::RequiresRegister()); |
| 3131 summary->set_in(1, Location::RequiresRegister()); | 3106 summary->set_in(1, Location::RequiresRegister()); |
| 3132 summary->set_temp(0, Location::RequiresRegister()); | 3107 summary->set_temp(0, Location::RequiresRegister()); |
| 3133 summary->set_out(0, Location::RequiresRegister()); | 3108 summary->set_out(0, Location::RequiresRegister()); |
| 3134 return summary; | 3109 return summary; |
| 3135 } | 3110 } |
| 3136 | 3111 |
| 3137 | 3112 |
| 3138 Condition CheckedSmiComparisonInstr::EmitComparisonCode( | 3113 Condition CheckedSmiComparisonInstr::EmitComparisonCode( |
| 3139 FlowGraphCompiler* compiler, BranchLabels labels) { | 3114 FlowGraphCompiler* compiler, |
| 3115 BranchLabels labels) { |
| 3140 return EmitSmiComparisonOp(compiler, *locs(), kind()); | 3116 return EmitSmiComparisonOp(compiler, *locs(), kind()); |
| 3141 } | 3117 } |
| 3142 | 3118 |
| 3143 | 3119 |
| 3144 #define EMIT_SMI_CHECK \ | 3120 #define EMIT_SMI_CHECK \ |
| 3145 Register left = locs()->in(0).reg(); \ | 3121 Register left = locs()->in(0).reg(); \ |
| 3146 Register right = locs()->in(1).reg(); \ | 3122 Register right = locs()->in(1).reg(); \ |
| 3147 Register temp = locs()->temp(0).reg(); \ | 3123 Register temp = locs()->temp(0).reg(); \ |
| 3148 intptr_t left_cid = this->left()->Type()->ToCid(); \ | 3124 intptr_t left_cid = this->left()->Type()->ToCid(); \ |
| 3149 intptr_t right_cid = this->right()->Type()->ToCid(); \ | 3125 intptr_t right_cid = this->right()->Type()->ToCid(); \ |
| 3150 if (this->left()->definition() == this->right()->definition()) { \ | 3126 if (this->left()->definition() == this->right()->definition()) { \ |
| 3151 __ andi(CMPRES1, left, Immediate(kSmiTagMask)); \ | 3127 __ andi(CMPRES1, left, Immediate(kSmiTagMask)); \ |
| 3152 } else if (left_cid == kSmiCid) { \ | 3128 } else if (left_cid == kSmiCid) { \ |
| 3153 __ andi(CMPRES1, right, Immediate(kSmiTagMask)); \ | 3129 __ andi(CMPRES1, right, Immediate(kSmiTagMask)); \ |
| 3154 } else if (right_cid == kSmiCid) { \ | 3130 } else if (right_cid == kSmiCid) { \ |
| 3155 __ andi(CMPRES1, left, Immediate(kSmiTagMask)); \ | 3131 __ andi(CMPRES1, left, Immediate(kSmiTagMask)); \ |
| 3156 } else { \ | 3132 } else { \ |
| 3157 __ or_(temp, left, right); \ | 3133 __ or_(temp, left, right); \ |
| 3158 __ andi(CMPRES1, temp, Immediate(kSmiTagMask)); \ | 3134 __ andi(CMPRES1, temp, Immediate(kSmiTagMask)); \ |
| 3159 } \ | 3135 } \ |
| 3160 __ bne(CMPRES1, ZR, slow_path->entry_label()); \ | 3136 __ bne(CMPRES1, ZR, slow_path->entry_label()); |
| 3161 | 3137 |
| 3162 | 3138 |
| 3163 void CheckedSmiComparisonInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 3139 void CheckedSmiComparisonInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
| 3164 BranchInstr* branch) { | 3140 BranchInstr* branch) { |
| 3165 BranchLabels labels = compiler->CreateBranchLabels(branch); | 3141 BranchLabels labels = compiler->CreateBranchLabels(branch); |
| 3166 CheckedSmiComparisonSlowPath* slow_path = | 3142 CheckedSmiComparisonSlowPath* slow_path = new CheckedSmiComparisonSlowPath( |
| 3167 new CheckedSmiComparisonSlowPath(this, | 3143 this, compiler->CurrentTryIndex(), labels, |
| 3168 compiler->CurrentTryIndex(), | 3144 /* merged = */ true); |
| 3169 labels, | |
| 3170 /* merged = */ true); | |
| 3171 compiler->AddSlowPathCode(slow_path); | 3145 compiler->AddSlowPathCode(slow_path); |
| 3172 EMIT_SMI_CHECK; | 3146 EMIT_SMI_CHECK; |
| 3173 Condition true_condition = EmitComparisonCode(compiler, labels); | 3147 Condition true_condition = EmitComparisonCode(compiler, labels); |
| 3174 EmitBranchOnCondition(compiler, true_condition, labels); | 3148 EmitBranchOnCondition(compiler, true_condition, labels); |
| 3175 __ Bind(slow_path->exit_label()); | 3149 __ Bind(slow_path->exit_label()); |
| 3176 } | 3150 } |
| 3177 | 3151 |
| 3178 | 3152 |
| 3179 void CheckedSmiComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3153 void CheckedSmiComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3180 Label true_label, false_label, done; | 3154 Label true_label, false_label, done; |
| 3181 BranchLabels labels = { &true_label, &false_label, &false_label }; | 3155 BranchLabels labels = {&true_label, &false_label, &false_label}; |
| 3182 CheckedSmiComparisonSlowPath* slow_path = | 3156 CheckedSmiComparisonSlowPath* slow_path = new CheckedSmiComparisonSlowPath( |
| 3183 new CheckedSmiComparisonSlowPath(this, | 3157 this, compiler->CurrentTryIndex(), labels, |
| 3184 compiler->CurrentTryIndex(), | 3158 /* merged = */ false); |
| 3185 labels, | |
| 3186 /* merged = */ false); | |
| 3187 compiler->AddSlowPathCode(slow_path); | 3159 compiler->AddSlowPathCode(slow_path); |
| 3188 EMIT_SMI_CHECK; | 3160 EMIT_SMI_CHECK; |
| 3189 Condition true_condition = EmitComparisonCode(compiler, labels); | 3161 Condition true_condition = EmitComparisonCode(compiler, labels); |
| 3190 EmitBranchOnCondition(compiler, true_condition, labels); | 3162 EmitBranchOnCondition(compiler, true_condition, labels); |
| 3191 Register result = locs()->out(0).reg(); | 3163 Register result = locs()->out(0).reg(); |
| 3192 __ Bind(&false_label); | 3164 __ Bind(&false_label); |
| 3193 __ LoadObject(result, Bool::False()); | 3165 __ LoadObject(result, Bool::False()); |
| 3194 __ b(&done); | 3166 __ b(&done); |
| 3195 __ Bind(&true_label); | 3167 __ Bind(&true_label); |
| 3196 __ LoadObject(result, Bool::True()); | 3168 __ LoadObject(result, Bool::True()); |
| 3197 __ Bind(&done); | 3169 __ Bind(&done); |
| 3198 __ Bind(slow_path->exit_label()); | 3170 __ Bind(slow_path->exit_label()); |
| 3199 } | 3171 } |
| 3200 | 3172 |
| 3201 | 3173 |
| 3202 LocationSummary* BinarySmiOpInstr::MakeLocationSummary(Zone* zone, | 3174 LocationSummary* BinarySmiOpInstr::MakeLocationSummary(Zone* zone, |
| 3203 bool opt) const { | 3175 bool opt) const { |
| 3204 const intptr_t kNumInputs = 2; | 3176 const intptr_t kNumInputs = 2; |
| 3205 const intptr_t kNumTemps = | 3177 const intptr_t kNumTemps = |
| 3206 ((op_kind() == Token::kADD) || | 3178 ((op_kind() == Token::kADD) || (op_kind() == Token::kMOD) || |
| 3207 (op_kind() == Token::kMOD) || | |
| 3208 (op_kind() == Token::kTRUNCDIV) || | 3179 (op_kind() == Token::kTRUNCDIV) || |
| 3209 (((op_kind() == Token::kSHL) && can_overflow()) || | 3180 (((op_kind() == Token::kSHL) && can_overflow()) || |
| 3210 (op_kind() == Token::kSHR))) ? 1 : 0; | 3181 (op_kind() == Token::kSHR))) |
| 3211 LocationSummary* summary = new(zone) LocationSummary( | 3182 ? 1 |
| 3212 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3183 : 0; |
| 3184 LocationSummary* summary = new (zone) |
| 3185 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3213 if (op_kind() == Token::kTRUNCDIV) { | 3186 if (op_kind() == Token::kTRUNCDIV) { |
| 3214 summary->set_in(0, Location::RequiresRegister()); | 3187 summary->set_in(0, Location::RequiresRegister()); |
| 3215 if (RightIsPowerOfTwoConstant()) { | 3188 if (RightIsPowerOfTwoConstant()) { |
| 3216 ConstantInstr* right_constant = right()->definition()->AsConstant(); | 3189 ConstantInstr* right_constant = right()->definition()->AsConstant(); |
| 3217 summary->set_in(1, Location::Constant(right_constant)); | 3190 summary->set_in(1, Location::Constant(right_constant)); |
| 3218 } else { | 3191 } else { |
| 3219 summary->set_in(1, Location::RequiresRegister()); | 3192 summary->set_in(1, Location::RequiresRegister()); |
| 3220 } | 3193 } |
| 3221 summary->set_temp(0, Location::RequiresRegister()); | 3194 summary->set_temp(0, Location::RequiresRegister()); |
| 3222 summary->set_out(0, Location::RequiresRegister()); | 3195 summary->set_out(0, Location::RequiresRegister()); |
| (...skipping 270 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3493 } | 3466 } |
| 3494 | 3467 |
| 3495 | 3468 |
| 3496 LocationSummary* CheckEitherNonSmiInstr::MakeLocationSummary(Zone* zone, | 3469 LocationSummary* CheckEitherNonSmiInstr::MakeLocationSummary(Zone* zone, |
| 3497 bool opt) const { | 3470 bool opt) const { |
| 3498 intptr_t left_cid = left()->Type()->ToCid(); | 3471 intptr_t left_cid = left()->Type()->ToCid(); |
| 3499 intptr_t right_cid = right()->Type()->ToCid(); | 3472 intptr_t right_cid = right()->Type()->ToCid(); |
| 3500 ASSERT((left_cid != kDoubleCid) && (right_cid != kDoubleCid)); | 3473 ASSERT((left_cid != kDoubleCid) && (right_cid != kDoubleCid)); |
| 3501 const intptr_t kNumInputs = 2; | 3474 const intptr_t kNumInputs = 2; |
| 3502 const intptr_t kNumTemps = 0; | 3475 const intptr_t kNumTemps = 0; |
| 3503 LocationSummary* summary = new(zone) LocationSummary( | 3476 LocationSummary* summary = new (zone) |
| 3504 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3477 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3505 summary->set_in(0, Location::RequiresRegister()); | 3478 summary->set_in(0, Location::RequiresRegister()); |
| 3506 summary->set_in(1, Location::RequiresRegister()); | 3479 summary->set_in(1, Location::RequiresRegister()); |
| 3507 return summary; | 3480 return summary; |
| 3508 } | 3481 } |
| 3509 | 3482 |
| 3510 | 3483 |
| 3511 void CheckEitherNonSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3484 void CheckEitherNonSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3512 Label* deopt = compiler->AddDeoptStub(deopt_id(), | 3485 Label* deopt = |
| 3513 ICData::kDeoptBinaryDoubleOp, | 3486 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryDoubleOp, |
| 3514 licm_hoisted_ ? ICData::kHoisted : 0); | 3487 licm_hoisted_ ? ICData::kHoisted : 0); |
| 3515 intptr_t left_cid = left()->Type()->ToCid(); | 3488 intptr_t left_cid = left()->Type()->ToCid(); |
| 3516 intptr_t right_cid = right()->Type()->ToCid(); | 3489 intptr_t right_cid = right()->Type()->ToCid(); |
| 3517 Register left = locs()->in(0).reg(); | 3490 Register left = locs()->in(0).reg(); |
| 3518 Register right = locs()->in(1).reg(); | 3491 Register right = locs()->in(1).reg(); |
| 3519 if (this->left()->definition() == this->right()->definition()) { | 3492 if (this->left()->definition() == this->right()->definition()) { |
| 3520 __ andi(CMPRES1, left, Immediate(kSmiTagMask)); | 3493 __ andi(CMPRES1, left, Immediate(kSmiTagMask)); |
| 3521 } else if (left_cid == kSmiCid) { | 3494 } else if (left_cid == kSmiCid) { |
| 3522 __ andi(CMPRES1, right, Immediate(kSmiTagMask)); | 3495 __ andi(CMPRES1, right, Immediate(kSmiTagMask)); |
| 3523 } else if (right_cid == kSmiCid) { | 3496 } else if (right_cid == kSmiCid) { |
| 3524 __ andi(CMPRES1, left, Immediate(kSmiTagMask)); | 3497 __ andi(CMPRES1, left, Immediate(kSmiTagMask)); |
| 3525 } else { | 3498 } else { |
| 3526 __ or_(TMP, left, right); | 3499 __ or_(TMP, left, right); |
| 3527 __ andi(CMPRES1, TMP, Immediate(kSmiTagMask)); | 3500 __ andi(CMPRES1, TMP, Immediate(kSmiTagMask)); |
| 3528 } | 3501 } |
| 3529 __ beq(CMPRES1, ZR, deopt); | 3502 __ beq(CMPRES1, ZR, deopt); |
| 3530 } | 3503 } |
| 3531 | 3504 |
| 3532 | 3505 |
| 3533 LocationSummary* BoxInstr::MakeLocationSummary(Zone* zone, | 3506 LocationSummary* BoxInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
| 3534 bool opt) const { | |
| 3535 const intptr_t kNumInputs = 1; | 3507 const intptr_t kNumInputs = 1; |
| 3536 const intptr_t kNumTemps = 1; | 3508 const intptr_t kNumTemps = 1; |
| 3537 LocationSummary* summary = new(zone) LocationSummary( | 3509 LocationSummary* summary = new (zone) LocationSummary( |
| 3538 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); | 3510 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); |
| 3539 summary->set_in(0, Location::RequiresFpuRegister()); | 3511 summary->set_in(0, Location::RequiresFpuRegister()); |
| 3540 summary->set_temp(0, Location::RequiresRegister()); | 3512 summary->set_temp(0, Location::RequiresRegister()); |
| 3541 summary->set_out(0, Location::RequiresRegister()); | 3513 summary->set_out(0, Location::RequiresRegister()); |
| 3542 return summary; | 3514 return summary; |
| 3543 } | 3515 } |
| 3544 | 3516 |
| 3545 | 3517 |
| 3546 void BoxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3518 void BoxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3547 ASSERT(from_representation() == kUnboxedDouble); | 3519 ASSERT(from_representation() == kUnboxedDouble); |
| 3548 | 3520 |
| 3549 Register out_reg = locs()->out(0).reg(); | 3521 Register out_reg = locs()->out(0).reg(); |
| 3550 DRegister value = locs()->in(0).fpu_reg(); | 3522 DRegister value = locs()->in(0).fpu_reg(); |
| 3551 | 3523 |
| 3552 BoxAllocationSlowPath::Allocate( | 3524 BoxAllocationSlowPath::Allocate(compiler, this, compiler->double_class(), |
| 3553 compiler, this, compiler->double_class(), out_reg, locs()->temp(0).reg()); | 3525 out_reg, locs()->temp(0).reg()); |
| 3554 __ StoreDToOffset(value, out_reg, Double::value_offset() - kHeapObjectTag); | 3526 __ StoreDToOffset(value, out_reg, Double::value_offset() - kHeapObjectTag); |
| 3555 } | 3527 } |
| 3556 | 3528 |
| 3557 | 3529 |
| 3558 LocationSummary* UnboxInstr::MakeLocationSummary(Zone* zone, | 3530 LocationSummary* UnboxInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
| 3559 bool opt) const { | |
| 3560 const intptr_t kNumInputs = 1; | 3531 const intptr_t kNumInputs = 1; |
| 3561 const intptr_t kNumTemps = 0; | 3532 const intptr_t kNumTemps = 0; |
| 3562 LocationSummary* summary = new(zone) LocationSummary( | 3533 LocationSummary* summary = new (zone) |
| 3563 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3534 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3564 summary->set_in(0, Location::RequiresRegister()); | 3535 summary->set_in(0, Location::RequiresRegister()); |
| 3565 if (representation() == kUnboxedMint) { | 3536 if (representation() == kUnboxedMint) { |
| 3566 summary->set_out(0, Location::Pair(Location::RequiresRegister(), | 3537 summary->set_out(0, Location::Pair(Location::RequiresRegister(), |
| 3567 Location::RequiresRegister())); | 3538 Location::RequiresRegister())); |
| 3568 } else { | 3539 } else { |
| 3569 summary->set_out(0, Location::RequiresFpuRegister()); | 3540 summary->set_out(0, Location::RequiresFpuRegister()); |
| 3570 } | 3541 } |
| 3571 return summary; | 3542 return summary; |
| 3572 } | 3543 } |
| 3573 | 3544 |
| 3574 | 3545 |
| 3575 void UnboxInstr::EmitLoadFromBox(FlowGraphCompiler* compiler) { | 3546 void UnboxInstr::EmitLoadFromBox(FlowGraphCompiler* compiler) { |
| 3576 const Register box = locs()->in(0).reg(); | 3547 const Register box = locs()->in(0).reg(); |
| 3577 | 3548 |
| 3578 switch (representation()) { | 3549 switch (representation()) { |
| 3579 case kUnboxedMint: { | 3550 case kUnboxedMint: { |
| 3580 PairLocation* result = locs()->out(0).AsPairLocation(); | 3551 PairLocation* result = locs()->out(0).AsPairLocation(); |
| 3581 __ LoadFromOffset(result->At(0).reg(), | 3552 __ LoadFromOffset(result->At(0).reg(), box, |
| 3582 box, | |
| 3583 ValueOffset() - kHeapObjectTag); | 3553 ValueOffset() - kHeapObjectTag); |
| 3584 __ LoadFromOffset(result->At(1).reg(), | 3554 __ LoadFromOffset(result->At(1).reg(), box, |
| 3585 box, | |
| 3586 ValueOffset() - kHeapObjectTag + kWordSize); | 3555 ValueOffset() - kHeapObjectTag + kWordSize); |
| 3587 break; | 3556 break; |
| 3588 } | 3557 } |
| 3589 | 3558 |
| 3590 case kUnboxedDouble: { | 3559 case kUnboxedDouble: { |
| 3591 const DRegister result = locs()->out(0).fpu_reg(); | 3560 const DRegister result = locs()->out(0).fpu_reg(); |
| 3592 __ LoadDFromOffset(result, box, Double::value_offset() - kHeapObjectTag); | 3561 __ LoadDFromOffset(result, box, Double::value_offset() - kHeapObjectTag); |
| 3593 break; | 3562 break; |
| 3594 } | 3563 } |
| 3595 | 3564 |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3636 void UnboxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3605 void UnboxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3637 const intptr_t value_cid = value()->Type()->ToCid(); | 3606 const intptr_t value_cid = value()->Type()->ToCid(); |
| 3638 const intptr_t box_cid = BoxCid(); | 3607 const intptr_t box_cid = BoxCid(); |
| 3639 | 3608 |
| 3640 if (value_cid == box_cid) { | 3609 if (value_cid == box_cid) { |
| 3641 EmitLoadFromBox(compiler); | 3610 EmitLoadFromBox(compiler); |
| 3642 } else if (CanConvertSmi() && (value_cid == kSmiCid)) { | 3611 } else if (CanConvertSmi() && (value_cid == kSmiCid)) { |
| 3643 EmitSmiConversion(compiler); | 3612 EmitSmiConversion(compiler); |
| 3644 } else { | 3613 } else { |
| 3645 const Register box = locs()->in(0).reg(); | 3614 const Register box = locs()->in(0).reg(); |
| 3646 Label* deopt = compiler->AddDeoptStub(GetDeoptId(), | 3615 Label* deopt = |
| 3647 ICData::kDeoptCheckClass); | 3616 compiler->AddDeoptStub(GetDeoptId(), ICData::kDeoptCheckClass); |
| 3648 Label is_smi; | 3617 Label is_smi; |
| 3649 | 3618 |
| 3650 if ((value()->Type()->ToNullableCid() == box_cid) && | 3619 if ((value()->Type()->ToNullableCid() == box_cid) && |
| 3651 value()->Type()->is_nullable()) { | 3620 value()->Type()->is_nullable()) { |
| 3652 __ BranchEqual(box, Object::null_object(), deopt); | 3621 __ BranchEqual(box, Object::null_object(), deopt); |
| 3653 } else { | 3622 } else { |
| 3654 __ andi(CMPRES1, box, Immediate(kSmiTagMask)); | 3623 __ andi(CMPRES1, box, Immediate(kSmiTagMask)); |
| 3655 __ beq(CMPRES1, ZR, CanConvertSmi() ? &is_smi : deopt); | 3624 __ beq(CMPRES1, ZR, CanConvertSmi() ? &is_smi : deopt); |
| 3656 __ LoadClassId(CMPRES1, box); | 3625 __ LoadClassId(CMPRES1, box); |
| 3657 __ BranchNotEqual(CMPRES1, Immediate(box_cid), deopt); | 3626 __ BranchNotEqual(CMPRES1, Immediate(box_cid), deopt); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 3669 } | 3638 } |
| 3670 } | 3639 } |
| 3671 | 3640 |
| 3672 | 3641 |
| 3673 LocationSummary* BoxInteger32Instr::MakeLocationSummary(Zone* zone, | 3642 LocationSummary* BoxInteger32Instr::MakeLocationSummary(Zone* zone, |
| 3674 bool opt) const { | 3643 bool opt) const { |
| 3675 ASSERT((from_representation() == kUnboxedInt32) || | 3644 ASSERT((from_representation() == kUnboxedInt32) || |
| 3676 (from_representation() == kUnboxedUint32)); | 3645 (from_representation() == kUnboxedUint32)); |
| 3677 const intptr_t kNumInputs = 1; | 3646 const intptr_t kNumInputs = 1; |
| 3678 const intptr_t kNumTemps = 1; | 3647 const intptr_t kNumTemps = 1; |
| 3679 LocationSummary* summary = new(zone) LocationSummary( | 3648 LocationSummary* summary = new (zone) LocationSummary( |
| 3680 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); | 3649 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); |
| 3681 summary->set_in(0, Location::RequiresRegister()); | 3650 summary->set_in(0, Location::RequiresRegister()); |
| 3682 summary->set_temp(0, Location::RequiresRegister()); | 3651 summary->set_temp(0, Location::RequiresRegister()); |
| 3683 summary->set_out(0, Location::RequiresRegister()); | 3652 summary->set_out(0, Location::RequiresRegister()); |
| 3684 return summary; | 3653 return summary; |
| 3685 } | 3654 } |
| 3686 | 3655 |
| 3687 | 3656 |
| 3688 void BoxInteger32Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3657 void BoxInteger32Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3689 Register value = locs()->in(0).reg(); | 3658 Register value = locs()->in(0).reg(); |
| 3690 Register out = locs()->out(0).reg(); | 3659 Register out = locs()->out(0).reg(); |
| 3691 ASSERT(value != out); | 3660 ASSERT(value != out); |
| 3692 | 3661 |
| 3693 __ SmiTag(out, value); | 3662 __ SmiTag(out, value); |
| 3694 if (!ValueFitsSmi()) { | 3663 if (!ValueFitsSmi()) { |
| 3695 Register temp = locs()->temp(0).reg(); | 3664 Register temp = locs()->temp(0).reg(); |
| 3696 Label done; | 3665 Label done; |
| 3697 if (from_representation() == kUnboxedInt32) { | 3666 if (from_representation() == kUnboxedInt32) { |
| 3698 __ SmiUntag(CMPRES1, out); | 3667 __ SmiUntag(CMPRES1, out); |
| 3699 __ BranchEqual(CMPRES1, value, &done); | 3668 __ BranchEqual(CMPRES1, value, &done); |
| 3700 } else { | 3669 } else { |
| 3701 ASSERT(from_representation() == kUnboxedUint32); | 3670 ASSERT(from_representation() == kUnboxedUint32); |
| 3702 __ AndImmediate(CMPRES1, value, 0xC0000000); | 3671 __ AndImmediate(CMPRES1, value, 0xC0000000); |
| 3703 __ BranchEqual(CMPRES1, ZR, &done); | 3672 __ BranchEqual(CMPRES1, ZR, &done); |
| 3704 } | 3673 } |
| 3705 BoxAllocationSlowPath::Allocate( | 3674 BoxAllocationSlowPath::Allocate(compiler, this, compiler->mint_class(), out, |
| 3706 compiler, | 3675 temp); |
| 3707 this, | |
| 3708 compiler->mint_class(), | |
| 3709 out, | |
| 3710 temp); | |
| 3711 Register hi; | 3676 Register hi; |
| 3712 if (from_representation() == kUnboxedInt32) { | 3677 if (from_representation() == kUnboxedInt32) { |
| 3713 hi = temp; | 3678 hi = temp; |
| 3714 __ sra(hi, value, kBitsPerWord - 1); | 3679 __ sra(hi, value, kBitsPerWord - 1); |
| 3715 } else { | 3680 } else { |
| 3716 ASSERT(from_representation() == kUnboxedUint32); | 3681 ASSERT(from_representation() == kUnboxedUint32); |
| 3717 hi = ZR; | 3682 hi = ZR; |
| 3718 } | 3683 } |
| 3719 __ StoreToOffset(value, | 3684 __ StoreToOffset(value, out, Mint::value_offset() - kHeapObjectTag); |
| 3720 out, | 3685 __ StoreToOffset(hi, out, |
| 3721 Mint::value_offset() - kHeapObjectTag); | |
| 3722 __ StoreToOffset(hi, | |
| 3723 out, | |
| 3724 Mint::value_offset() - kHeapObjectTag + kWordSize); | 3686 Mint::value_offset() - kHeapObjectTag + kWordSize); |
| 3725 __ Bind(&done); | 3687 __ Bind(&done); |
| 3726 } | 3688 } |
| 3727 } | 3689 } |
| 3728 | 3690 |
| 3729 | 3691 |
| 3730 LocationSummary* BoxInt64Instr::MakeLocationSummary(Zone* zone, | 3692 LocationSummary* BoxInt64Instr::MakeLocationSummary(Zone* zone, |
| 3731 bool opt) const { | 3693 bool opt) const { |
| 3732 const intptr_t kNumInputs = 1; | 3694 const intptr_t kNumInputs = 1; |
| 3733 const intptr_t kNumTemps = ValueFitsSmi() ? 0 : 1; | 3695 const intptr_t kNumTemps = ValueFitsSmi() ? 0 : 1; |
| 3734 LocationSummary* summary = new(zone) LocationSummary( | 3696 LocationSummary* summary = new (zone) |
| 3735 zone, | 3697 LocationSummary(zone, kNumInputs, kNumTemps, |
| 3736 kNumInputs, | 3698 ValueFitsSmi() ? LocationSummary::kNoCall |
| 3737 kNumTemps, | 3699 : LocationSummary::kCallOnSlowPath); |
| 3738 ValueFitsSmi() ? LocationSummary::kNoCall | |
| 3739 : LocationSummary::kCallOnSlowPath); | |
| 3740 summary->set_in(0, Location::Pair(Location::RequiresRegister(), | 3700 summary->set_in(0, Location::Pair(Location::RequiresRegister(), |
| 3741 Location::RequiresRegister())); | 3701 Location::RequiresRegister())); |
| 3742 if (!ValueFitsSmi()) { | 3702 if (!ValueFitsSmi()) { |
| 3743 summary->set_temp(0, Location::RequiresRegister()); | 3703 summary->set_temp(0, Location::RequiresRegister()); |
| 3744 } | 3704 } |
| 3745 summary->set_out(0, Location::RequiresRegister()); | 3705 summary->set_out(0, Location::RequiresRegister()); |
| 3746 return summary; | 3706 return summary; |
| 3747 } | 3707 } |
| 3748 | 3708 |
| 3749 | 3709 |
| (...skipping 13 matching lines...) Expand all Loading... |
| 3763 Register out_reg = locs()->out(0).reg(); | 3723 Register out_reg = locs()->out(0).reg(); |
| 3764 | 3724 |
| 3765 Label not_smi, done; | 3725 Label not_smi, done; |
| 3766 __ SmiTag(out_reg, value_lo); | 3726 __ SmiTag(out_reg, value_lo); |
| 3767 __ SmiUntag(tmp, out_reg); | 3727 __ SmiUntag(tmp, out_reg); |
| 3768 __ bne(tmp, value_lo, ¬_smi); | 3728 __ bne(tmp, value_lo, ¬_smi); |
| 3769 __ delay_slot()->sra(tmp, out_reg, 31); | 3729 __ delay_slot()->sra(tmp, out_reg, 31); |
| 3770 __ beq(tmp, value_hi, &done); | 3730 __ beq(tmp, value_hi, &done); |
| 3771 | 3731 |
| 3772 __ Bind(¬_smi); | 3732 __ Bind(¬_smi); |
| 3773 BoxAllocationSlowPath::Allocate( | 3733 BoxAllocationSlowPath::Allocate(compiler, this, compiler->mint_class(), |
| 3774 compiler, | 3734 out_reg, tmp); |
| 3775 this, | |
| 3776 compiler->mint_class(), | |
| 3777 out_reg, | |
| 3778 tmp); | |
| 3779 __ StoreToOffset(value_lo, out_reg, Mint::value_offset() - kHeapObjectTag); | 3735 __ StoreToOffset(value_lo, out_reg, Mint::value_offset() - kHeapObjectTag); |
| 3780 __ StoreToOffset(value_hi, | 3736 __ StoreToOffset(value_hi, out_reg, |
| 3781 out_reg, | |
| 3782 Mint::value_offset() - kHeapObjectTag + kWordSize); | 3737 Mint::value_offset() - kHeapObjectTag + kWordSize); |
| 3783 __ Bind(&done); | 3738 __ Bind(&done); |
| 3784 } | 3739 } |
| 3785 | 3740 |
| 3786 | 3741 |
| 3787 LocationSummary* UnboxInteger32Instr::MakeLocationSummary(Zone* zone, | 3742 LocationSummary* UnboxInteger32Instr::MakeLocationSummary(Zone* zone, |
| 3788 bool opt) const { | 3743 bool opt) const { |
| 3789 ASSERT((representation() == kUnboxedInt32) || | 3744 ASSERT((representation() == kUnboxedInt32) || |
| 3790 (representation() == kUnboxedUint32)); | 3745 (representation() == kUnboxedUint32)); |
| 3791 const intptr_t kNumInputs = 1; | 3746 const intptr_t kNumInputs = 1; |
| 3792 const intptr_t kNumTemps = 0; | 3747 const intptr_t kNumTemps = 0; |
| 3793 LocationSummary* summary = new(zone) LocationSummary( | 3748 LocationSummary* summary = new (zone) |
| 3794 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3749 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3795 summary->set_in(0, Location::RequiresRegister()); | 3750 summary->set_in(0, Location::RequiresRegister()); |
| 3796 summary->set_out(0, Location::RequiresRegister()); | 3751 summary->set_out(0, Location::RequiresRegister()); |
| 3797 return summary; | 3752 return summary; |
| 3798 } | 3753 } |
| 3799 | 3754 |
| 3800 | 3755 |
| 3801 static void LoadInt32FromMint(FlowGraphCompiler* compiler, | 3756 static void LoadInt32FromMint(FlowGraphCompiler* compiler, |
| 3802 Register mint, | 3757 Register mint, |
| 3803 Register result, | 3758 Register result, |
| 3804 Label* deopt) { | 3759 Label* deopt) { |
| 3805 __ LoadFieldFromOffset(result, mint, Mint::value_offset()); | 3760 __ LoadFieldFromOffset(result, mint, Mint::value_offset()); |
| 3806 if (deopt != NULL) { | 3761 if (deopt != NULL) { |
| 3807 __ LoadFieldFromOffset(CMPRES1, | 3762 __ LoadFieldFromOffset(CMPRES1, mint, Mint::value_offset() + kWordSize); |
| 3808 mint, | |
| 3809 Mint::value_offset() + kWordSize); | |
| 3810 __ sra(CMPRES2, result, kBitsPerWord - 1); | 3763 __ sra(CMPRES2, result, kBitsPerWord - 1); |
| 3811 __ BranchNotEqual(CMPRES1, CMPRES2, deopt); | 3764 __ BranchNotEqual(CMPRES1, CMPRES2, deopt); |
| 3812 } | 3765 } |
| 3813 } | 3766 } |
| 3814 | 3767 |
| 3815 | 3768 |
| 3816 void UnboxInteger32Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3769 void UnboxInteger32Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3817 const intptr_t value_cid = value()->Type()->ToCid(); | 3770 const intptr_t value_cid = value()->Type()->ToCid(); |
| 3818 const Register value = locs()->in(0).reg(); | 3771 const Register value = locs()->in(0).reg(); |
| 3819 const Register out = locs()->out(0).reg(); | 3772 const Register out = locs()->out(0).reg(); |
| 3820 Label* deopt = CanDeoptimize() ? | 3773 Label* deopt = |
| 3821 compiler->AddDeoptStub(GetDeoptId(), ICData::kDeoptUnboxInteger) : NULL; | 3774 CanDeoptimize() |
| 3775 ? compiler->AddDeoptStub(GetDeoptId(), ICData::kDeoptUnboxInteger) |
| 3776 : NULL; |
| 3822 Label* out_of_range = !is_truncating() ? deopt : NULL; | 3777 Label* out_of_range = !is_truncating() ? deopt : NULL; |
| 3823 ASSERT(value != out); | 3778 ASSERT(value != out); |
| 3824 | 3779 |
| 3825 if (value_cid == kSmiCid) { | 3780 if (value_cid == kSmiCid) { |
| 3826 __ SmiUntag(out, value); | 3781 __ SmiUntag(out, value); |
| 3827 } else if (value_cid == kMintCid) { | 3782 } else if (value_cid == kMintCid) { |
| 3828 LoadInt32FromMint(compiler, value, out, out_of_range); | 3783 LoadInt32FromMint(compiler, value, out, out_of_range); |
| 3829 } else if (!CanDeoptimize()) { | 3784 } else if (!CanDeoptimize()) { |
| 3830 Label done; | 3785 Label done; |
| 3831 __ SmiUntag(out, value); | 3786 __ SmiUntag(out, value); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 3843 LoadInt32FromMint(compiler, value, out, out_of_range); | 3798 LoadInt32FromMint(compiler, value, out, out_of_range); |
| 3844 __ Bind(&done); | 3799 __ Bind(&done); |
| 3845 } | 3800 } |
| 3846 } | 3801 } |
| 3847 | 3802 |
| 3848 | 3803 |
| 3849 LocationSummary* BinaryDoubleOpInstr::MakeLocationSummary(Zone* zone, | 3804 LocationSummary* BinaryDoubleOpInstr::MakeLocationSummary(Zone* zone, |
| 3850 bool opt) const { | 3805 bool opt) const { |
| 3851 const intptr_t kNumInputs = 2; | 3806 const intptr_t kNumInputs = 2; |
| 3852 const intptr_t kNumTemps = 0; | 3807 const intptr_t kNumTemps = 0; |
| 3853 LocationSummary* summary = new(zone) LocationSummary( | 3808 LocationSummary* summary = new (zone) |
| 3854 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3809 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3855 summary->set_in(0, Location::RequiresFpuRegister()); | 3810 summary->set_in(0, Location::RequiresFpuRegister()); |
| 3856 summary->set_in(1, Location::RequiresFpuRegister()); | 3811 summary->set_in(1, Location::RequiresFpuRegister()); |
| 3857 summary->set_out(0, Location::RequiresFpuRegister()); | 3812 summary->set_out(0, Location::RequiresFpuRegister()); |
| 3858 return summary; | 3813 return summary; |
| 3859 } | 3814 } |
| 3860 | 3815 |
| 3861 | 3816 |
| 3862 void BinaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3817 void BinaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3863 DRegister left = locs()->in(0).fpu_reg(); | 3818 DRegister left = locs()->in(0).fpu_reg(); |
| 3864 DRegister right = locs()->in(1).fpu_reg(); | 3819 DRegister right = locs()->in(1).fpu_reg(); |
| 3865 DRegister result = locs()->out(0).fpu_reg(); | 3820 DRegister result = locs()->out(0).fpu_reg(); |
| 3866 switch (op_kind()) { | 3821 switch (op_kind()) { |
| 3867 case Token::kADD: __ addd(result, left, right); break; | 3822 case Token::kADD: |
| 3868 case Token::kSUB: __ subd(result, left, right); break; | 3823 __ addd(result, left, right); |
| 3869 case Token::kMUL: __ muld(result, left, right); break; | 3824 break; |
| 3870 case Token::kDIV: __ divd(result, left, right); break; | 3825 case Token::kSUB: |
| 3871 default: UNREACHABLE(); | 3826 __ subd(result, left, right); |
| 3827 break; |
| 3828 case Token::kMUL: |
| 3829 __ muld(result, left, right); |
| 3830 break; |
| 3831 case Token::kDIV: |
| 3832 __ divd(result, left, right); |
| 3833 break; |
| 3834 default: |
| 3835 UNREACHABLE(); |
| 3872 } | 3836 } |
| 3873 } | 3837 } |
| 3874 | 3838 |
| 3875 | 3839 |
| 3876 LocationSummary* DoubleTestOpInstr::MakeLocationSummary(Zone* zone, | 3840 LocationSummary* DoubleTestOpInstr::MakeLocationSummary(Zone* zone, |
| 3877 bool opt) const { | 3841 bool opt) const { |
| 3878 const intptr_t kNumInputs = 1; | 3842 const intptr_t kNumInputs = 1; |
| 3879 const intptr_t kNumTemps = 0; | 3843 const intptr_t kNumTemps = 0; |
| 3880 LocationSummary* summary = new(zone) LocationSummary( | 3844 LocationSummary* summary = new (zone) |
| 3881 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3845 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3882 summary->set_in(0, Location::RequiresFpuRegister()); | 3846 summary->set_in(0, Location::RequiresFpuRegister()); |
| 3883 summary->set_out(0, Location::RequiresRegister()); | 3847 summary->set_out(0, Location::RequiresRegister()); |
| 3884 return summary; | 3848 return summary; |
| 3885 } | 3849 } |
| 3886 | 3850 |
| 3887 | 3851 |
| 3888 Condition DoubleTestOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler, | 3852 Condition DoubleTestOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
| 3889 BranchLabels labels) { | 3853 BranchLabels labels) { |
| 3890 const DRegister value = locs()->in(0).fpu_reg(); | 3854 const DRegister value = locs()->in(0).fpu_reg(); |
| 3891 const bool is_negated = kind() != Token::kEQ; | 3855 const bool is_negated = kind() != Token::kEQ; |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3933 Condition true_condition = EmitComparisonCode(compiler, labels); | 3897 Condition true_condition = EmitComparisonCode(compiler, labels); |
| 3934 // Branches for isNaN are emitted in EmitComparisonCode already. | 3898 // Branches for isNaN are emitted in EmitComparisonCode already. |
| 3935 if (op_kind() == MethodRecognizer::kDouble_getIsInfinite) { | 3899 if (op_kind() == MethodRecognizer::kDouble_getIsInfinite) { |
| 3936 EmitBranchOnCondition(compiler, true_condition, labels); | 3900 EmitBranchOnCondition(compiler, true_condition, labels); |
| 3937 } | 3901 } |
| 3938 } | 3902 } |
| 3939 | 3903 |
| 3940 | 3904 |
| 3941 void DoubleTestOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3905 void DoubleTestOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3942 Label is_true, is_false; | 3906 Label is_true, is_false; |
| 3943 BranchLabels labels = { &is_true, &is_false, &is_false }; | 3907 BranchLabels labels = {&is_true, &is_false, &is_false}; |
| 3944 Condition true_condition = EmitComparisonCode(compiler, labels); | 3908 Condition true_condition = EmitComparisonCode(compiler, labels); |
| 3945 // Branches for isNaN are emitted in EmitComparisonCode already. | 3909 // Branches for isNaN are emitted in EmitComparisonCode already. |
| 3946 if (op_kind() == MethodRecognizer::kDouble_getIsInfinite) { | 3910 if (op_kind() == MethodRecognizer::kDouble_getIsInfinite) { |
| 3947 EmitBranchOnCondition(compiler, true_condition, labels); | 3911 EmitBranchOnCondition(compiler, true_condition, labels); |
| 3948 } | 3912 } |
| 3949 const Register result = locs()->out(0).reg(); | 3913 const Register result = locs()->out(0).reg(); |
| 3950 Label done; | 3914 Label done; |
| 3951 __ Comment("return bool"); | 3915 __ Comment("return bool"); |
| 3952 __ Bind(&is_false); | 3916 __ Bind(&is_false); |
| 3953 __ LoadObject(result, Bool::False()); | 3917 __ LoadObject(result, Bool::False()); |
| 3954 __ b(&done); | 3918 __ b(&done); |
| 3955 __ Bind(&is_true); | 3919 __ Bind(&is_true); |
| 3956 __ LoadObject(result, Bool::True()); | 3920 __ LoadObject(result, Bool::True()); |
| 3957 __ Bind(&done); | 3921 __ Bind(&done); |
| (...skipping 29 matching lines...) Expand all Loading... |
| 3987 UNIMPLEMENTED(); | 3951 UNIMPLEMENTED(); |
| 3988 return NULL; | 3952 return NULL; |
| 3989 } | 3953 } |
| 3990 | 3954 |
| 3991 | 3955 |
| 3992 void Simd32x4ShuffleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3956 void Simd32x4ShuffleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3993 UNIMPLEMENTED(); | 3957 UNIMPLEMENTED(); |
| 3994 } | 3958 } |
| 3995 | 3959 |
| 3996 | 3960 |
| 3997 | |
| 3998 LocationSummary* Simd32x4ShuffleMixInstr::MakeLocationSummary(Zone* zone, | 3961 LocationSummary* Simd32x4ShuffleMixInstr::MakeLocationSummary(Zone* zone, |
| 3999 bool opt) const { | 3962 bool opt) const { |
| 4000 UNIMPLEMENTED(); | 3963 UNIMPLEMENTED(); |
| 4001 return NULL; | 3964 return NULL; |
| 4002 } | 3965 } |
| 4003 | 3966 |
| 4004 | 3967 |
| 4005 void Simd32x4ShuffleMixInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3968 void Simd32x4ShuffleMixInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4006 UNIMPLEMENTED(); | 3969 UNIMPLEMENTED(); |
| 4007 } | 3970 } |
| 4008 | 3971 |
| 4009 | 3972 |
| 4010 LocationSummary* Float32x4ConstructorInstr::MakeLocationSummary( | 3973 LocationSummary* Float32x4ConstructorInstr::MakeLocationSummary( |
| 4011 Zone* zone, bool opt) const { | 3974 Zone* zone, |
| 3975 bool opt) const { |
| 4012 UNIMPLEMENTED(); | 3976 UNIMPLEMENTED(); |
| 4013 return NULL; | 3977 return NULL; |
| 4014 } | 3978 } |
| 4015 | 3979 |
| 4016 | 3980 |
| 4017 void Float32x4ConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3981 void Float32x4ConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4018 UNIMPLEMENTED(); | 3982 UNIMPLEMENTED(); |
| 4019 } | 3983 } |
| 4020 | 3984 |
| 4021 | 3985 |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4140 | 4104 |
| 4141 | 4105 |
| 4142 LocationSummary* Simd64x2ShuffleInstr::MakeLocationSummary(Zone* zone, | 4106 LocationSummary* Simd64x2ShuffleInstr::MakeLocationSummary(Zone* zone, |
| 4143 bool opt) const { | 4107 bool opt) const { |
| 4144 UNIMPLEMENTED(); | 4108 UNIMPLEMENTED(); |
| 4145 return NULL; | 4109 return NULL; |
| 4146 } | 4110 } |
| 4147 | 4111 |
| 4148 | 4112 |
| 4149 void Simd64x2ShuffleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4113 void Simd64x2ShuffleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4150 UNIMPLEMENTED(); | 4114 UNIMPLEMENTED(); |
| 4151 } | 4115 } |
| 4152 | 4116 |
| 4153 | 4117 |
| 4154 LocationSummary* Float64x2ZeroInstr::MakeLocationSummary(Zone* zone, | 4118 LocationSummary* Float64x2ZeroInstr::MakeLocationSummary(Zone* zone, |
| 4155 bool opt) const { | 4119 bool opt) const { |
| 4156 UNIMPLEMENTED(); | 4120 UNIMPLEMENTED(); |
| 4157 return NULL; | 4121 return NULL; |
| 4158 } | 4122 } |
| 4159 | 4123 |
| 4160 | 4124 |
| 4161 void Float64x2ZeroInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4125 void Float64x2ZeroInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4162 UNIMPLEMENTED(); | 4126 UNIMPLEMENTED(); |
| 4163 } | 4127 } |
| 4164 | 4128 |
| 4165 | 4129 |
| 4166 LocationSummary* Float64x2SplatInstr::MakeLocationSummary(Zone* zone, | 4130 LocationSummary* Float64x2SplatInstr::MakeLocationSummary(Zone* zone, |
| 4167 bool opt) const { | 4131 bool opt) const { |
| 4168 UNIMPLEMENTED(); | 4132 UNIMPLEMENTED(); |
| 4169 return NULL; | 4133 return NULL; |
| 4170 } | 4134 } |
| 4171 | 4135 |
| 4172 | 4136 |
| 4173 void Float64x2SplatInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4137 void Float64x2SplatInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4174 UNIMPLEMENTED(); | 4138 UNIMPLEMENTED(); |
| 4175 } | 4139 } |
| 4176 | 4140 |
| 4177 | 4141 |
| 4178 LocationSummary* Float64x2ConstructorInstr::MakeLocationSummary( | 4142 LocationSummary* Float64x2ConstructorInstr::MakeLocationSummary( |
| 4179 Zone* zone, bool opt) const { | 4143 Zone* zone, |
| 4144 bool opt) const { |
| 4180 UNIMPLEMENTED(); | 4145 UNIMPLEMENTED(); |
| 4181 return NULL; | 4146 return NULL; |
| 4182 } | 4147 } |
| 4183 | 4148 |
| 4184 | 4149 |
| 4185 void Float64x2ConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4150 void Float64x2ConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4186 UNIMPLEMENTED(); | 4151 UNIMPLEMENTED(); |
| 4187 } | 4152 } |
| 4188 | 4153 |
| 4189 | 4154 |
| 4190 LocationSummary* Float64x2ToFloat32x4Instr::MakeLocationSummary( | 4155 LocationSummary* Float64x2ToFloat32x4Instr::MakeLocationSummary( |
| 4191 Zone* zone, bool opt) const { | 4156 Zone* zone, |
| 4157 bool opt) const { |
| 4192 UNIMPLEMENTED(); | 4158 UNIMPLEMENTED(); |
| 4193 return NULL; | 4159 return NULL; |
| 4194 } | 4160 } |
| 4195 | 4161 |
| 4196 | 4162 |
| 4197 void Float64x2ToFloat32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4163 void Float64x2ToFloat32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4198 UNIMPLEMENTED(); | 4164 UNIMPLEMENTED(); |
| 4199 } | 4165 } |
| 4200 | 4166 |
| 4201 | 4167 |
| 4202 LocationSummary* Float32x4ToFloat64x2Instr::MakeLocationSummary( | 4168 LocationSummary* Float32x4ToFloat64x2Instr::MakeLocationSummary( |
| 4203 Zone* zone, bool opt) const { | 4169 Zone* zone, |
| 4170 bool opt) const { |
| 4204 UNIMPLEMENTED(); | 4171 UNIMPLEMENTED(); |
| 4205 return NULL; | 4172 return NULL; |
| 4206 } | 4173 } |
| 4207 | 4174 |
| 4208 | 4175 |
| 4209 void Float32x4ToFloat64x2Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4176 void Float32x4ToFloat64x2Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4210 UNIMPLEMENTED(); | 4177 UNIMPLEMENTED(); |
| 4211 } | 4178 } |
| 4212 | 4179 |
| 4213 | 4180 |
| (...skipping 14 matching lines...) Expand all Loading... |
| 4228 UNIMPLEMENTED(); | 4195 UNIMPLEMENTED(); |
| 4229 return NULL; | 4196 return NULL; |
| 4230 } | 4197 } |
| 4231 | 4198 |
| 4232 | 4199 |
| 4233 void Float64x2OneArgInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4200 void Float64x2OneArgInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4234 UNIMPLEMENTED(); | 4201 UNIMPLEMENTED(); |
| 4235 } | 4202 } |
| 4236 | 4203 |
| 4237 | 4204 |
| 4238 LocationSummary* Int32x4ConstructorInstr::MakeLocationSummary( | 4205 LocationSummary* Int32x4ConstructorInstr::MakeLocationSummary(Zone* zone, |
| 4239 Zone* zone, bool opt) const { | 4206 bool opt) const { |
| 4240 UNIMPLEMENTED(); | 4207 UNIMPLEMENTED(); |
| 4241 return NULL; | 4208 return NULL; |
| 4242 } | 4209 } |
| 4243 | 4210 |
| 4244 | 4211 |
| 4245 void Int32x4ConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4212 void Int32x4ConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4246 UNIMPLEMENTED(); | 4213 UNIMPLEMENTED(); |
| 4247 } | 4214 } |
| 4248 | 4215 |
| 4249 | 4216 |
| 4250 LocationSummary* Int32x4BoolConstructorInstr::MakeLocationSummary( | 4217 LocationSummary* Int32x4BoolConstructorInstr::MakeLocationSummary( |
| 4251 Zone* zone, bool opt) const { | 4218 Zone* zone, |
| 4219 bool opt) const { |
| 4252 UNIMPLEMENTED(); | 4220 UNIMPLEMENTED(); |
| 4253 return NULL; | 4221 return NULL; |
| 4254 } | 4222 } |
| 4255 | 4223 |
| 4256 | 4224 |
| 4257 void Int32x4BoolConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4225 void Int32x4BoolConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4258 UNIMPLEMENTED(); | 4226 UNIMPLEMENTED(); |
| 4259 } | 4227 } |
| 4260 | 4228 |
| 4261 | 4229 |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4330 UNIMPLEMENTED(); | 4298 UNIMPLEMENTED(); |
| 4331 } | 4299 } |
| 4332 | 4300 |
| 4333 | 4301 |
| 4334 LocationSummary* MathUnaryInstr::MakeLocationSummary(Zone* zone, | 4302 LocationSummary* MathUnaryInstr::MakeLocationSummary(Zone* zone, |
| 4335 bool opt) const { | 4303 bool opt) const { |
| 4336 ASSERT((kind() == MathUnaryInstr::kSqrt) || | 4304 ASSERT((kind() == MathUnaryInstr::kSqrt) || |
| 4337 (kind() == MathUnaryInstr::kDoubleSquare)); | 4305 (kind() == MathUnaryInstr::kDoubleSquare)); |
| 4338 const intptr_t kNumInputs = 1; | 4306 const intptr_t kNumInputs = 1; |
| 4339 const intptr_t kNumTemps = 0; | 4307 const intptr_t kNumTemps = 0; |
| 4340 LocationSummary* summary = new(zone) LocationSummary( | 4308 LocationSummary* summary = new (zone) |
| 4341 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4309 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4342 summary->set_in(0, Location::RequiresFpuRegister()); | 4310 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4343 summary->set_out(0, Location::RequiresFpuRegister()); | 4311 summary->set_out(0, Location::RequiresFpuRegister()); |
| 4344 return summary; | 4312 return summary; |
| 4345 } | 4313 } |
| 4346 | 4314 |
| 4347 | 4315 |
| 4348 void MathUnaryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4316 void MathUnaryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4349 if (kind() == MathUnaryInstr::kSqrt) { | 4317 if (kind() == MathUnaryInstr::kSqrt) { |
| 4350 __ sqrtd(locs()->out(0).fpu_reg(), locs()->in(0).fpu_reg()); | 4318 __ sqrtd(locs()->out(0).fpu_reg(), locs()->in(0).fpu_reg()); |
| 4351 } else if (kind() == MathUnaryInstr::kDoubleSquare) { | 4319 } else if (kind() == MathUnaryInstr::kDoubleSquare) { |
| 4352 DRegister val = locs()->in(0).fpu_reg(); | 4320 DRegister val = locs()->in(0).fpu_reg(); |
| 4353 DRegister result = locs()->out(0).fpu_reg(); | 4321 DRegister result = locs()->out(0).fpu_reg(); |
| 4354 __ muld(result, val, val); | 4322 __ muld(result, val, val); |
| 4355 } else { | 4323 } else { |
| 4356 UNREACHABLE(); | 4324 UNREACHABLE(); |
| 4357 } | 4325 } |
| 4358 } | 4326 } |
| 4359 | 4327 |
| 4360 | 4328 |
| 4361 LocationSummary* CaseInsensitiveCompareUC16Instr::MakeLocationSummary( | 4329 LocationSummary* CaseInsensitiveCompareUC16Instr::MakeLocationSummary( |
| 4362 Zone* zone, bool opt) const { | 4330 Zone* zone, |
| 4331 bool opt) const { |
| 4363 const intptr_t kNumTemps = 0; | 4332 const intptr_t kNumTemps = 0; |
| 4364 LocationSummary* summary = new(zone) LocationSummary( | 4333 LocationSummary* summary = new (zone) |
| 4365 zone, InputCount(), kNumTemps, LocationSummary::kCall); | 4334 LocationSummary(zone, InputCount(), kNumTemps, LocationSummary::kCall); |
| 4366 summary->set_in(0, Location::RegisterLocation(A0)); | 4335 summary->set_in(0, Location::RegisterLocation(A0)); |
| 4367 summary->set_in(1, Location::RegisterLocation(A1)); | 4336 summary->set_in(1, Location::RegisterLocation(A1)); |
| 4368 summary->set_in(2, Location::RegisterLocation(A2)); | 4337 summary->set_in(2, Location::RegisterLocation(A2)); |
| 4369 summary->set_in(3, Location::RegisterLocation(A3)); | 4338 summary->set_in(3, Location::RegisterLocation(A3)); |
| 4370 summary->set_out(0, Location::RegisterLocation(V0)); | 4339 summary->set_out(0, Location::RegisterLocation(V0)); |
| 4371 return summary; | 4340 return summary; |
| 4372 } | 4341 } |
| 4373 | 4342 |
| 4374 | 4343 |
| 4375 void CaseInsensitiveCompareUC16Instr::EmitNativeCode( | 4344 void CaseInsensitiveCompareUC16Instr::EmitNativeCode( |
| 4376 FlowGraphCompiler* compiler) { | 4345 FlowGraphCompiler* compiler) { |
| 4377 | |
| 4378 // Call the function. | 4346 // Call the function. |
| 4379 __ CallRuntime(TargetFunction(), TargetFunction().argument_count()); | 4347 __ CallRuntime(TargetFunction(), TargetFunction().argument_count()); |
| 4380 } | 4348 } |
| 4381 | 4349 |
| 4382 | 4350 |
| 4383 LocationSummary* MathMinMaxInstr::MakeLocationSummary(Zone* zone, | 4351 LocationSummary* MathMinMaxInstr::MakeLocationSummary(Zone* zone, |
| 4384 bool opt) const { | 4352 bool opt) const { |
| 4385 if (result_cid() == kDoubleCid) { | 4353 if (result_cid() == kDoubleCid) { |
| 4386 const intptr_t kNumInputs = 2; | 4354 const intptr_t kNumInputs = 2; |
| 4387 const intptr_t kNumTemps = 1; | 4355 const intptr_t kNumTemps = 1; |
| 4388 LocationSummary* summary = new(zone) LocationSummary( | 4356 LocationSummary* summary = new (zone) |
| 4389 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4357 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4390 summary->set_in(0, Location::RequiresFpuRegister()); | 4358 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4391 summary->set_in(1, Location::RequiresFpuRegister()); | 4359 summary->set_in(1, Location::RequiresFpuRegister()); |
| 4392 // Reuse the left register so that code can be made shorter. | 4360 // Reuse the left register so that code can be made shorter. |
| 4393 summary->set_out(0, Location::SameAsFirstInput()); | 4361 summary->set_out(0, Location::SameAsFirstInput()); |
| 4394 summary->set_temp(0, Location::RequiresRegister()); | 4362 summary->set_temp(0, Location::RequiresRegister()); |
| 4395 return summary; | 4363 return summary; |
| 4396 } | 4364 } |
| 4397 ASSERT(result_cid() == kSmiCid); | 4365 ASSERT(result_cid() == kSmiCid); |
| 4398 const intptr_t kNumInputs = 2; | 4366 const intptr_t kNumInputs = 2; |
| 4399 const intptr_t kNumTemps = 0; | 4367 const intptr_t kNumTemps = 0; |
| 4400 LocationSummary* summary = new(zone) LocationSummary( | 4368 LocationSummary* summary = new (zone) |
| 4401 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4369 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4402 summary->set_in(0, Location::RequiresRegister()); | 4370 summary->set_in(0, Location::RequiresRegister()); |
| 4403 summary->set_in(1, Location::RequiresRegister()); | 4371 summary->set_in(1, Location::RequiresRegister()); |
| 4404 // Reuse the left register so that code can be made shorter. | 4372 // Reuse the left register so that code can be made shorter. |
| 4405 summary->set_out(0, Location::SameAsFirstInput()); | 4373 summary->set_out(0, Location::SameAsFirstInput()); |
| 4406 return summary; | 4374 return summary; |
| 4407 } | 4375 } |
| 4408 | 4376 |
| 4409 | 4377 |
| 4410 void MathMinMaxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4378 void MathMinMaxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4411 ASSERT((op_kind() == MethodRecognizer::kMathMin) || | 4379 ASSERT((op_kind() == MethodRecognizer::kMathMin) || |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4469 } | 4437 } |
| 4470 __ mov(result, right); | 4438 __ mov(result, right); |
| 4471 __ Bind(&done); | 4439 __ Bind(&done); |
| 4472 } | 4440 } |
| 4473 | 4441 |
| 4474 | 4442 |
| 4475 LocationSummary* UnarySmiOpInstr::MakeLocationSummary(Zone* zone, | 4443 LocationSummary* UnarySmiOpInstr::MakeLocationSummary(Zone* zone, |
| 4476 bool opt) const { | 4444 bool opt) const { |
| 4477 const intptr_t kNumInputs = 1; | 4445 const intptr_t kNumInputs = 1; |
| 4478 const intptr_t kNumTemps = 0; | 4446 const intptr_t kNumTemps = 0; |
| 4479 LocationSummary* summary = new(zone) LocationSummary( | 4447 LocationSummary* summary = new (zone) |
| 4480 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4448 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4481 summary->set_in(0, Location::RequiresRegister()); | 4449 summary->set_in(0, Location::RequiresRegister()); |
| 4482 // We make use of 3-operand instructions by not requiring result register | 4450 // We make use of 3-operand instructions by not requiring result register |
| 4483 // to be identical to first input register as on Intel. | 4451 // to be identical to first input register as on Intel. |
| 4484 summary->set_out(0, Location::RequiresRegister()); | 4452 summary->set_out(0, Location::RequiresRegister()); |
| 4485 return summary; | 4453 return summary; |
| 4486 } | 4454 } |
| 4487 | 4455 |
| 4488 | 4456 |
| 4489 void UnarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4457 void UnarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4490 Register value = locs()->in(0).reg(); | 4458 Register value = locs()->in(0).reg(); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 4503 default: | 4471 default: |
| 4504 UNREACHABLE(); | 4472 UNREACHABLE(); |
| 4505 } | 4473 } |
| 4506 } | 4474 } |
| 4507 | 4475 |
| 4508 | 4476 |
| 4509 LocationSummary* UnaryDoubleOpInstr::MakeLocationSummary(Zone* zone, | 4477 LocationSummary* UnaryDoubleOpInstr::MakeLocationSummary(Zone* zone, |
| 4510 bool opt) const { | 4478 bool opt) const { |
| 4511 const intptr_t kNumInputs = 1; | 4479 const intptr_t kNumInputs = 1; |
| 4512 const intptr_t kNumTemps = 0; | 4480 const intptr_t kNumTemps = 0; |
| 4513 LocationSummary* summary = new(zone) LocationSummary( | 4481 LocationSummary* summary = new (zone) |
| 4514 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4482 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4515 summary->set_in(0, Location::RequiresFpuRegister()); | 4483 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4516 summary->set_out(0, Location::RequiresFpuRegister()); | 4484 summary->set_out(0, Location::RequiresFpuRegister()); |
| 4517 return summary; | 4485 return summary; |
| 4518 } | 4486 } |
| 4519 | 4487 |
| 4520 | 4488 |
| 4521 void UnaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4489 void UnaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4522 FpuRegister result = locs()->out(0).fpu_reg(); | 4490 FpuRegister result = locs()->out(0).fpu_reg(); |
| 4523 FpuRegister value = locs()->in(0).fpu_reg(); | 4491 FpuRegister value = locs()->in(0).fpu_reg(); |
| 4524 __ negd(result, value); | 4492 __ negd(result, value); |
| 4525 } | 4493 } |
| 4526 | 4494 |
| 4527 | 4495 |
| 4528 LocationSummary* Int32ToDoubleInstr::MakeLocationSummary(Zone* zone, | 4496 LocationSummary* Int32ToDoubleInstr::MakeLocationSummary(Zone* zone, |
| 4529 bool opt) const { | 4497 bool opt) const { |
| 4530 const intptr_t kNumInputs = 1; | 4498 const intptr_t kNumInputs = 1; |
| 4531 const intptr_t kNumTemps = 0; | 4499 const intptr_t kNumTemps = 0; |
| 4532 LocationSummary* result = new(zone) LocationSummary( | 4500 LocationSummary* result = new (zone) |
| 4533 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4501 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4534 result->set_in(0, Location::RequiresRegister()); | 4502 result->set_in(0, Location::RequiresRegister()); |
| 4535 result->set_out(0, Location::RequiresFpuRegister()); | 4503 result->set_out(0, Location::RequiresFpuRegister()); |
| 4536 return result; | 4504 return result; |
| 4537 } | 4505 } |
| 4538 | 4506 |
| 4539 | 4507 |
| 4540 void Int32ToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4508 void Int32ToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4541 Register value = locs()->in(0).reg(); | 4509 Register value = locs()->in(0).reg(); |
| 4542 FpuRegister result = locs()->out(0).fpu_reg(); | 4510 FpuRegister result = locs()->out(0).fpu_reg(); |
| 4543 __ mtc1(value, STMP1); | 4511 __ mtc1(value, STMP1); |
| 4544 __ cvtdw(result, STMP1); | 4512 __ cvtdw(result, STMP1); |
| 4545 } | 4513 } |
| 4546 | 4514 |
| 4547 | 4515 |
| 4548 LocationSummary* SmiToDoubleInstr::MakeLocationSummary(Zone* zone, | 4516 LocationSummary* SmiToDoubleInstr::MakeLocationSummary(Zone* zone, |
| 4549 bool opt) const { | 4517 bool opt) const { |
| 4550 const intptr_t kNumInputs = 1; | 4518 const intptr_t kNumInputs = 1; |
| 4551 const intptr_t kNumTemps = 0; | 4519 const intptr_t kNumTemps = 0; |
| 4552 LocationSummary* result = new(zone) LocationSummary( | 4520 LocationSummary* result = new (zone) |
| 4553 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4521 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4554 result->set_in(0, Location::RequiresRegister()); | 4522 result->set_in(0, Location::RequiresRegister()); |
| 4555 result->set_out(0, Location::RequiresFpuRegister()); | 4523 result->set_out(0, Location::RequiresFpuRegister()); |
| 4556 return result; | 4524 return result; |
| 4557 } | 4525 } |
| 4558 | 4526 |
| 4559 | 4527 |
| 4560 void SmiToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4528 void SmiToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4561 Register value = locs()->in(0).reg(); | 4529 Register value = locs()->in(0).reg(); |
| 4562 FpuRegister result = locs()->out(0).fpu_reg(); | 4530 FpuRegister result = locs()->out(0).fpu_reg(); |
| 4563 __ SmiUntag(TMP, value); | 4531 __ SmiUntag(TMP, value); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 4575 | 4543 |
| 4576 void MintToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4544 void MintToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4577 UNIMPLEMENTED(); | 4545 UNIMPLEMENTED(); |
| 4578 } | 4546 } |
| 4579 | 4547 |
| 4580 | 4548 |
| 4581 LocationSummary* DoubleToIntegerInstr::MakeLocationSummary(Zone* zone, | 4549 LocationSummary* DoubleToIntegerInstr::MakeLocationSummary(Zone* zone, |
| 4582 bool opt) const { | 4550 bool opt) const { |
| 4583 const intptr_t kNumInputs = 1; | 4551 const intptr_t kNumInputs = 1; |
| 4584 const intptr_t kNumTemps = 0; | 4552 const intptr_t kNumTemps = 0; |
| 4585 LocationSummary* result = new(zone) LocationSummary( | 4553 LocationSummary* result = new (zone) |
| 4586 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 4554 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
| 4587 result->set_in(0, Location::RegisterLocation(T1)); | 4555 result->set_in(0, Location::RegisterLocation(T1)); |
| 4588 result->set_out(0, Location::RegisterLocation(V0)); | 4556 result->set_out(0, Location::RegisterLocation(V0)); |
| 4589 return result; | 4557 return result; |
| 4590 } | 4558 } |
| 4591 | 4559 |
| 4592 | 4560 |
| 4593 void DoubleToIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4561 void DoubleToIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4594 Register result = locs()->out(0).reg(); | 4562 Register result = locs()->out(0).reg(); |
| 4595 Register value_obj = locs()->in(0).reg(); | 4563 Register value_obj = locs()->in(0).reg(); |
| 4596 ASSERT(result == V0); | 4564 ASSERT(result == V0); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 4608 __ SmiTag(result); | 4576 __ SmiTag(result); |
| 4609 __ b(&done); | 4577 __ b(&done); |
| 4610 __ Bind(&do_call); | 4578 __ Bind(&do_call); |
| 4611 __ Push(value_obj); | 4579 __ Push(value_obj); |
| 4612 ASSERT(instance_call()->HasICData()); | 4580 ASSERT(instance_call()->HasICData()); |
| 4613 const ICData& ic_data = *instance_call()->ic_data(); | 4581 const ICData& ic_data = *instance_call()->ic_data(); |
| 4614 ASSERT((ic_data.NumberOfChecks() == 1)); | 4582 ASSERT((ic_data.NumberOfChecks() == 1)); |
| 4615 const Function& target = Function::ZoneHandle(ic_data.GetTargetAt(0)); | 4583 const Function& target = Function::ZoneHandle(ic_data.GetTargetAt(0)); |
| 4616 | 4584 |
| 4617 const intptr_t kNumberOfArguments = 1; | 4585 const intptr_t kNumberOfArguments = 1; |
| 4618 compiler->GenerateStaticCall(deopt_id(), | 4586 compiler->GenerateStaticCall(deopt_id(), instance_call()->token_pos(), target, |
| 4619 instance_call()->token_pos(), | |
| 4620 target, | |
| 4621 kNumberOfArguments, | 4587 kNumberOfArguments, |
| 4622 Object::null_array(), // No argument names. | 4588 Object::null_array(), // No argument names. |
| 4623 locs(), | 4589 locs(), ICData::Handle()); |
| 4624 ICData::Handle()); | |
| 4625 __ Bind(&done); | 4590 __ Bind(&done); |
| 4626 } | 4591 } |
| 4627 | 4592 |
| 4628 | 4593 |
| 4629 LocationSummary* DoubleToSmiInstr::MakeLocationSummary(Zone* zone, | 4594 LocationSummary* DoubleToSmiInstr::MakeLocationSummary(Zone* zone, |
| 4630 bool opt) const { | 4595 bool opt) const { |
| 4631 const intptr_t kNumInputs = 1; | 4596 const intptr_t kNumInputs = 1; |
| 4632 const intptr_t kNumTemps = 0; | 4597 const intptr_t kNumTemps = 0; |
| 4633 LocationSummary* result = new(zone) LocationSummary( | 4598 LocationSummary* result = new (zone) |
| 4634 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4599 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4635 result->set_in(0, Location::RequiresFpuRegister()); | 4600 result->set_in(0, Location::RequiresFpuRegister()); |
| 4636 result->set_out(0, Location::RequiresRegister()); | 4601 result->set_out(0, Location::RequiresRegister()); |
| 4637 return result; | 4602 return result; |
| 4638 } | 4603 } |
| 4639 | 4604 |
| 4640 | 4605 |
| 4641 void DoubleToSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4606 void DoubleToSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4642 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptDoubleToSmi); | 4607 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptDoubleToSmi); |
| 4643 Register result = locs()->out(0).reg(); | 4608 Register result = locs()->out(0).reg(); |
| 4644 DRegister value = locs()->in(0).fpu_reg(); | 4609 DRegister value = locs()->in(0).fpu_reg(); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 4662 | 4627 |
| 4663 void DoubleToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4628 void DoubleToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4664 UNIMPLEMENTED(); | 4629 UNIMPLEMENTED(); |
| 4665 } | 4630 } |
| 4666 | 4631 |
| 4667 | 4632 |
| 4668 LocationSummary* DoubleToFloatInstr::MakeLocationSummary(Zone* zone, | 4633 LocationSummary* DoubleToFloatInstr::MakeLocationSummary(Zone* zone, |
| 4669 bool opt) const { | 4634 bool opt) const { |
| 4670 const intptr_t kNumInputs = 1; | 4635 const intptr_t kNumInputs = 1; |
| 4671 const intptr_t kNumTemps = 0; | 4636 const intptr_t kNumTemps = 0; |
| 4672 LocationSummary* result = new(zone) LocationSummary( | 4637 LocationSummary* result = new (zone) |
| 4673 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4638 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4674 result->set_in(0, Location::RequiresFpuRegister()); | 4639 result->set_in(0, Location::RequiresFpuRegister()); |
| 4675 result->set_out(0, Location::SameAsFirstInput()); | 4640 result->set_out(0, Location::SameAsFirstInput()); |
| 4676 return result; | 4641 return result; |
| 4677 } | 4642 } |
| 4678 | 4643 |
| 4679 | 4644 |
| 4680 void DoubleToFloatInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4645 void DoubleToFloatInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4681 DRegister value = locs()->in(0).fpu_reg(); | 4646 DRegister value = locs()->in(0).fpu_reg(); |
| 4682 FRegister result = EvenFRegisterOf(locs()->out(0).fpu_reg()); | 4647 FRegister result = EvenFRegisterOf(locs()->out(0).fpu_reg()); |
| 4683 __ cvtsd(result, value); | 4648 __ cvtsd(result, value); |
| 4684 } | 4649 } |
| 4685 | 4650 |
| 4686 | 4651 |
| 4687 LocationSummary* FloatToDoubleInstr::MakeLocationSummary(Zone* zone, | 4652 LocationSummary* FloatToDoubleInstr::MakeLocationSummary(Zone* zone, |
| 4688 bool opt) const { | 4653 bool opt) const { |
| 4689 const intptr_t kNumInputs = 1; | 4654 const intptr_t kNumInputs = 1; |
| 4690 const intptr_t kNumTemps = 0; | 4655 const intptr_t kNumTemps = 0; |
| 4691 LocationSummary* result = new(zone) LocationSummary( | 4656 LocationSummary* result = new (zone) |
| 4692 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4657 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4693 result->set_in(0, Location::RequiresFpuRegister()); | 4658 result->set_in(0, Location::RequiresFpuRegister()); |
| 4694 result->set_out(0, Location::SameAsFirstInput()); | 4659 result->set_out(0, Location::SameAsFirstInput()); |
| 4695 return result; | 4660 return result; |
| 4696 } | 4661 } |
| 4697 | 4662 |
| 4698 | 4663 |
| 4699 void FloatToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4664 void FloatToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4700 FRegister value = EvenFRegisterOf(locs()->in(0).fpu_reg()); | 4665 FRegister value = EvenFRegisterOf(locs()->in(0).fpu_reg()); |
| 4701 DRegister result = locs()->out(0).fpu_reg(); | 4666 DRegister result = locs()->out(0).fpu_reg(); |
| 4702 __ cvtds(result, value); | 4667 __ cvtds(result, value); |
| 4703 } | 4668 } |
| 4704 | 4669 |
| 4705 | 4670 |
| 4706 LocationSummary* InvokeMathCFunctionInstr::MakeLocationSummary(Zone* zone, | 4671 LocationSummary* InvokeMathCFunctionInstr::MakeLocationSummary(Zone* zone, |
| 4707 bool opt) const { | 4672 bool opt) const { |
| 4708 // Calling convention on MIPS uses D6 and D7 to pass the first two | 4673 // Calling convention on MIPS uses D6 and D7 to pass the first two |
| 4709 // double arguments. | 4674 // double arguments. |
| 4710 ASSERT((InputCount() == 1) || (InputCount() == 2)); | 4675 ASSERT((InputCount() == 1) || (InputCount() == 2)); |
| 4711 const intptr_t kNumTemps = 0; | 4676 const intptr_t kNumTemps = 0; |
| 4712 LocationSummary* result = new(zone) LocationSummary( | 4677 LocationSummary* result = new (zone) |
| 4713 zone, InputCount(), kNumTemps, LocationSummary::kCall); | 4678 LocationSummary(zone, InputCount(), kNumTemps, LocationSummary::kCall); |
| 4714 result->set_in(0, Location::FpuRegisterLocation(D6)); | 4679 result->set_in(0, Location::FpuRegisterLocation(D6)); |
| 4715 if (InputCount() == 2) { | 4680 if (InputCount() == 2) { |
| 4716 result->set_in(1, Location::FpuRegisterLocation(D7)); | 4681 result->set_in(1, Location::FpuRegisterLocation(D7)); |
| 4717 } | 4682 } |
| 4718 result->set_out(0, Location::FpuRegisterLocation(D0)); | 4683 result->set_out(0, Location::FpuRegisterLocation(D0)); |
| 4719 return result; | 4684 return result; |
| 4720 } | 4685 } |
| 4721 | 4686 |
| 4722 | 4687 |
| 4723 // Pseudo code: | 4688 // Pseudo code: |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4842 // double values are passed and returned in vfp registers. | 4807 // double values are passed and returned in vfp registers. |
| 4843 __ CallRuntime(TargetFunction(), InputCount()); | 4808 __ CallRuntime(TargetFunction(), InputCount()); |
| 4844 } | 4809 } |
| 4845 | 4810 |
| 4846 | 4811 |
| 4847 LocationSummary* ExtractNthOutputInstr::MakeLocationSummary(Zone* zone, | 4812 LocationSummary* ExtractNthOutputInstr::MakeLocationSummary(Zone* zone, |
| 4848 bool opt) const { | 4813 bool opt) const { |
| 4849 // Only use this instruction in optimized code. | 4814 // Only use this instruction in optimized code. |
| 4850 ASSERT(opt); | 4815 ASSERT(opt); |
| 4851 const intptr_t kNumInputs = 1; | 4816 const intptr_t kNumInputs = 1; |
| 4852 LocationSummary* summary = new(zone) LocationSummary( | 4817 LocationSummary* summary = |
| 4853 zone, kNumInputs, 0, LocationSummary::kNoCall); | 4818 new (zone) LocationSummary(zone, kNumInputs, 0, LocationSummary::kNoCall); |
| 4854 if (representation() == kUnboxedDouble) { | 4819 if (representation() == kUnboxedDouble) { |
| 4855 if (index() == 0) { | 4820 if (index() == 0) { |
| 4856 summary->set_in(0, Location::Pair(Location::RequiresFpuRegister(), | 4821 summary->set_in( |
| 4857 Location::Any())); | 4822 0, Location::Pair(Location::RequiresFpuRegister(), Location::Any())); |
| 4858 } else { | 4823 } else { |
| 4859 ASSERT(index() == 1); | 4824 ASSERT(index() == 1); |
| 4860 summary->set_in(0, Location::Pair(Location::Any(), | 4825 summary->set_in( |
| 4861 Location::RequiresFpuRegister())); | 4826 0, Location::Pair(Location::Any(), Location::RequiresFpuRegister())); |
| 4862 } | 4827 } |
| 4863 summary->set_out(0, Location::RequiresFpuRegister()); | 4828 summary->set_out(0, Location::RequiresFpuRegister()); |
| 4864 } else { | 4829 } else { |
| 4865 ASSERT(representation() == kTagged); | 4830 ASSERT(representation() == kTagged); |
| 4866 if (index() == 0) { | 4831 if (index() == 0) { |
| 4867 summary->set_in(0, Location::Pair(Location::RequiresRegister(), | 4832 summary->set_in( |
| 4868 Location::Any())); | 4833 0, Location::Pair(Location::RequiresRegister(), Location::Any())); |
| 4869 } else { | 4834 } else { |
| 4870 ASSERT(index() == 1); | 4835 ASSERT(index() == 1); |
| 4871 summary->set_in(0, Location::Pair(Location::Any(), | 4836 summary->set_in( |
| 4872 Location::RequiresRegister())); | 4837 0, Location::Pair(Location::Any(), Location::RequiresRegister())); |
| 4873 } | 4838 } |
| 4874 summary->set_out(0, Location::RequiresRegister()); | 4839 summary->set_out(0, Location::RequiresRegister()); |
| 4875 } | 4840 } |
| 4876 return summary; | 4841 return summary; |
| 4877 } | 4842 } |
| 4878 | 4843 |
| 4879 | 4844 |
| 4880 void ExtractNthOutputInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4845 void ExtractNthOutputInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4881 ASSERT(locs()->in(0).IsPairLocation()); | 4846 ASSERT(locs()->in(0).IsPairLocation()); |
| 4882 PairLocation* pair = locs()->in(0).AsPairLocation(); | 4847 PairLocation* pair = locs()->in(0).AsPairLocation(); |
| 4883 Location in_loc = pair->At(index()); | 4848 Location in_loc = pair->At(index()); |
| 4884 if (representation() == kUnboxedDouble) { | 4849 if (representation() == kUnboxedDouble) { |
| 4885 DRegister out = locs()->out(0).fpu_reg(); | 4850 DRegister out = locs()->out(0).fpu_reg(); |
| 4886 DRegister in = in_loc.fpu_reg(); | 4851 DRegister in = in_loc.fpu_reg(); |
| 4887 __ movd(out, in); | 4852 __ movd(out, in); |
| 4888 } else { | 4853 } else { |
| 4889 ASSERT(representation() == kTagged); | 4854 ASSERT(representation() == kTagged); |
| 4890 Register out = locs()->out(0).reg(); | 4855 Register out = locs()->out(0).reg(); |
| 4891 Register in = in_loc.reg(); | 4856 Register in = in_loc.reg(); |
| 4892 __ mov(out, in); | 4857 __ mov(out, in); |
| 4893 } | 4858 } |
| 4894 } | 4859 } |
| 4895 | 4860 |
| 4896 | 4861 |
| 4897 LocationSummary* MergedMathInstr::MakeLocationSummary(Zone* zone, | 4862 LocationSummary* MergedMathInstr::MakeLocationSummary(Zone* zone, |
| 4898 bool opt) const { | 4863 bool opt) const { |
| 4899 if (kind() == MergedMathInstr::kTruncDivMod) { | 4864 if (kind() == MergedMathInstr::kTruncDivMod) { |
| 4900 const intptr_t kNumInputs = 2; | 4865 const intptr_t kNumInputs = 2; |
| 4901 const intptr_t kNumTemps = 1; | 4866 const intptr_t kNumTemps = 1; |
| 4902 LocationSummary* summary = new(zone) LocationSummary( | 4867 LocationSummary* summary = new (zone) |
| 4903 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4868 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4904 summary->set_in(0, Location::RequiresRegister()); | 4869 summary->set_in(0, Location::RequiresRegister()); |
| 4905 summary->set_in(1, Location::RequiresRegister()); | 4870 summary->set_in(1, Location::RequiresRegister()); |
| 4906 summary->set_temp(0, Location::RequiresRegister()); | 4871 summary->set_temp(0, Location::RequiresRegister()); |
| 4907 // Output is a pair of registers. | 4872 // Output is a pair of registers. |
| 4908 summary->set_out(0, Location::Pair(Location::RequiresRegister(), | 4873 summary->set_out(0, Location::Pair(Location::RequiresRegister(), |
| 4909 Location::RequiresRegister())); | 4874 Location::RequiresRegister())); |
| 4910 return summary; | 4875 return summary; |
| 4911 } | 4876 } |
| 4912 UNIMPLEMENTED(); | 4877 UNIMPLEMENTED(); |
| 4913 return NULL; | 4878 return NULL; |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4968 | 4933 |
| 4969 __ SmiTag(result_div); | 4934 __ SmiTag(result_div); |
| 4970 __ SmiTag(result_mod); | 4935 __ SmiTag(result_mod); |
| 4971 return; | 4936 return; |
| 4972 } | 4937 } |
| 4973 UNIMPLEMENTED(); | 4938 UNIMPLEMENTED(); |
| 4974 } | 4939 } |
| 4975 | 4940 |
| 4976 | 4941 |
| 4977 LocationSummary* PolymorphicInstanceCallInstr::MakeLocationSummary( | 4942 LocationSummary* PolymorphicInstanceCallInstr::MakeLocationSummary( |
| 4978 Zone* zone, bool opt) const { | 4943 Zone* zone, |
| 4944 bool opt) const { |
| 4979 return MakeCallSummary(zone); | 4945 return MakeCallSummary(zone); |
| 4980 } | 4946 } |
| 4981 | 4947 |
| 4982 | 4948 |
| 4983 LocationSummary* BranchInstr::MakeLocationSummary(Zone* zone, | 4949 LocationSummary* BranchInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
| 4984 bool opt) const { | |
| 4985 comparison()->InitializeLocationSummary(zone, opt); | 4950 comparison()->InitializeLocationSummary(zone, opt); |
| 4986 // Branches don't produce a result. | 4951 // Branches don't produce a result. |
| 4987 comparison()->locs()->set_out(0, Location::NoLocation()); | 4952 comparison()->locs()->set_out(0, Location::NoLocation()); |
| 4988 return comparison()->locs(); | 4953 return comparison()->locs(); |
| 4989 } | 4954 } |
| 4990 | 4955 |
| 4991 | 4956 |
| 4992 void BranchInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4957 void BranchInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4993 __ Comment("BranchInstr"); | 4958 __ Comment("BranchInstr"); |
| 4994 comparison()->EmitBranchCode(compiler, this); | 4959 comparison()->EmitBranchCode(compiler, this); |
| 4995 } | 4960 } |
| 4996 | 4961 |
| 4997 | 4962 |
| 4998 LocationSummary* CheckClassInstr::MakeLocationSummary(Zone* zone, | 4963 LocationSummary* CheckClassInstr::MakeLocationSummary(Zone* zone, |
| 4999 bool opt) const { | 4964 bool opt) const { |
| 5000 const intptr_t kNumInputs = 1; | 4965 const intptr_t kNumInputs = 1; |
| 5001 const bool need_mask_temp = IsDenseSwitch() && !IsDenseMask(ComputeCidMask()); | 4966 const bool need_mask_temp = IsDenseSwitch() && !IsDenseMask(ComputeCidMask()); |
| 5002 const intptr_t kNumTemps = !IsNullCheck() ? (need_mask_temp ? 2 : 1) : 0; | 4967 const intptr_t kNumTemps = !IsNullCheck() ? (need_mask_temp ? 2 : 1) : 0; |
| 5003 LocationSummary* summary = new(zone) LocationSummary( | 4968 LocationSummary* summary = new (zone) |
| 5004 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4969 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5005 summary->set_in(0, Location::RequiresRegister()); | 4970 summary->set_in(0, Location::RequiresRegister()); |
| 5006 if (!IsNullCheck()) { | 4971 if (!IsNullCheck()) { |
| 5007 summary->set_temp(0, Location::RequiresRegister()); | 4972 summary->set_temp(0, Location::RequiresRegister()); |
| 5008 if (need_mask_temp) { | 4973 if (need_mask_temp) { |
| 5009 summary->set_temp(1, Location::RequiresRegister()); | 4974 summary->set_temp(1, Location::RequiresRegister()); |
| 5010 } | 4975 } |
| 5011 } | 4976 } |
| 5012 return summary; | 4977 return summary; |
| 5013 } | 4978 } |
| 5014 | 4979 |
| 5015 | 4980 |
| 5016 void CheckClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4981 void CheckClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5017 Label* deopt = compiler->AddDeoptStub(deopt_id(), | 4982 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptCheckClass, |
| 5018 ICData::kDeoptCheckClass, | |
| 5019 licm_hoisted_ ? ICData::kHoisted : 0); | 4983 licm_hoisted_ ? ICData::kHoisted : 0); |
| 5020 if (IsNullCheck()) { | 4984 if (IsNullCheck()) { |
| 5021 if (DeoptIfNull()) { | 4985 if (DeoptIfNull()) { |
| 5022 __ BranchEqual(locs()->in(0).reg(), Object::null_object(), deopt); | 4986 __ BranchEqual(locs()->in(0).reg(), Object::null_object(), deopt); |
| 5023 } else { | 4987 } else { |
| 5024 ASSERT(DeoptIfNotNull()); | 4988 ASSERT(DeoptIfNotNull()); |
| 5025 __ BranchNotEqual(locs()->in(0).reg(), Object::null_object(), deopt); | 4989 __ BranchNotEqual(locs()->in(0).reg(), Object::null_object(), deopt); |
| 5026 } | 4990 } |
| 5027 return; | 4991 return; |
| 5028 } | 4992 } |
| (...skipping 24 matching lines...) Expand all Loading... |
| 5053 // Only need mask if there are missing numbers in the range. | 5017 // Only need mask if there are missing numbers in the range. |
| 5054 ASSERT(cids_.length() > 2); | 5018 ASSERT(cids_.length() > 2); |
| 5055 Register mask_reg = locs()->temp(1).reg(); | 5019 Register mask_reg = locs()->temp(1).reg(); |
| 5056 __ LoadImmediate(mask_reg, 1); | 5020 __ LoadImmediate(mask_reg, 1); |
| 5057 __ sllv(mask_reg, mask_reg, temp); | 5021 __ sllv(mask_reg, mask_reg, temp); |
| 5058 __ AndImmediate(mask_reg, mask_reg, mask); | 5022 __ AndImmediate(mask_reg, mask_reg, mask); |
| 5059 __ beq(mask_reg, ZR, deopt); | 5023 __ beq(mask_reg, ZR, deopt); |
| 5060 } | 5024 } |
| 5061 } else { | 5025 } else { |
| 5062 GrowableArray<CidTarget> sorted_ic_data; | 5026 GrowableArray<CidTarget> sorted_ic_data; |
| 5063 FlowGraphCompiler::SortICDataByCount(unary_checks(), | 5027 FlowGraphCompiler::SortICDataByCount(unary_checks(), &sorted_ic_data, |
| 5064 &sorted_ic_data, | |
| 5065 /* drop_smi = */ true); | 5028 /* drop_smi = */ true); |
| 5066 const intptr_t num_checks = sorted_ic_data.length(); | 5029 const intptr_t num_checks = sorted_ic_data.length(); |
| 5067 for (intptr_t i = 0; i < num_checks; i++) { | 5030 for (intptr_t i = 0; i < num_checks; i++) { |
| 5068 const intptr_t cid = sorted_ic_data[i].cid; | 5031 const intptr_t cid = sorted_ic_data[i].cid; |
| 5069 ASSERT(cid != kSmiCid); | 5032 ASSERT(cid != kSmiCid); |
| 5070 __ LoadImmediate(TMP, cid); | 5033 __ LoadImmediate(TMP, cid); |
| 5071 __ subu(CMPRES1, temp, TMP); | 5034 __ subu(CMPRES1, temp, TMP); |
| 5072 if (i == (num_checks - 1)) { | 5035 if (i == (num_checks - 1)) { |
| 5073 __ bne(CMPRES1, ZR, deopt); | 5036 __ bne(CMPRES1, ZR, deopt); |
| 5074 } else { | 5037 } else { |
| 5075 __ beq(CMPRES1, ZR, &is_ok); | 5038 __ beq(CMPRES1, ZR, &is_ok); |
| 5076 } | 5039 } |
| 5077 } | 5040 } |
| 5078 } | 5041 } |
| 5079 __ Bind(&is_ok); | 5042 __ Bind(&is_ok); |
| 5080 } | 5043 } |
| 5081 | 5044 |
| 5082 | 5045 |
| 5083 LocationSummary* CheckSmiInstr::MakeLocationSummary(Zone* zone, | 5046 LocationSummary* CheckSmiInstr::MakeLocationSummary(Zone* zone, |
| 5084 bool opt) const { | 5047 bool opt) const { |
| 5085 const intptr_t kNumInputs = 1; | 5048 const intptr_t kNumInputs = 1; |
| 5086 const intptr_t kNumTemps = 0; | 5049 const intptr_t kNumTemps = 0; |
| 5087 LocationSummary* summary = new(zone) LocationSummary( | 5050 LocationSummary* summary = new (zone) |
| 5088 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5051 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5089 summary->set_in(0, Location::RequiresRegister()); | 5052 summary->set_in(0, Location::RequiresRegister()); |
| 5090 return summary; | 5053 return summary; |
| 5091 } | 5054 } |
| 5092 | 5055 |
| 5093 | 5056 |
| 5094 void CheckSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5057 void CheckSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5095 __ Comment("CheckSmiInstr"); | 5058 __ Comment("CheckSmiInstr"); |
| 5096 Register value = locs()->in(0).reg(); | 5059 Register value = locs()->in(0).reg(); |
| 5097 Label* deopt = compiler->AddDeoptStub(deopt_id(), | 5060 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptCheckSmi, |
| 5098 ICData::kDeoptCheckSmi, | |
| 5099 licm_hoisted_ ? ICData::kHoisted : 0); | 5061 licm_hoisted_ ? ICData::kHoisted : 0); |
| 5100 __ BranchIfNotSmi(value, deopt); | 5062 __ BranchIfNotSmi(value, deopt); |
| 5101 } | 5063 } |
| 5102 | 5064 |
| 5103 | 5065 |
| 5104 LocationSummary* CheckClassIdInstr::MakeLocationSummary(Zone* zone, | 5066 LocationSummary* CheckClassIdInstr::MakeLocationSummary(Zone* zone, |
| 5105 bool opt) const { | 5067 bool opt) const { |
| 5106 const intptr_t kNumInputs = 1; | 5068 const intptr_t kNumInputs = 1; |
| 5107 const intptr_t kNumTemps = 0; | 5069 const intptr_t kNumTemps = 0; |
| 5108 LocationSummary* summary = new(zone) LocationSummary( | 5070 LocationSummary* summary = new (zone) |
| 5109 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5071 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5110 summary->set_in(0, Location::RequiresRegister()); | 5072 summary->set_in(0, Location::RequiresRegister()); |
| 5111 return summary; | 5073 return summary; |
| 5112 } | 5074 } |
| 5113 | 5075 |
| 5114 | 5076 |
| 5115 void CheckClassIdInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5077 void CheckClassIdInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5116 Register value = locs()->in(0).reg(); | 5078 Register value = locs()->in(0).reg(); |
| 5117 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptCheckClass); | 5079 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptCheckClass); |
| 5118 __ BranchNotEqual(value, Immediate(Smi::RawValue(cid_)), deopt); | 5080 __ BranchNotEqual(value, Immediate(Smi::RawValue(cid_)), deopt); |
| 5119 } | 5081 } |
| 5120 | 5082 |
| 5121 | 5083 |
| 5122 LocationSummary* GenericCheckBoundInstr::MakeLocationSummary(Zone* zone, | 5084 LocationSummary* GenericCheckBoundInstr::MakeLocationSummary(Zone* zone, |
| 5123 bool opt) const { | 5085 bool opt) const { |
| 5124 const intptr_t kNumInputs = 2; | 5086 const intptr_t kNumInputs = 2; |
| 5125 const intptr_t kNumTemps = 0; | 5087 const intptr_t kNumTemps = 0; |
| 5126 LocationSummary* locs = new(zone) LocationSummary( | 5088 LocationSummary* locs = new (zone) LocationSummary( |
| 5127 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); | 5089 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); |
| 5128 locs->set_in(kLengthPos, Location::RequiresRegister()); | 5090 locs->set_in(kLengthPos, Location::RequiresRegister()); |
| 5129 locs->set_in(kIndexPos, Location::RequiresRegister()); | 5091 locs->set_in(kIndexPos, Location::RequiresRegister()); |
| 5130 return locs; | 5092 return locs; |
| 5131 } | 5093 } |
| 5132 | 5094 |
| 5133 | 5095 |
| 5134 class RangeErrorSlowPath : public SlowPathCode { | 5096 class RangeErrorSlowPath : public SlowPathCode { |
| 5135 public: | 5097 public: |
| 5136 RangeErrorSlowPath(GenericCheckBoundInstr* instruction, intptr_t try_index) | 5098 RangeErrorSlowPath(GenericCheckBoundInstr* instruction, intptr_t try_index) |
| 5137 : instruction_(instruction), try_index_(try_index) { } | 5099 : instruction_(instruction), try_index_(try_index) {} |
| 5138 | 5100 |
| 5139 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { | 5101 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5140 if (Assembler::EmittingComments()) { | 5102 if (Assembler::EmittingComments()) { |
| 5141 __ Comment("slow path check bound operation"); | 5103 __ Comment("slow path check bound operation"); |
| 5142 } | 5104 } |
| 5143 __ Bind(entry_label()); | 5105 __ Bind(entry_label()); |
| 5144 LocationSummary* locs = instruction_->locs(); | 5106 LocationSummary* locs = instruction_->locs(); |
| 5145 __ Push(locs->in(0).reg()); | 5107 __ Push(locs->in(0).reg()); |
| 5146 __ Push(locs->in(1).reg()); | 5108 __ Push(locs->in(1).reg()); |
| 5147 __ CallRuntime(kRangeErrorRuntimeEntry, 2); | 5109 __ CallRuntime(kRangeErrorRuntimeEntry, 2); |
| 5148 compiler->pc_descriptors_list()->AddDescriptor( | 5110 compiler->pc_descriptors_list()->AddDescriptor( |
| 5149 RawPcDescriptors::kOther, | 5111 RawPcDescriptors::kOther, compiler->assembler()->CodeSize(), |
| 5150 compiler->assembler()->CodeSize(), | 5112 instruction_->deopt_id(), instruction_->token_pos(), try_index_); |
| 5151 instruction_->deopt_id(), | |
| 5152 instruction_->token_pos(), | |
| 5153 try_index_); | |
| 5154 __ break_(0); | 5113 __ break_(0); |
| 5155 } | 5114 } |
| 5156 | 5115 |
| 5157 private: | 5116 private: |
| 5158 GenericCheckBoundInstr* instruction_; | 5117 GenericCheckBoundInstr* instruction_; |
| 5159 intptr_t try_index_; | 5118 intptr_t try_index_; |
| 5160 }; | 5119 }; |
| 5161 | 5120 |
| 5162 | 5121 |
| 5163 void GenericCheckBoundInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5122 void GenericCheckBoundInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| (...skipping 10 matching lines...) Expand all Loading... |
| 5174 __ BranchIfNotSmi(index, slow_path->entry_label()); | 5133 __ BranchIfNotSmi(index, slow_path->entry_label()); |
| 5175 } | 5134 } |
| 5176 __ BranchUnsignedGreaterEqual(index, length, slow_path->entry_label()); | 5135 __ BranchUnsignedGreaterEqual(index, length, slow_path->entry_label()); |
| 5177 } | 5136 } |
| 5178 | 5137 |
| 5179 | 5138 |
| 5180 LocationSummary* CheckArrayBoundInstr::MakeLocationSummary(Zone* zone, | 5139 LocationSummary* CheckArrayBoundInstr::MakeLocationSummary(Zone* zone, |
| 5181 bool opt) const { | 5140 bool opt) const { |
| 5182 const intptr_t kNumInputs = 2; | 5141 const intptr_t kNumInputs = 2; |
| 5183 const intptr_t kNumTemps = 0; | 5142 const intptr_t kNumTemps = 0; |
| 5184 LocationSummary* locs = new(zone) LocationSummary( | 5143 LocationSummary* locs = new (zone) |
| 5185 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5144 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5186 locs->set_in(kLengthPos, Location::RegisterOrSmiConstant(length())); | 5145 locs->set_in(kLengthPos, Location::RegisterOrSmiConstant(length())); |
| 5187 locs->set_in(kIndexPos, Location::RegisterOrSmiConstant(index())); | 5146 locs->set_in(kIndexPos, Location::RegisterOrSmiConstant(index())); |
| 5188 return locs; | 5147 return locs; |
| 5189 } | 5148 } |
| 5190 | 5149 |
| 5191 | 5150 |
| 5192 void CheckArrayBoundInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5151 void CheckArrayBoundInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5193 uint32_t flags = generalized_ ? ICData::kGeneralized : 0; | 5152 uint32_t flags = generalized_ ? ICData::kGeneralized : 0; |
| 5194 flags |= licm_hoisted_ ? ICData::kHoisted : 0; | 5153 flags |= licm_hoisted_ ? ICData::kHoisted : 0; |
| 5195 Label* deopt = compiler->AddDeoptStub( | 5154 Label* deopt = |
| 5196 deopt_id(), | 5155 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptCheckArrayBound, flags); |
| 5197 ICData::kDeoptCheckArrayBound, | |
| 5198 flags); | |
| 5199 | 5156 |
| 5200 Location length_loc = locs()->in(kLengthPos); | 5157 Location length_loc = locs()->in(kLengthPos); |
| 5201 Location index_loc = locs()->in(kIndexPos); | 5158 Location index_loc = locs()->in(kIndexPos); |
| 5202 | 5159 |
| 5203 if (length_loc.IsConstant() && index_loc.IsConstant()) { | 5160 if (length_loc.IsConstant() && index_loc.IsConstant()) { |
| 5204 ASSERT((Smi::Cast(length_loc.constant()).Value() <= | 5161 ASSERT((Smi::Cast(length_loc.constant()).Value() <= |
| 5205 Smi::Cast(index_loc.constant()).Value()) || | 5162 Smi::Cast(index_loc.constant()).Value()) || |
| 5206 (Smi::Cast(index_loc.constant()).Value() < 0)); | 5163 (Smi::Cast(index_loc.constant()).Value() < 0)); |
| 5207 // Unconditionally deoptimize for constant bounds checks because they | 5164 // Unconditionally deoptimize for constant bounds checks because they |
| 5208 // only occur only when index is out-of-bounds. | 5165 // only occur only when index is out-of-bounds. |
| (...skipping 26 matching lines...) Expand all Loading... |
| 5235 __ BranchIfNotSmi(index, deopt); | 5192 __ BranchIfNotSmi(index, deopt); |
| 5236 } | 5193 } |
| 5237 __ BranchUnsignedGreaterEqual(index, length, deopt); | 5194 __ BranchUnsignedGreaterEqual(index, length, deopt); |
| 5238 } | 5195 } |
| 5239 } | 5196 } |
| 5240 | 5197 |
| 5241 LocationSummary* BinaryMintOpInstr::MakeLocationSummary(Zone* zone, | 5198 LocationSummary* BinaryMintOpInstr::MakeLocationSummary(Zone* zone, |
| 5242 bool opt) const { | 5199 bool opt) const { |
| 5243 const intptr_t kNumInputs = 2; | 5200 const intptr_t kNumInputs = 2; |
| 5244 const intptr_t kNumTemps = 0; | 5201 const intptr_t kNumTemps = 0; |
| 5245 LocationSummary* summary = new(zone) LocationSummary( | 5202 LocationSummary* summary = new (zone) |
| 5246 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5203 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5247 summary->set_in(0, Location::Pair(Location::RequiresRegister(), | 5204 summary->set_in(0, Location::Pair(Location::RequiresRegister(), |
| 5248 Location::RequiresRegister())); | 5205 Location::RequiresRegister())); |
| 5249 summary->set_in(1, Location::Pair(Location::RequiresRegister(), | 5206 summary->set_in(1, Location::Pair(Location::RequiresRegister(), |
| 5250 Location::RequiresRegister())); | 5207 Location::RequiresRegister())); |
| 5251 summary->set_out(0, Location::Pair(Location::RequiresRegister(), | 5208 summary->set_out(0, Location::Pair(Location::RequiresRegister(), |
| 5252 Location::RequiresRegister())); | 5209 Location::RequiresRegister())); |
| 5253 return summary; | 5210 return summary; |
| 5254 } | 5211 } |
| 5255 | 5212 |
| 5256 | 5213 |
| (...skipping 17 matching lines...) Expand all Loading... |
| 5274 __ and_(out_lo, left_lo, right_lo); | 5231 __ and_(out_lo, left_lo, right_lo); |
| 5275 __ and_(out_hi, left_hi, right_hi); | 5232 __ and_(out_hi, left_hi, right_hi); |
| 5276 break; | 5233 break; |
| 5277 } | 5234 } |
| 5278 case Token::kBIT_OR: { | 5235 case Token::kBIT_OR: { |
| 5279 __ or_(out_lo, left_lo, right_lo); | 5236 __ or_(out_lo, left_lo, right_lo); |
| 5280 __ or_(out_hi, left_hi, right_hi); | 5237 __ or_(out_hi, left_hi, right_hi); |
| 5281 break; | 5238 break; |
| 5282 } | 5239 } |
| 5283 case Token::kBIT_XOR: { | 5240 case Token::kBIT_XOR: { |
| 5284 __ xor_(out_lo, left_lo, right_lo); | 5241 __ xor_(out_lo, left_lo, right_lo); |
| 5285 __ xor_(out_hi, left_hi, right_hi); | 5242 __ xor_(out_hi, left_hi, right_hi); |
| 5286 break; | 5243 break; |
| 5287 } | 5244 } |
| 5288 case Token::kADD: | 5245 case Token::kADD: |
| 5289 case Token::kSUB: { | 5246 case Token::kSUB: { |
| 5290 if (op_kind() == Token::kADD) { | 5247 if (op_kind() == Token::kADD) { |
| 5291 __ addu(out_lo, left_lo, right_lo); | 5248 __ addu(out_lo, left_lo, right_lo); |
| 5292 __ sltu(TMP, out_lo, left_lo); // TMP = carry of left_lo + right_lo. | 5249 __ sltu(TMP, out_lo, left_lo); // TMP = carry of left_lo + right_lo. |
| 5293 __ addu(out_hi, left_hi, right_hi); | 5250 __ addu(out_hi, left_hi, right_hi); |
| 5294 __ addu(out_hi, out_hi, TMP); | 5251 __ addu(out_hi, out_hi, TMP); |
| 5295 if (can_overflow()) { | 5252 if (can_overflow()) { |
| 5296 __ xor_(CMPRES1, out_hi, left_hi); | 5253 __ xor_(CMPRES1, out_hi, left_hi); |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5329 default: | 5286 default: |
| 5330 UNREACHABLE(); | 5287 UNREACHABLE(); |
| 5331 } | 5288 } |
| 5332 } | 5289 } |
| 5333 | 5290 |
| 5334 | 5291 |
| 5335 LocationSummary* ShiftMintOpInstr::MakeLocationSummary(Zone* zone, | 5292 LocationSummary* ShiftMintOpInstr::MakeLocationSummary(Zone* zone, |
| 5336 bool opt) const { | 5293 bool opt) const { |
| 5337 const intptr_t kNumInputs = 2; | 5294 const intptr_t kNumInputs = 2; |
| 5338 const intptr_t kNumTemps = 0; | 5295 const intptr_t kNumTemps = 0; |
| 5339 LocationSummary* summary = new(zone) LocationSummary( | 5296 LocationSummary* summary = new (zone) |
| 5340 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5297 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5341 summary->set_in(0, Location::Pair(Location::RequiresRegister(), | 5298 summary->set_in(0, Location::Pair(Location::RequiresRegister(), |
| 5342 Location::RequiresRegister())); | 5299 Location::RequiresRegister())); |
| 5343 summary->set_in(1, Location::WritableRegisterOrSmiConstant(right())); | 5300 summary->set_in(1, Location::WritableRegisterOrSmiConstant(right())); |
| 5344 summary->set_out(0, Location::Pair(Location::RequiresRegister(), | 5301 summary->set_out(0, Location::Pair(Location::RequiresRegister(), |
| 5345 Location::RequiresRegister())); | 5302 Location::RequiresRegister())); |
| 5346 return summary; | 5303 return summary; |
| 5347 } | 5304 } |
| 5348 | 5305 |
| 5349 | 5306 |
| 5350 static const intptr_t kMintShiftCountLimit = 63; | 5307 static const intptr_t kMintShiftCountLimit = 63; |
| 5351 | 5308 |
| 5352 bool ShiftMintOpInstr::has_shift_count_check() const { | 5309 bool ShiftMintOpInstr::has_shift_count_check() const { |
| 5353 return !RangeUtils::IsWithin( | 5310 return !RangeUtils::IsWithin(right()->definition()->range(), 0, |
| 5354 right()->definition()->range(), 0, kMintShiftCountLimit); | 5311 kMintShiftCountLimit); |
| 5355 } | 5312 } |
| 5356 | 5313 |
| 5357 | 5314 |
| 5358 void ShiftMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5315 void ShiftMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5359 PairLocation* left_pair = locs()->in(0).AsPairLocation(); | 5316 PairLocation* left_pair = locs()->in(0).AsPairLocation(); |
| 5360 Register left_lo = left_pair->At(0).reg(); | 5317 Register left_lo = left_pair->At(0).reg(); |
| 5361 Register left_hi = left_pair->At(1).reg(); | 5318 Register left_hi = left_pair->At(1).reg(); |
| 5362 PairLocation* out_pair = locs()->out(0).AsPairLocation(); | 5319 PairLocation* out_pair = locs()->out(0).AsPairLocation(); |
| 5363 Register out_lo = out_pair->At(0).reg(); | 5320 Register out_lo = out_pair->At(0).reg(); |
| 5364 Register out_hi = out_pair->At(1).reg(); | 5321 Register out_hi = out_pair->At(1).reg(); |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5431 // Code below assumes shift amount is not 0 (cannot shift by 32 - 0). | 5388 // Code below assumes shift amount is not 0 (cannot shift by 32 - 0). |
| 5432 Label non_zero_shift, done; | 5389 Label non_zero_shift, done; |
| 5433 __ bne(shift, ZR, &non_zero_shift); | 5390 __ bne(shift, ZR, &non_zero_shift); |
| 5434 __ delay_slot()->mov(out_lo, left_lo); | 5391 __ delay_slot()->mov(out_lo, left_lo); |
| 5435 __ b(&done); | 5392 __ b(&done); |
| 5436 __ delay_slot()->mov(out_hi, left_hi); | 5393 __ delay_slot()->mov(out_hi, left_hi); |
| 5437 __ Bind(&non_zero_shift); | 5394 __ Bind(&non_zero_shift); |
| 5438 | 5395 |
| 5439 // Deopt if shift is larger than 63 or less than 0. | 5396 // Deopt if shift is larger than 63 or less than 0. |
| 5440 if (has_shift_count_check()) { | 5397 if (has_shift_count_check()) { |
| 5441 __ sltiu(CMPRES1, shift, Immediate(2*(kMintShiftCountLimit + 1))); | 5398 __ sltiu(CMPRES1, shift, Immediate(2 * (kMintShiftCountLimit + 1))); |
| 5442 __ beq(CMPRES1, ZR, deopt); | 5399 __ beq(CMPRES1, ZR, deopt); |
| 5443 // Untag shift count. | 5400 // Untag shift count. |
| 5444 __ delay_slot()->SmiUntag(shift); | 5401 __ delay_slot()->SmiUntag(shift); |
| 5445 } else { | 5402 } else { |
| 5446 // Untag shift count. | 5403 // Untag shift count. |
| 5447 __ SmiUntag(shift); | 5404 __ SmiUntag(shift); |
| 5448 } | 5405 } |
| 5449 | 5406 |
| 5450 switch (op_kind()) { | 5407 switch (op_kind()) { |
| 5451 case Token::kSHR: { | 5408 case Token::kSHR: { |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5515 } | 5472 } |
| 5516 __ Bind(&done); | 5473 __ Bind(&done); |
| 5517 } | 5474 } |
| 5518 } | 5475 } |
| 5519 | 5476 |
| 5520 | 5477 |
| 5521 LocationSummary* UnaryMintOpInstr::MakeLocationSummary(Zone* zone, | 5478 LocationSummary* UnaryMintOpInstr::MakeLocationSummary(Zone* zone, |
| 5522 bool opt) const { | 5479 bool opt) const { |
| 5523 const intptr_t kNumInputs = 1; | 5480 const intptr_t kNumInputs = 1; |
| 5524 const intptr_t kNumTemps = 0; | 5481 const intptr_t kNumTemps = 0; |
| 5525 LocationSummary* summary = new(zone) LocationSummary( | 5482 LocationSummary* summary = new (zone) |
| 5526 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5483 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5527 summary->set_in(0, Location::Pair(Location::RequiresRegister(), | 5484 summary->set_in(0, Location::Pair(Location::RequiresRegister(), |
| 5528 Location::RequiresRegister())); | 5485 Location::RequiresRegister())); |
| 5529 summary->set_out(0, Location::Pair(Location::RequiresRegister(), | 5486 summary->set_out(0, Location::Pair(Location::RequiresRegister(), |
| 5530 Location::RequiresRegister())); | 5487 Location::RequiresRegister())); |
| 5531 return summary; | 5488 return summary; |
| 5532 } | 5489 } |
| 5533 | 5490 |
| 5534 | 5491 |
| 5535 void UnaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5492 void UnaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5536 ASSERT(op_kind() == Token::kBIT_NOT); | 5493 ASSERT(op_kind() == Token::kBIT_NOT); |
| (...skipping 22 matching lines...) Expand all Loading... |
| 5559 | 5516 |
| 5560 CompileType UnaryUint32OpInstr::ComputeType() const { | 5517 CompileType UnaryUint32OpInstr::ComputeType() const { |
| 5561 return CompileType::Int(); | 5518 return CompileType::Int(); |
| 5562 } | 5519 } |
| 5563 | 5520 |
| 5564 | 5521 |
| 5565 LocationSummary* BinaryUint32OpInstr::MakeLocationSummary(Zone* zone, | 5522 LocationSummary* BinaryUint32OpInstr::MakeLocationSummary(Zone* zone, |
| 5566 bool opt) const { | 5523 bool opt) const { |
| 5567 const intptr_t kNumInputs = 2; | 5524 const intptr_t kNumInputs = 2; |
| 5568 const intptr_t kNumTemps = 0; | 5525 const intptr_t kNumTemps = 0; |
| 5569 LocationSummary* summary = new(zone) LocationSummary( | 5526 LocationSummary* summary = new (zone) |
| 5570 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5527 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5571 summary->set_in(0, Location::RequiresRegister()); | 5528 summary->set_in(0, Location::RequiresRegister()); |
| 5572 summary->set_in(1, Location::RequiresRegister()); | 5529 summary->set_in(1, Location::RequiresRegister()); |
| 5573 summary->set_out(0, Location::RequiresRegister()); | 5530 summary->set_out(0, Location::RequiresRegister()); |
| 5574 return summary; | 5531 return summary; |
| 5575 } | 5532 } |
| 5576 | 5533 |
| 5577 | 5534 |
| 5578 void BinaryUint32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5535 void BinaryUint32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5579 Register left = locs()->in(0).reg(); | 5536 Register left = locs()->in(0).reg(); |
| 5580 Register right = locs()->in(1).reg(); | 5537 Register right = locs()->in(1).reg(); |
| (...skipping 22 matching lines...) Expand all Loading... |
| 5603 default: | 5560 default: |
| 5604 UNREACHABLE(); | 5561 UNREACHABLE(); |
| 5605 } | 5562 } |
| 5606 } | 5563 } |
| 5607 | 5564 |
| 5608 | 5565 |
| 5609 LocationSummary* ShiftUint32OpInstr::MakeLocationSummary(Zone* zone, | 5566 LocationSummary* ShiftUint32OpInstr::MakeLocationSummary(Zone* zone, |
| 5610 bool opt) const { | 5567 bool opt) const { |
| 5611 const intptr_t kNumInputs = 2; | 5568 const intptr_t kNumInputs = 2; |
| 5612 const intptr_t kNumTemps = 1; | 5569 const intptr_t kNumTemps = 1; |
| 5613 LocationSummary* summary = new(zone) LocationSummary( | 5570 LocationSummary* summary = new (zone) |
| 5614 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5571 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5615 summary->set_in(0, Location::RequiresRegister()); | 5572 summary->set_in(0, Location::RequiresRegister()); |
| 5616 summary->set_in(1, Location::RegisterOrSmiConstant(right())); | 5573 summary->set_in(1, Location::RegisterOrSmiConstant(right())); |
| 5617 summary->set_temp(0, Location::RequiresRegister()); | 5574 summary->set_temp(0, Location::RequiresRegister()); |
| 5618 summary->set_out(0, Location::RequiresRegister()); | 5575 summary->set_out(0, Location::RequiresRegister()); |
| 5619 return summary; | 5576 return summary; |
| 5620 } | 5577 } |
| 5621 | 5578 |
| 5622 | 5579 |
| 5623 void ShiftUint32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5580 void ShiftUint32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5624 const intptr_t kShifterLimit = 31; | 5581 const intptr_t kShifterLimit = 31; |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5672 default: | 5629 default: |
| 5673 UNREACHABLE(); | 5630 UNREACHABLE(); |
| 5674 } | 5631 } |
| 5675 } | 5632 } |
| 5676 | 5633 |
| 5677 | 5634 |
| 5678 LocationSummary* UnaryUint32OpInstr::MakeLocationSummary(Zone* zone, | 5635 LocationSummary* UnaryUint32OpInstr::MakeLocationSummary(Zone* zone, |
| 5679 bool opt) const { | 5636 bool opt) const { |
| 5680 const intptr_t kNumInputs = 1; | 5637 const intptr_t kNumInputs = 1; |
| 5681 const intptr_t kNumTemps = 0; | 5638 const intptr_t kNumTemps = 0; |
| 5682 LocationSummary* summary = new(zone) LocationSummary( | 5639 LocationSummary* summary = new (zone) |
| 5683 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5640 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5684 summary->set_in(0, Location::RequiresRegister()); | 5641 summary->set_in(0, Location::RequiresRegister()); |
| 5685 summary->set_out(0, Location::RequiresRegister()); | 5642 summary->set_out(0, Location::RequiresRegister()); |
| 5686 return summary; | 5643 return summary; |
| 5687 } | 5644 } |
| 5688 | 5645 |
| 5689 | 5646 |
| 5690 void UnaryUint32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5647 void UnaryUint32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5691 Register left = locs()->in(0).reg(); | 5648 Register left = locs()->in(0).reg(); |
| 5692 Register out = locs()->out(0).reg(); | 5649 Register out = locs()->out(0).reg(); |
| 5693 ASSERT(left != out); | 5650 ASSERT(left != out); |
| 5694 | 5651 |
| 5695 ASSERT(op_kind() == Token::kBIT_NOT); | 5652 ASSERT(op_kind() == Token::kBIT_NOT); |
| 5696 | 5653 |
| 5697 __ nor(out, ZR, left); | 5654 __ nor(out, ZR, left); |
| 5698 } | 5655 } |
| 5699 | 5656 |
| 5700 | 5657 |
| 5701 DEFINE_UNIMPLEMENTED_INSTRUCTION(BinaryInt32OpInstr) | 5658 DEFINE_UNIMPLEMENTED_INSTRUCTION(BinaryInt32OpInstr) |
| 5702 | 5659 |
| 5703 | 5660 |
| 5704 LocationSummary* UnboxedIntConverterInstr::MakeLocationSummary(Zone* zone, | 5661 LocationSummary* UnboxedIntConverterInstr::MakeLocationSummary(Zone* zone, |
| 5705 bool opt) const { | 5662 bool opt) const { |
| 5706 const intptr_t kNumInputs = 1; | 5663 const intptr_t kNumInputs = 1; |
| 5707 const intptr_t kNumTemps = 0; | 5664 const intptr_t kNumTemps = 0; |
| 5708 LocationSummary* summary = new(zone) LocationSummary( | 5665 LocationSummary* summary = new (zone) |
| 5709 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5666 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5710 if (from() == kUnboxedMint) { | 5667 if (from() == kUnboxedMint) { |
| 5711 ASSERT((to() == kUnboxedUint32) || (to() == kUnboxedInt32)); | 5668 ASSERT((to() == kUnboxedUint32) || (to() == kUnboxedInt32)); |
| 5712 summary->set_in(0, Location::Pair(Location::RequiresRegister(), | 5669 summary->set_in(0, Location::Pair(Location::RequiresRegister(), |
| 5713 Location::RequiresRegister())); | 5670 Location::RequiresRegister())); |
| 5714 summary->set_out(0, Location::RequiresRegister()); | 5671 summary->set_out(0, Location::RequiresRegister()); |
| 5715 } else if (to() == kUnboxedMint) { | 5672 } else if (to() == kUnboxedMint) { |
| 5716 ASSERT((from() == kUnboxedUint32) || (from() == kUnboxedInt32)); | 5673 ASSERT((from() == kUnboxedUint32) || (from() == kUnboxedInt32)); |
| 5717 summary->set_in(0, Location::RequiresRegister()); | 5674 summary->set_in(0, Location::RequiresRegister()); |
| 5718 summary->set_out(0, Location::Pair(Location::RequiresRegister(), | 5675 summary->set_out(0, Location::Pair(Location::RequiresRegister(), |
| 5719 Location::RequiresRegister())); | 5676 Location::RequiresRegister())); |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5769 } else { | 5726 } else { |
| 5770 ASSERT(from() == kUnboxedInt32); | 5727 ASSERT(from() == kUnboxedInt32); |
| 5771 __ sra(out_hi, in, 31); | 5728 __ sra(out_hi, in, 31); |
| 5772 } | 5729 } |
| 5773 } else { | 5730 } else { |
| 5774 UNREACHABLE(); | 5731 UNREACHABLE(); |
| 5775 } | 5732 } |
| 5776 } | 5733 } |
| 5777 | 5734 |
| 5778 | 5735 |
| 5779 LocationSummary* ThrowInstr::MakeLocationSummary(Zone* zone, | 5736 LocationSummary* ThrowInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
| 5780 bool opt) const { | 5737 return new (zone) LocationSummary(zone, 0, 0, LocationSummary::kCall); |
| 5781 return new(zone) LocationSummary(zone, 0, 0, LocationSummary::kCall); | |
| 5782 } | 5738 } |
| 5783 | 5739 |
| 5784 | 5740 |
| 5785 | |
| 5786 void ThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5741 void ThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5787 compiler->GenerateRuntimeCall(token_pos(), | 5742 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), kThrowRuntimeEntry, 1, |
| 5788 deopt_id(), | |
| 5789 kThrowRuntimeEntry, | |
| 5790 1, | |
| 5791 locs()); | 5743 locs()); |
| 5792 __ break_(0); | 5744 __ break_(0); |
| 5793 } | 5745 } |
| 5794 | 5746 |
| 5795 | 5747 |
| 5796 LocationSummary* ReThrowInstr::MakeLocationSummary(Zone* zone, | 5748 LocationSummary* ReThrowInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
| 5797 bool opt) const { | 5749 return new (zone) LocationSummary(zone, 0, 0, LocationSummary::kCall); |
| 5798 return new(zone) LocationSummary(zone, 0, 0, LocationSummary::kCall); | |
| 5799 } | 5750 } |
| 5800 | 5751 |
| 5801 | 5752 |
| 5802 void ReThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5753 void ReThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5803 compiler->SetNeedsStacktrace(catch_try_index()); | 5754 compiler->SetNeedsStacktrace(catch_try_index()); |
| 5804 compiler->GenerateRuntimeCall(token_pos(), | 5755 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), kReThrowRuntimeEntry, |
| 5805 deopt_id(), | 5756 2, locs()); |
| 5806 kReThrowRuntimeEntry, | |
| 5807 2, | |
| 5808 locs()); | |
| 5809 __ break_(0); | 5757 __ break_(0); |
| 5810 } | 5758 } |
| 5811 | 5759 |
| 5812 | 5760 |
| 5813 LocationSummary* StopInstr::MakeLocationSummary(Zone* zone, | 5761 LocationSummary* StopInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
| 5814 bool opt) const { | 5762 return new (zone) LocationSummary(zone, 0, 0, LocationSummary::kNoCall); |
| 5815 return new(zone) LocationSummary(zone, 0, 0, LocationSummary::kNoCall); | |
| 5816 } | 5763 } |
| 5817 | 5764 |
| 5818 | 5765 |
| 5819 void StopInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5766 void StopInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5820 __ Stop(message()); | 5767 __ Stop(message()); |
| 5821 } | 5768 } |
| 5822 | 5769 |
| 5823 | 5770 |
| 5824 void GraphEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5771 void GraphEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5825 if (!compiler->CanFallThroughTo(normal_entry())) { | 5772 if (!compiler->CanFallThroughTo(normal_entry())) { |
| 5826 __ b(compiler->GetJumpLabel(normal_entry())); | 5773 __ b(compiler->GetJumpLabel(normal_entry())); |
| 5827 } | 5774 } |
| 5828 } | 5775 } |
| 5829 | 5776 |
| 5830 | 5777 |
| 5831 LocationSummary* GotoInstr::MakeLocationSummary(Zone* zone, | 5778 LocationSummary* GotoInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
| 5832 bool opt) const { | 5779 return new (zone) LocationSummary(zone, 0, 0, LocationSummary::kNoCall); |
| 5833 return new(zone) LocationSummary(zone, 0, 0, LocationSummary::kNoCall); | |
| 5834 } | 5780 } |
| 5835 | 5781 |
| 5836 | 5782 |
| 5837 void GotoInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5783 void GotoInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5838 __ Comment("GotoInstr"); | 5784 __ Comment("GotoInstr"); |
| 5839 if (!compiler->is_optimizing()) { | 5785 if (!compiler->is_optimizing()) { |
| 5840 if (FLAG_reorder_basic_blocks) { | 5786 if (FLAG_reorder_basic_blocks) { |
| 5841 compiler->EmitEdgeCounter(block()->preorder_number()); | 5787 compiler->EmitEdgeCounter(block()->preorder_number()); |
| 5842 } | 5788 } |
| 5843 // Add a deoptimization descriptor for deoptimizing instructions that | 5789 // Add a deoptimization descriptor for deoptimizing instructions that |
| 5844 // may be inserted before this instruction. | 5790 // may be inserted before this instruction. |
| 5845 compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt, | 5791 compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt, GetDeoptId(), |
| 5846 GetDeoptId(), | |
| 5847 TokenPosition::kNoSource); | 5792 TokenPosition::kNoSource); |
| 5848 } | 5793 } |
| 5849 if (HasParallelMove()) { | 5794 if (HasParallelMove()) { |
| 5850 compiler->parallel_move_resolver()->EmitNativeCode(parallel_move()); | 5795 compiler->parallel_move_resolver()->EmitNativeCode(parallel_move()); |
| 5851 } | 5796 } |
| 5852 | 5797 |
| 5853 // We can fall through if the successor is the next block in the list. | 5798 // We can fall through if the successor is the next block in the list. |
| 5854 // Otherwise, we need a jump. | 5799 // Otherwise, we need a jump. |
| 5855 if (!compiler->CanFallThroughTo(successor())) { | 5800 if (!compiler->CanFallThroughTo(successor())) { |
| 5856 __ b(compiler->GetJumpLabel(successor())); | 5801 __ b(compiler->GetJumpLabel(successor())); |
| 5857 } | 5802 } |
| 5858 } | 5803 } |
| 5859 | 5804 |
| 5860 | 5805 |
| 5861 LocationSummary* IndirectGotoInstr::MakeLocationSummary(Zone* zone, | 5806 LocationSummary* IndirectGotoInstr::MakeLocationSummary(Zone* zone, |
| 5862 bool opt) const { | 5807 bool opt) const { |
| 5863 const intptr_t kNumInputs = 1; | 5808 const intptr_t kNumInputs = 1; |
| 5864 const intptr_t kNumTemps = 1; | 5809 const intptr_t kNumTemps = 1; |
| 5865 | 5810 |
| 5866 LocationSummary* summary = new(zone) LocationSummary( | 5811 LocationSummary* summary = new (zone) |
| 5867 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5812 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5868 | 5813 |
| 5869 summary->set_in(0, Location::RequiresRegister()); | 5814 summary->set_in(0, Location::RequiresRegister()); |
| 5870 summary->set_temp(0, Location::RequiresRegister()); | 5815 summary->set_temp(0, Location::RequiresRegister()); |
| 5871 | 5816 |
| 5872 return summary; | 5817 return summary; |
| 5873 } | 5818 } |
| 5874 | 5819 |
| 5875 | 5820 |
| 5876 void IndirectGotoInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5821 void IndirectGotoInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5877 Register target_reg = locs()->temp_slot(0)->reg(); | 5822 Register target_reg = locs()->temp_slot(0)->reg(); |
| 5878 | 5823 |
| 5879 __ GetNextPC(target_reg, TMP); | 5824 __ GetNextPC(target_reg, TMP); |
| 5880 const intptr_t entry_offset = | 5825 const intptr_t entry_offset = __ CodeSize() - 1 * Instr::kInstrSize; |
| 5881 __ CodeSize() - 1 * Instr::kInstrSize; | |
| 5882 __ AddImmediate(target_reg, target_reg, -entry_offset); | 5826 __ AddImmediate(target_reg, target_reg, -entry_offset); |
| 5883 | 5827 |
| 5884 // Add the offset. | 5828 // Add the offset. |
| 5885 Register offset_reg = locs()->in(0).reg(); | 5829 Register offset_reg = locs()->in(0).reg(); |
| 5886 if (offset()->definition()->representation() == kTagged) { | 5830 if (offset()->definition()->representation() == kTagged) { |
| 5887 __ SmiUntag(offset_reg); | 5831 __ SmiUntag(offset_reg); |
| 5888 } | 5832 } |
| 5889 __ addu(target_reg, target_reg, offset_reg); | 5833 __ addu(target_reg, target_reg, offset_reg); |
| 5890 | 5834 |
| 5891 // Jump to the absolute address. | 5835 // Jump to the absolute address. |
| 5892 __ jr(target_reg); | 5836 __ jr(target_reg); |
| 5893 } | 5837 } |
| 5894 | 5838 |
| 5895 | 5839 |
| 5896 LocationSummary* StrictCompareInstr::MakeLocationSummary(Zone* zone, | 5840 LocationSummary* StrictCompareInstr::MakeLocationSummary(Zone* zone, |
| 5897 bool opt) const { | 5841 bool opt) const { |
| 5898 const intptr_t kNumInputs = 2; | 5842 const intptr_t kNumInputs = 2; |
| 5899 const intptr_t kNumTemps = 0; | 5843 const intptr_t kNumTemps = 0; |
| 5900 if (needs_number_check()) { | 5844 if (needs_number_check()) { |
| 5901 LocationSummary* locs = new(zone) LocationSummary( | 5845 LocationSummary* locs = new (zone) |
| 5902 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 5846 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
| 5903 locs->set_in(0, Location::RegisterLocation(A0)); | 5847 locs->set_in(0, Location::RegisterLocation(A0)); |
| 5904 locs->set_in(1, Location::RegisterLocation(A1)); | 5848 locs->set_in(1, Location::RegisterLocation(A1)); |
| 5905 locs->set_out(0, Location::RegisterLocation(A0)); | 5849 locs->set_out(0, Location::RegisterLocation(A0)); |
| 5906 return locs; | 5850 return locs; |
| 5907 } | 5851 } |
| 5908 LocationSummary* locs = new(zone) LocationSummary( | 5852 LocationSummary* locs = new (zone) |
| 5909 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5853 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5910 locs->set_in(0, Location::RegisterOrConstant(left())); | 5854 locs->set_in(0, Location::RegisterOrConstant(left())); |
| 5911 // Only one of the inputs can be a constant. Choose register if the first one | 5855 // Only one of the inputs can be a constant. Choose register if the first one |
| 5912 // is a constant. | 5856 // is a constant. |
| 5913 locs->set_in(1, locs->in(0).IsConstant() | 5857 locs->set_in(1, locs->in(0).IsConstant() |
| 5914 ? Location::RequiresRegister() | 5858 ? Location::RequiresRegister() |
| 5915 : Location::RegisterOrConstant(right())); | 5859 : Location::RegisterOrConstant(right())); |
| 5916 locs->set_out(0, Location::RequiresRegister()); | 5860 locs->set_out(0, Location::RequiresRegister()); |
| 5917 return locs; | 5861 return locs; |
| 5918 } | 5862 } |
| 5919 | 5863 |
| 5920 | 5864 |
| 5921 Condition StrictCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler, | 5865 Condition StrictCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
| 5922 BranchLabels labels) { | 5866 BranchLabels labels) { |
| 5923 Location left = locs()->in(0); | 5867 Location left = locs()->in(0); |
| 5924 Location right = locs()->in(1); | 5868 Location right = locs()->in(1); |
| 5925 ASSERT(!left.IsConstant() || !right.IsConstant()); | 5869 ASSERT(!left.IsConstant() || !right.IsConstant()); |
| 5926 Condition true_condition; | 5870 Condition true_condition; |
| 5927 if (left.IsConstant()) { | 5871 if (left.IsConstant()) { |
| 5928 true_condition = compiler->EmitEqualityRegConstCompare(right.reg(), | 5872 true_condition = compiler->EmitEqualityRegConstCompare( |
| 5929 left.constant(), | 5873 right.reg(), left.constant(), needs_number_check(), token_pos()); |
| 5930 needs_number_check(), | |
| 5931 token_pos()); | |
| 5932 } else if (right.IsConstant()) { | 5874 } else if (right.IsConstant()) { |
| 5933 true_condition = compiler->EmitEqualityRegConstCompare(left.reg(), | 5875 true_condition = compiler->EmitEqualityRegConstCompare( |
| 5934 right.constant(), | 5876 left.reg(), right.constant(), needs_number_check(), token_pos()); |
| 5935 needs_number_check(), | |
| 5936 token_pos()); | |
| 5937 } else { | 5877 } else { |
| 5938 true_condition = compiler->EmitEqualityRegRegCompare(left.reg(), | 5878 true_condition = compiler->EmitEqualityRegRegCompare( |
| 5939 right.reg(), | 5879 left.reg(), right.reg(), needs_number_check(), token_pos()); |
| 5940 needs_number_check(), | |
| 5941 token_pos()); | |
| 5942 } | 5880 } |
| 5943 if (kind() != Token::kEQ_STRICT) { | 5881 if (kind() != Token::kEQ_STRICT) { |
| 5944 ASSERT(kind() == Token::kNE_STRICT); | 5882 ASSERT(kind() == Token::kNE_STRICT); |
| 5945 true_condition = NegateCondition(true_condition); | 5883 true_condition = NegateCondition(true_condition); |
| 5946 } | 5884 } |
| 5947 return true_condition; | 5885 return true_condition; |
| 5948 } | 5886 } |
| 5949 | 5887 |
| 5950 | 5888 |
| 5951 void StrictCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5889 void StrictCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5952 __ Comment("StrictCompareInstr"); | 5890 __ Comment("StrictCompareInstr"); |
| 5953 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); | 5891 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); |
| 5954 | 5892 |
| 5955 Label is_true, is_false; | 5893 Label is_true, is_false; |
| 5956 BranchLabels labels = { &is_true, &is_false, &is_false }; | 5894 BranchLabels labels = {&is_true, &is_false, &is_false}; |
| 5957 Condition true_condition = EmitComparisonCode(compiler, labels); | 5895 Condition true_condition = EmitComparisonCode(compiler, labels); |
| 5958 EmitBranchOnCondition(compiler, true_condition, labels); | 5896 EmitBranchOnCondition(compiler, true_condition, labels); |
| 5959 | 5897 |
| 5960 Register result = locs()->out(0).reg(); | 5898 Register result = locs()->out(0).reg(); |
| 5961 Label done; | 5899 Label done; |
| 5962 __ Bind(&is_false); | 5900 __ Bind(&is_false); |
| 5963 __ LoadObject(result, Bool::False()); | 5901 __ LoadObject(result, Bool::False()); |
| 5964 __ b(&done); | 5902 __ b(&done); |
| 5965 __ Bind(&is_true); | 5903 __ Bind(&is_true); |
| 5966 __ LoadObject(result, Bool::True()); | 5904 __ LoadObject(result, Bool::True()); |
| 5967 __ Bind(&done); | 5905 __ Bind(&done); |
| 5968 } | 5906 } |
| 5969 | 5907 |
| 5970 | 5908 |
| 5971 void StrictCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 5909 void StrictCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
| 5972 BranchInstr* branch) { | 5910 BranchInstr* branch) { |
| 5973 __ Comment("StrictCompareInstr::EmitBranchCode"); | 5911 __ Comment("StrictCompareInstr::EmitBranchCode"); |
| 5974 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); | 5912 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); |
| 5975 | 5913 |
| 5976 BranchLabels labels = compiler->CreateBranchLabels(branch); | 5914 BranchLabels labels = compiler->CreateBranchLabels(branch); |
| 5977 Condition true_condition = EmitComparisonCode(compiler, labels); | 5915 Condition true_condition = EmitComparisonCode(compiler, labels); |
| 5978 EmitBranchOnCondition(compiler, true_condition, labels); | 5916 EmitBranchOnCondition(compiler, true_condition, labels); |
| 5979 } | 5917 } |
| 5980 | 5918 |
| 5981 | 5919 |
| 5982 LocationSummary* BooleanNegateInstr::MakeLocationSummary(Zone* zone, | 5920 LocationSummary* BooleanNegateInstr::MakeLocationSummary(Zone* zone, |
| 5983 bool opt) const { | 5921 bool opt) const { |
| 5984 return LocationSummary::Make(zone, | 5922 return LocationSummary::Make(zone, 1, Location::RequiresRegister(), |
| 5985 1, | |
| 5986 Location::RequiresRegister(), | |
| 5987 LocationSummary::kNoCall); | 5923 LocationSummary::kNoCall); |
| 5988 } | 5924 } |
| 5989 | 5925 |
| 5990 | 5926 |
| 5991 void BooleanNegateInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5927 void BooleanNegateInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5992 Register value = locs()->in(0).reg(); | 5928 Register value = locs()->in(0).reg(); |
| 5993 Register result = locs()->out(0).reg(); | 5929 Register result = locs()->out(0).reg(); |
| 5994 | 5930 |
| 5995 __ LoadObject(result, Bool::True()); | 5931 __ LoadObject(result, Bool::True()); |
| 5996 __ LoadObject(TMP, Bool::False()); | 5932 __ LoadObject(TMP, Bool::False()); |
| 5997 __ subu(CMPRES1, value, result); | 5933 __ subu(CMPRES1, value, result); |
| 5998 __ movz(result, TMP, CMPRES1); // If value is True, move False into result. | 5934 __ movz(result, TMP, CMPRES1); // If value is True, move False into result. |
| 5999 } | 5935 } |
| 6000 | 5936 |
| 6001 | 5937 |
| 6002 LocationSummary* AllocateObjectInstr::MakeLocationSummary(Zone* zone, | 5938 LocationSummary* AllocateObjectInstr::MakeLocationSummary(Zone* zone, |
| 6003 bool opt) const { | 5939 bool opt) const { |
| 6004 return MakeCallSummary(zone); | 5940 return MakeCallSummary(zone); |
| 6005 } | 5941 } |
| 6006 | 5942 |
| 6007 | 5943 |
| 6008 void AllocateObjectInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5944 void AllocateObjectInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 6009 __ Comment("AllocateObjectInstr"); | 5945 __ Comment("AllocateObjectInstr"); |
| 6010 const Code& stub = Code::ZoneHandle( | 5946 const Code& stub = Code::ZoneHandle( |
| 6011 compiler->zone(), StubCode::GetAllocationStubForClass(cls())); | 5947 compiler->zone(), StubCode::GetAllocationStubForClass(cls())); |
| 6012 const StubEntry stub_entry(stub); | 5948 const StubEntry stub_entry(stub); |
| 6013 compiler->GenerateCall(token_pos(), | 5949 compiler->GenerateCall(token_pos(), stub_entry, RawPcDescriptors::kOther, |
| 6014 stub_entry, | |
| 6015 RawPcDescriptors::kOther, | |
| 6016 locs()); | 5950 locs()); |
| 6017 compiler->AddStubCallTarget(stub); | 5951 compiler->AddStubCallTarget(stub); |
| 6018 __ Drop(ArgumentCount()); // Discard arguments. | 5952 __ Drop(ArgumentCount()); // Discard arguments. |
| 6019 } | 5953 } |
| 6020 | 5954 |
| 6021 | 5955 |
| 6022 void DebugStepCheckInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5956 void DebugStepCheckInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 6023 ASSERT(!compiler->is_optimizing()); | 5957 ASSERT(!compiler->is_optimizing()); |
| 6024 __ BranchLinkPatchable(*StubCode::DebugStepCheck_entry()); | 5958 __ BranchLinkPatchable(*StubCode::DebugStepCheck_entry()); |
| 6025 compiler->AddCurrentDescriptor(stub_kind_, Thread::kNoDeoptId, token_pos()); | 5959 compiler->AddCurrentDescriptor(stub_kind_, Thread::kNoDeoptId, token_pos()); |
| 6026 compiler->RecordSafepoint(locs()); | 5960 compiler->RecordSafepoint(locs()); |
| 6027 } | 5961 } |
| 6028 | 5962 |
| 6029 | 5963 |
| 6030 LocationSummary* GrowRegExpStackInstr::MakeLocationSummary( | 5964 LocationSummary* GrowRegExpStackInstr::MakeLocationSummary(Zone* zone, |
| 6031 Zone* zone, bool opt) const { | 5965 bool opt) const { |
| 6032 const intptr_t kNumInputs = 1; | 5966 const intptr_t kNumInputs = 1; |
| 6033 const intptr_t kNumTemps = 0; | 5967 const intptr_t kNumTemps = 0; |
| 6034 LocationSummary* locs = new(zone) LocationSummary( | 5968 LocationSummary* locs = new (zone) |
| 6035 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 5969 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
| 6036 locs->set_in(0, Location::RegisterLocation(T0)); | 5970 locs->set_in(0, Location::RegisterLocation(T0)); |
| 6037 locs->set_out(0, Location::RegisterLocation(T0)); | 5971 locs->set_out(0, Location::RegisterLocation(T0)); |
| 6038 return locs; | 5972 return locs; |
| 6039 } | 5973 } |
| 6040 | 5974 |
| 6041 | 5975 |
| 6042 void GrowRegExpStackInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5976 void GrowRegExpStackInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 6043 const Register typed_data = locs()->in(0).reg(); | 5977 const Register typed_data = locs()->in(0).reg(); |
| 6044 const Register result = locs()->out(0).reg(); | 5978 const Register result = locs()->out(0).reg(); |
| 6045 __ Comment("GrowRegExpStackInstr"); | 5979 __ Comment("GrowRegExpStackInstr"); |
| 6046 __ addiu(SP, SP, Immediate(-2 * kWordSize)); | 5980 __ addiu(SP, SP, Immediate(-2 * kWordSize)); |
| 6047 __ LoadObject(TMP, Object::null_object()); | 5981 __ LoadObject(TMP, Object::null_object()); |
| 6048 __ sw(TMP, Address(SP, 1 * kWordSize)); | 5982 __ sw(TMP, Address(SP, 1 * kWordSize)); |
| 6049 __ sw(typed_data, Address(SP, 0 * kWordSize)); | 5983 __ sw(typed_data, Address(SP, 0 * kWordSize)); |
| 6050 compiler->GenerateRuntimeCall(TokenPosition::kNoSource, | 5984 compiler->GenerateRuntimeCall(TokenPosition::kNoSource, deopt_id(), |
| 6051 deopt_id(), | 5985 kGrowRegExpStackRuntimeEntry, 1, locs()); |
| 6052 kGrowRegExpStackRuntimeEntry, | |
| 6053 1, | |
| 6054 locs()); | |
| 6055 __ lw(result, Address(SP, 1 * kWordSize)); | 5986 __ lw(result, Address(SP, 1 * kWordSize)); |
| 6056 __ addiu(SP, SP, Immediate(2 * kWordSize)); | 5987 __ addiu(SP, SP, Immediate(2 * kWordSize)); |
| 6057 } | 5988 } |
| 6058 | 5989 |
| 6059 | 5990 |
| 6060 } // namespace dart | 5991 } // namespace dart |
| 6061 | 5992 |
| 6062 #endif // defined TARGET_ARCH_MIPS | 5993 #endif // defined TARGET_ARCH_MIPS |
| OLD | NEW |