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_IA32. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_IA32. |
6 #if defined(TARGET_ARCH_IA32) | 6 #if defined(TARGET_ARCH_IA32) |
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 18 matching lines...) Expand all Loading... |
29 // on the stack and return the result in a fixed register EAX. | 29 // on the stack and return the result in a fixed register EAX. |
30 LocationSummary* Instruction::MakeCallSummary(Zone* zone) { | 30 LocationSummary* Instruction::MakeCallSummary(Zone* zone) { |
31 const intptr_t kNumInputs = 0; | 31 const intptr_t kNumInputs = 0; |
32 const intptr_t kNumTemps = 0; | 32 const intptr_t kNumTemps = 0; |
33 LocationSummary* result = new (zone) | 33 LocationSummary* result = new (zone) |
34 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 34 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
35 result->set_out(0, Location::RegisterLocation(EAX)); | 35 result->set_out(0, Location::RegisterLocation(EAX)); |
36 return result; | 36 return result; |
37 } | 37 } |
38 | 38 |
39 | |
40 LocationSummary* PushArgumentInstr::MakeLocationSummary(Zone* zone, | 39 LocationSummary* PushArgumentInstr::MakeLocationSummary(Zone* zone, |
41 bool opt) const { | 40 bool opt) const { |
42 const intptr_t kNumInputs = 1; | 41 const intptr_t kNumInputs = 1; |
43 const intptr_t kNumTemps = 0; | 42 const intptr_t kNumTemps = 0; |
44 LocationSummary* locs = new (zone) | 43 LocationSummary* locs = new (zone) |
45 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 44 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
46 locs->set_in(0, Location::AnyOrConstant(value())); | 45 locs->set_in(0, Location::AnyOrConstant(value())); |
47 return locs; | 46 return locs; |
48 } | 47 } |
49 | 48 |
50 | |
51 void PushArgumentInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 49 void PushArgumentInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
52 // In SSA mode, we need an explicit push. Nothing to do in non-SSA mode | 50 // In SSA mode, we need an explicit push. Nothing to do in non-SSA mode |
53 // where PushArgument is handled by BindInstr::EmitNativeCode. | 51 // where PushArgument is handled by BindInstr::EmitNativeCode. |
54 if (compiler->is_optimizing()) { | 52 if (compiler->is_optimizing()) { |
55 Location value = locs()->in(0); | 53 Location value = locs()->in(0); |
56 if (value.IsRegister()) { | 54 if (value.IsRegister()) { |
57 __ pushl(value.reg()); | 55 __ pushl(value.reg()); |
58 } else if (value.IsConstant()) { | 56 } else if (value.IsConstant()) { |
59 __ PushObject(value.constant()); | 57 __ PushObject(value.constant()); |
60 } else { | 58 } else { |
61 ASSERT(value.IsStackSlot()); | 59 ASSERT(value.IsStackSlot()); |
62 __ pushl(value.ToStackSlotAddress()); | 60 __ pushl(value.ToStackSlotAddress()); |
63 } | 61 } |
64 } | 62 } |
65 } | 63 } |
66 | 64 |
67 | |
68 LocationSummary* ReturnInstr::MakeLocationSummary(Zone* zone, bool opt) const { | 65 LocationSummary* ReturnInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
69 const intptr_t kNumInputs = 1; | 66 const intptr_t kNumInputs = 1; |
70 const intptr_t kNumTemps = 0; | 67 const intptr_t kNumTemps = 0; |
71 LocationSummary* locs = new (zone) | 68 LocationSummary* locs = new (zone) |
72 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 69 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
73 locs->set_in(0, Location::RegisterLocation(EAX)); | 70 locs->set_in(0, Location::RegisterLocation(EAX)); |
74 return locs; | 71 return locs; |
75 } | 72 } |
76 | 73 |
77 | |
78 // Attempt optimized compilation at return instruction instead of at the entry. | 74 // Attempt optimized compilation at return instruction instead of at the entry. |
79 // The entry needs to be patchable, no inlined objects are allowed in the area | 75 // The entry needs to be patchable, no inlined objects are allowed in the area |
80 // that will be overwritten by the patch instruction: a jump). | 76 // that will be overwritten by the patch instruction: a jump). |
81 void ReturnInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 77 void ReturnInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
82 Register result = locs()->in(0).reg(); | 78 Register result = locs()->in(0).reg(); |
83 ASSERT(result == EAX); | 79 ASSERT(result == EAX); |
84 | 80 |
85 if (compiler->intrinsic_mode()) { | 81 if (compiler->intrinsic_mode()) { |
86 // Intrinsics don't have a frame. | 82 // Intrinsics don't have a frame. |
87 __ ret(); | 83 __ ret(); |
(...skipping 10 matching lines...) Expand all Loading... |
98 __ subl(EDI, EBP); | 94 __ subl(EDI, EBP); |
99 __ cmpl(EDI, Immediate(fp_sp_dist)); | 95 __ cmpl(EDI, Immediate(fp_sp_dist)); |
100 __ j(EQUAL, &done, Assembler::kNearJump); | 96 __ j(EQUAL, &done, Assembler::kNearJump); |
101 __ int3(); | 97 __ int3(); |
102 __ Bind(&done); | 98 __ Bind(&done); |
103 #endif | 99 #endif |
104 __ LeaveFrame(); | 100 __ LeaveFrame(); |
105 __ ret(); | 101 __ ret(); |
106 } | 102 } |
107 | 103 |
108 | |
109 LocationSummary* LoadLocalInstr::MakeLocationSummary(Zone* zone, | 104 LocationSummary* LoadLocalInstr::MakeLocationSummary(Zone* zone, |
110 bool opt) const { | 105 bool opt) const { |
111 const intptr_t kNumInputs = 0; | 106 const intptr_t kNumInputs = 0; |
112 const intptr_t stack_index = (local().index() < 0) | 107 const intptr_t stack_index = (local().index() < 0) |
113 ? kFirstLocalSlotFromFp - local().index() | 108 ? kFirstLocalSlotFromFp - local().index() |
114 : kParamEndSlotFromFp - local().index(); | 109 : kParamEndSlotFromFp - local().index(); |
115 return LocationSummary::Make(zone, kNumInputs, | 110 return LocationSummary::Make(zone, kNumInputs, |
116 Location::StackSlot(stack_index), | 111 Location::StackSlot(stack_index), |
117 LocationSummary::kNoCall); | 112 LocationSummary::kNoCall); |
118 } | 113 } |
119 | 114 |
120 | |
121 void LoadLocalInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 115 void LoadLocalInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
122 ASSERT(!compiler->is_optimizing()); | 116 ASSERT(!compiler->is_optimizing()); |
123 // Nothing to do. | 117 // Nothing to do. |
124 } | 118 } |
125 | 119 |
126 | |
127 LocationSummary* StoreLocalInstr::MakeLocationSummary(Zone* zone, | 120 LocationSummary* StoreLocalInstr::MakeLocationSummary(Zone* zone, |
128 bool opt) const { | 121 bool opt) const { |
129 const intptr_t kNumInputs = 1; | 122 const intptr_t kNumInputs = 1; |
130 return LocationSummary::Make(zone, kNumInputs, Location::SameAsFirstInput(), | 123 return LocationSummary::Make(zone, kNumInputs, Location::SameAsFirstInput(), |
131 LocationSummary::kNoCall); | 124 LocationSummary::kNoCall); |
132 } | 125 } |
133 | 126 |
134 | |
135 void StoreLocalInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 127 void StoreLocalInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
136 Register value = locs()->in(0).reg(); | 128 Register value = locs()->in(0).reg(); |
137 Register result = locs()->out(0).reg(); | 129 Register result = locs()->out(0).reg(); |
138 ASSERT(result == value); // Assert that register assignment is correct. | 130 ASSERT(result == value); // Assert that register assignment is correct. |
139 __ movl(Address(EBP, local().index() * kWordSize), value); | 131 __ movl(Address(EBP, local().index() * kWordSize), value); |
140 } | 132 } |
141 | 133 |
142 | |
143 LocationSummary* ConstantInstr::MakeLocationSummary(Zone* zone, | 134 LocationSummary* ConstantInstr::MakeLocationSummary(Zone* zone, |
144 bool opt) const { | 135 bool opt) const { |
145 const intptr_t kNumInputs = 0; | 136 const intptr_t kNumInputs = 0; |
146 return LocationSummary::Make(zone, kNumInputs, | 137 return LocationSummary::Make(zone, kNumInputs, |
147 Assembler::IsSafe(value()) | 138 Assembler::IsSafe(value()) |
148 ? Location::Constant(this) | 139 ? Location::Constant(this) |
149 : Location::RequiresRegister(), | 140 : Location::RequiresRegister(), |
150 LocationSummary::kNoCall); | 141 LocationSummary::kNoCall); |
151 } | 142 } |
152 | 143 |
153 | |
154 void ConstantInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 144 void ConstantInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
155 // The register allocator drops constant definitions that have no uses. | 145 // The register allocator drops constant definitions that have no uses. |
156 Location out = locs()->out(0); | 146 Location out = locs()->out(0); |
157 ASSERT(out.IsRegister() || out.IsConstant() || out.IsInvalid()); | 147 ASSERT(out.IsRegister() || out.IsConstant() || out.IsInvalid()); |
158 if (out.IsRegister()) { | 148 if (out.IsRegister()) { |
159 Register result = out.reg(); | 149 Register result = out.reg(); |
160 __ LoadObjectSafely(result, value()); | 150 __ LoadObjectSafely(result, value()); |
161 } | 151 } |
162 } | 152 } |
163 | 153 |
164 | |
165 LocationSummary* UnboxedConstantInstr::MakeLocationSummary(Zone* zone, | 154 LocationSummary* UnboxedConstantInstr::MakeLocationSummary(Zone* zone, |
166 bool opt) const { | 155 bool opt) const { |
167 const intptr_t kNumInputs = 0; | 156 const intptr_t kNumInputs = 0; |
168 const intptr_t kNumTemps = | 157 const intptr_t kNumTemps = |
169 (constant_address() == 0) && (representation() != kUnboxedInt32) ? 1 : 0; | 158 (constant_address() == 0) && (representation() != kUnboxedInt32) ? 1 : 0; |
170 LocationSummary* locs = new (zone) | 159 LocationSummary* locs = new (zone) |
171 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 160 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
172 if (representation() == kUnboxedDouble) { | 161 if (representation() == kUnboxedDouble) { |
173 locs->set_out(0, Location::RequiresFpuRegister()); | 162 locs->set_out(0, Location::RequiresFpuRegister()); |
174 } else { | 163 } else { |
175 ASSERT(representation() == kUnboxedInt32); | 164 ASSERT(representation() == kUnboxedInt32); |
176 locs->set_out(0, Location::RequiresRegister()); | 165 locs->set_out(0, Location::RequiresRegister()); |
177 } | 166 } |
178 if (kNumTemps == 1) { | 167 if (kNumTemps == 1) { |
179 locs->set_temp(0, Location::RequiresRegister()); | 168 locs->set_temp(0, Location::RequiresRegister()); |
180 } | 169 } |
181 return locs; | 170 return locs; |
182 } | 171 } |
183 | 172 |
184 | |
185 void UnboxedConstantInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 173 void UnboxedConstantInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
186 // The register allocator drops constant definitions that have no uses. | 174 // The register allocator drops constant definitions that have no uses. |
187 if (!locs()->out(0).IsInvalid()) { | 175 if (!locs()->out(0).IsInvalid()) { |
188 switch (representation()) { | 176 switch (representation()) { |
189 case kUnboxedDouble: { | 177 case kUnboxedDouble: { |
190 XmmRegister result = locs()->out(0).fpu_reg(); | 178 XmmRegister result = locs()->out(0).fpu_reg(); |
191 if (constant_address() == 0) { | 179 if (constant_address() == 0) { |
192 Register boxed = locs()->temp(0).reg(); | 180 Register boxed = locs()->temp(0).reg(); |
193 __ LoadObjectSafely(boxed, value()); | 181 __ LoadObjectSafely(boxed, value()); |
194 __ movsd(result, FieldAddress(boxed, Double::value_offset())); | 182 __ movsd(result, FieldAddress(boxed, Double::value_offset())); |
195 } else if (Utils::DoublesBitEqual(Double::Cast(value()).value(), 0.0)) { | 183 } else if (Utils::DoublesBitEqual(Double::Cast(value()).value(), 0.0)) { |
196 __ xorps(result, result); | 184 __ xorps(result, result); |
197 } else { | 185 } else { |
198 __ movsd(result, Address::Absolute(constant_address())); | 186 __ movsd(result, Address::Absolute(constant_address())); |
199 } | 187 } |
200 break; | 188 break; |
201 } | 189 } |
202 case kUnboxedInt32: | 190 case kUnboxedInt32: |
203 __ movl(locs()->out(0).reg(), Immediate(Smi::Cast(value()).Value())); | 191 __ movl(locs()->out(0).reg(), Immediate(Smi::Cast(value()).Value())); |
204 break; | 192 break; |
205 default: | 193 default: |
206 UNREACHABLE(); | 194 UNREACHABLE(); |
207 } | 195 } |
208 } | 196 } |
209 } | 197 } |
210 | 198 |
211 | |
212 LocationSummary* AssertAssignableInstr::MakeLocationSummary(Zone* zone, | 199 LocationSummary* AssertAssignableInstr::MakeLocationSummary(Zone* zone, |
213 bool opt) const { | 200 bool opt) const { |
214 const intptr_t kNumInputs = 3; | 201 const intptr_t kNumInputs = 3; |
215 const intptr_t kNumTemps = 0; | 202 const intptr_t kNumTemps = 0; |
216 LocationSummary* summary = new (zone) | 203 LocationSummary* summary = new (zone) |
217 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 204 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
218 summary->set_in(0, Location::RegisterLocation(EAX)); // Value. | 205 summary->set_in(0, Location::RegisterLocation(EAX)); // Value. |
219 summary->set_in(1, Location::RegisterLocation(EDX)); // Instant. type args. | 206 summary->set_in(1, Location::RegisterLocation(EDX)); // Instant. type args. |
220 summary->set_in(2, Location::RegisterLocation(ECX)); // Function type args. | 207 summary->set_in(2, Location::RegisterLocation(ECX)); // Function type args. |
221 summary->set_out(0, Location::RegisterLocation(EAX)); | 208 summary->set_out(0, Location::RegisterLocation(EAX)); |
222 return summary; | 209 return summary; |
223 } | 210 } |
224 | 211 |
225 | |
226 LocationSummary* AssertBooleanInstr::MakeLocationSummary(Zone* zone, | 212 LocationSummary* AssertBooleanInstr::MakeLocationSummary(Zone* zone, |
227 bool opt) const { | 213 bool opt) const { |
228 const intptr_t kNumInputs = 1; | 214 const intptr_t kNumInputs = 1; |
229 const intptr_t kNumTemps = 0; | 215 const intptr_t kNumTemps = 0; |
230 LocationSummary* locs = new (zone) | 216 LocationSummary* locs = new (zone) |
231 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 217 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
232 locs->set_in(0, Location::RegisterLocation(EAX)); | 218 locs->set_in(0, Location::RegisterLocation(EAX)); |
233 locs->set_out(0, Location::RegisterLocation(EAX)); | 219 locs->set_out(0, Location::RegisterLocation(EAX)); |
234 return locs; | 220 return locs; |
235 } | 221 } |
236 | 222 |
237 | |
238 static void EmitAssertBoolean(Register reg, | 223 static void EmitAssertBoolean(Register reg, |
239 TokenPosition token_pos, | 224 TokenPosition token_pos, |
240 intptr_t deopt_id, | 225 intptr_t deopt_id, |
241 LocationSummary* locs, | 226 LocationSummary* locs, |
242 FlowGraphCompiler* compiler) { | 227 FlowGraphCompiler* compiler) { |
243 // Check that the type of the value is allowed in conditional context. | 228 // Check that the type of the value is allowed in conditional context. |
244 // Call the runtime if the object is not bool::true or bool::false. | 229 // Call the runtime if the object is not bool::true or bool::false. |
245 ASSERT(locs->always_calls()); | 230 ASSERT(locs->always_calls()); |
246 Label done; | 231 Label done; |
247 | 232 |
248 if (Isolate::Current()->type_checks()) { | 233 if (Isolate::Current()->type_checks()) { |
249 __ CompareObject(reg, Bool::True()); | 234 __ CompareObject(reg, Bool::True()); |
250 __ j(EQUAL, &done, Assembler::kNearJump); | 235 __ j(EQUAL, &done, Assembler::kNearJump); |
251 __ CompareObject(reg, Bool::False()); | 236 __ CompareObject(reg, Bool::False()); |
252 __ j(EQUAL, &done, Assembler::kNearJump); | 237 __ j(EQUAL, &done, Assembler::kNearJump); |
253 } else { | 238 } else { |
254 ASSERT(Isolate::Current()->asserts()); | 239 ASSERT(Isolate::Current()->asserts()); |
255 __ CompareObject(reg, Object::null_instance()); | 240 __ CompareObject(reg, Object::null_instance()); |
256 __ j(NOT_EQUAL, &done, Assembler::kNearJump); | 241 __ j(NOT_EQUAL, &done, Assembler::kNearJump); |
257 } | 242 } |
258 | 243 |
259 __ pushl(reg); // Push the source object. | 244 __ pushl(reg); // Push the source object. |
260 compiler->GenerateRuntimeCall(token_pos, deopt_id, | 245 compiler->GenerateRuntimeCall(token_pos, deopt_id, |
261 kNonBoolTypeErrorRuntimeEntry, 1, locs); | 246 kNonBoolTypeErrorRuntimeEntry, 1, locs); |
262 // We should never return here. | 247 // We should never return here. |
263 __ int3(); | 248 __ int3(); |
264 __ Bind(&done); | 249 __ Bind(&done); |
265 } | 250 } |
266 | 251 |
267 | |
268 void AssertBooleanInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 252 void AssertBooleanInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
269 Register obj = locs()->in(0).reg(); | 253 Register obj = locs()->in(0).reg(); |
270 Register result = locs()->out(0).reg(); | 254 Register result = locs()->out(0).reg(); |
271 | 255 |
272 EmitAssertBoolean(obj, token_pos(), deopt_id(), locs(), compiler); | 256 EmitAssertBoolean(obj, token_pos(), deopt_id(), locs(), compiler); |
273 ASSERT(obj == result); | 257 ASSERT(obj == result); |
274 } | 258 } |
275 | 259 |
276 | |
277 static Condition TokenKindToSmiCondition(Token::Kind kind) { | 260 static Condition TokenKindToSmiCondition(Token::Kind kind) { |
278 switch (kind) { | 261 switch (kind) { |
279 case Token::kEQ: | 262 case Token::kEQ: |
280 return EQUAL; | 263 return EQUAL; |
281 case Token::kNE: | 264 case Token::kNE: |
282 return NOT_EQUAL; | 265 return NOT_EQUAL; |
283 case Token::kLT: | 266 case Token::kLT: |
284 return LESS; | 267 return LESS; |
285 case Token::kGT: | 268 case Token::kGT: |
286 return GREATER; | 269 return GREATER; |
287 case Token::kLTE: | 270 case Token::kLTE: |
288 return LESS_EQUAL; | 271 return LESS_EQUAL; |
289 case Token::kGTE: | 272 case Token::kGTE: |
290 return GREATER_EQUAL; | 273 return GREATER_EQUAL; |
291 default: | 274 default: |
292 UNREACHABLE(); | 275 UNREACHABLE(); |
293 return OVERFLOW; | 276 return OVERFLOW; |
294 } | 277 } |
295 } | 278 } |
296 | 279 |
297 | |
298 LocationSummary* EqualityCompareInstr::MakeLocationSummary(Zone* zone, | 280 LocationSummary* EqualityCompareInstr::MakeLocationSummary(Zone* zone, |
299 bool opt) const { | 281 bool opt) const { |
300 const intptr_t kNumInputs = 2; | 282 const intptr_t kNumInputs = 2; |
301 if (operation_cid() == kMintCid) { | 283 if (operation_cid() == kMintCid) { |
302 const intptr_t kNumTemps = 0; | 284 const intptr_t kNumTemps = 0; |
303 LocationSummary* locs = new (zone) | 285 LocationSummary* locs = new (zone) |
304 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 286 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
305 locs->set_in(0, Location::Pair(Location::RequiresRegister(), | 287 locs->set_in(0, Location::Pair(Location::RequiresRegister(), |
306 Location::RequiresRegister())); | 288 Location::RequiresRegister())); |
307 locs->set_in(1, Location::Pair(Location::RequiresRegister(), | 289 locs->set_in(1, Location::Pair(Location::RequiresRegister(), |
(...skipping 21 matching lines...) Expand all Loading... |
329 locs->set_in(1, locs->in(0).IsConstant() | 311 locs->set_in(1, locs->in(0).IsConstant() |
330 ? Location::RequiresRegister() | 312 ? Location::RequiresRegister() |
331 : Location::RegisterOrConstant(right())); | 313 : Location::RegisterOrConstant(right())); |
332 locs->set_out(0, Location::RequiresRegister()); | 314 locs->set_out(0, Location::RequiresRegister()); |
333 return locs; | 315 return locs; |
334 } | 316 } |
335 UNREACHABLE(); | 317 UNREACHABLE(); |
336 return NULL; | 318 return NULL; |
337 } | 319 } |
338 | 320 |
339 | |
340 static void LoadValueCid(FlowGraphCompiler* compiler, | 321 static void LoadValueCid(FlowGraphCompiler* compiler, |
341 Register value_cid_reg, | 322 Register value_cid_reg, |
342 Register value_reg, | 323 Register value_reg, |
343 Label* value_is_smi = NULL) { | 324 Label* value_is_smi = NULL) { |
344 Label done; | 325 Label done; |
345 if (value_is_smi == NULL) { | 326 if (value_is_smi == NULL) { |
346 __ movl(value_cid_reg, Immediate(kSmiCid)); | 327 __ movl(value_cid_reg, Immediate(kSmiCid)); |
347 } | 328 } |
348 __ testl(value_reg, Immediate(kSmiTagMask)); | 329 __ testl(value_reg, Immediate(kSmiTagMask)); |
349 if (value_is_smi == NULL) { | 330 if (value_is_smi == NULL) { |
350 __ j(ZERO, &done, Assembler::kNearJump); | 331 __ j(ZERO, &done, Assembler::kNearJump); |
351 } else { | 332 } else { |
352 __ j(ZERO, value_is_smi); | 333 __ j(ZERO, value_is_smi); |
353 } | 334 } |
354 __ LoadClassId(value_cid_reg, value_reg); | 335 __ LoadClassId(value_cid_reg, value_reg); |
355 __ Bind(&done); | 336 __ Bind(&done); |
356 } | 337 } |
357 | 338 |
358 | |
359 static Condition FlipCondition(Condition condition) { | 339 static Condition FlipCondition(Condition condition) { |
360 switch (condition) { | 340 switch (condition) { |
361 case EQUAL: | 341 case EQUAL: |
362 return EQUAL; | 342 return EQUAL; |
363 case NOT_EQUAL: | 343 case NOT_EQUAL: |
364 return NOT_EQUAL; | 344 return NOT_EQUAL; |
365 case LESS: | 345 case LESS: |
366 return GREATER; | 346 return GREATER; |
367 case LESS_EQUAL: | 347 case LESS_EQUAL: |
368 return GREATER_EQUAL; | 348 return GREATER_EQUAL; |
369 case GREATER: | 349 case GREATER: |
370 return LESS; | 350 return LESS; |
371 case GREATER_EQUAL: | 351 case GREATER_EQUAL: |
372 return LESS_EQUAL; | 352 return LESS_EQUAL; |
373 case BELOW: | 353 case BELOW: |
374 return ABOVE; | 354 return ABOVE; |
375 case BELOW_EQUAL: | 355 case BELOW_EQUAL: |
376 return ABOVE_EQUAL; | 356 return ABOVE_EQUAL; |
377 case ABOVE: | 357 case ABOVE: |
378 return BELOW; | 358 return BELOW; |
379 case ABOVE_EQUAL: | 359 case ABOVE_EQUAL: |
380 return BELOW_EQUAL; | 360 return BELOW_EQUAL; |
381 default: | 361 default: |
382 UNIMPLEMENTED(); | 362 UNIMPLEMENTED(); |
383 return EQUAL; | 363 return EQUAL; |
384 } | 364 } |
385 } | 365 } |
386 | 366 |
387 | |
388 static Condition NegateCondition(Condition condition) { | 367 static Condition NegateCondition(Condition condition) { |
389 switch (condition) { | 368 switch (condition) { |
390 case EQUAL: | 369 case EQUAL: |
391 return NOT_EQUAL; | 370 return NOT_EQUAL; |
392 case NOT_EQUAL: | 371 case NOT_EQUAL: |
393 return EQUAL; | 372 return EQUAL; |
394 case LESS: | 373 case LESS: |
395 return GREATER_EQUAL; | 374 return GREATER_EQUAL; |
396 case LESS_EQUAL: | 375 case LESS_EQUAL: |
397 return GREATER; | 376 return GREATER; |
(...skipping 12 matching lines...) Expand all Loading... |
410 case PARITY_ODD: | 389 case PARITY_ODD: |
411 return PARITY_EVEN; | 390 return PARITY_EVEN; |
412 case PARITY_EVEN: | 391 case PARITY_EVEN: |
413 return PARITY_ODD; | 392 return PARITY_ODD; |
414 default: | 393 default: |
415 UNIMPLEMENTED(); | 394 UNIMPLEMENTED(); |
416 return EQUAL; | 395 return EQUAL; |
417 } | 396 } |
418 } | 397 } |
419 | 398 |
420 | |
421 static void EmitBranchOnCondition(FlowGraphCompiler* compiler, | 399 static void EmitBranchOnCondition(FlowGraphCompiler* compiler, |
422 Condition true_condition, | 400 Condition true_condition, |
423 BranchLabels labels) { | 401 BranchLabels labels) { |
424 if (labels.fall_through == labels.false_label) { | 402 if (labels.fall_through == labels.false_label) { |
425 // If the next block is the false successor, fall through to it. | 403 // If the next block is the false successor, fall through to it. |
426 __ j(true_condition, labels.true_label); | 404 __ j(true_condition, labels.true_label); |
427 } else { | 405 } else { |
428 // If the next block is not the false successor, branch to it. | 406 // If the next block is not the false successor, branch to it. |
429 Condition false_condition = NegateCondition(true_condition); | 407 Condition false_condition = NegateCondition(true_condition); |
430 __ j(false_condition, labels.false_label); | 408 __ j(false_condition, labels.false_label); |
431 | 409 |
432 // Fall through or jump to the true successor. | 410 // Fall through or jump to the true successor. |
433 if (labels.fall_through != labels.true_label) { | 411 if (labels.fall_through != labels.true_label) { |
434 __ jmp(labels.true_label); | 412 __ jmp(labels.true_label); |
435 } | 413 } |
436 } | 414 } |
437 } | 415 } |
438 | 416 |
439 | |
440 static Condition EmitSmiComparisonOp(FlowGraphCompiler* compiler, | 417 static Condition EmitSmiComparisonOp(FlowGraphCompiler* compiler, |
441 const LocationSummary& locs, | 418 const LocationSummary& locs, |
442 Token::Kind kind, | 419 Token::Kind kind, |
443 BranchLabels labels) { | 420 BranchLabels labels) { |
444 Location left = locs.in(0); | 421 Location left = locs.in(0); |
445 Location right = locs.in(1); | 422 Location right = locs.in(1); |
446 ASSERT(!left.IsConstant() || !right.IsConstant()); | 423 ASSERT(!left.IsConstant() || !right.IsConstant()); |
447 | 424 |
448 Condition true_condition = TokenKindToSmiCondition(kind); | 425 Condition true_condition = TokenKindToSmiCondition(kind); |
449 | 426 |
450 if (left.IsConstant()) { | 427 if (left.IsConstant()) { |
451 __ CompareObject(right.reg(), left.constant()); | 428 __ CompareObject(right.reg(), left.constant()); |
452 true_condition = FlipCondition(true_condition); | 429 true_condition = FlipCondition(true_condition); |
453 } else if (right.IsConstant()) { | 430 } else if (right.IsConstant()) { |
454 __ CompareObject(left.reg(), right.constant()); | 431 __ CompareObject(left.reg(), right.constant()); |
455 } else if (right.IsStackSlot()) { | 432 } else if (right.IsStackSlot()) { |
456 __ cmpl(left.reg(), right.ToStackSlotAddress()); | 433 __ cmpl(left.reg(), right.ToStackSlotAddress()); |
457 } else { | 434 } else { |
458 __ cmpl(left.reg(), right.reg()); | 435 __ cmpl(left.reg(), right.reg()); |
459 } | 436 } |
460 return true_condition; | 437 return true_condition; |
461 } | 438 } |
462 | 439 |
463 | |
464 static Condition TokenKindToMintCondition(Token::Kind kind) { | 440 static Condition TokenKindToMintCondition(Token::Kind kind) { |
465 switch (kind) { | 441 switch (kind) { |
466 case Token::kEQ: | 442 case Token::kEQ: |
467 return EQUAL; | 443 return EQUAL; |
468 case Token::kNE: | 444 case Token::kNE: |
469 return NOT_EQUAL; | 445 return NOT_EQUAL; |
470 case Token::kLT: | 446 case Token::kLT: |
471 return LESS; | 447 return LESS; |
472 case Token::kGT: | 448 case Token::kGT: |
473 return GREATER; | 449 return GREATER; |
474 case Token::kLTE: | 450 case Token::kLTE: |
475 return LESS_EQUAL; | 451 return LESS_EQUAL; |
476 case Token::kGTE: | 452 case Token::kGTE: |
477 return GREATER_EQUAL; | 453 return GREATER_EQUAL; |
478 default: | 454 default: |
479 UNREACHABLE(); | 455 UNREACHABLE(); |
480 return OVERFLOW; | 456 return OVERFLOW; |
481 } | 457 } |
482 } | 458 } |
483 | 459 |
484 | |
485 static Condition EmitUnboxedMintEqualityOp(FlowGraphCompiler* compiler, | 460 static Condition EmitUnboxedMintEqualityOp(FlowGraphCompiler* compiler, |
486 const LocationSummary& locs, | 461 const LocationSummary& locs, |
487 Token::Kind kind, | 462 Token::Kind kind, |
488 BranchLabels labels) { | 463 BranchLabels labels) { |
489 ASSERT(Token::IsEqualityOperator(kind)); | 464 ASSERT(Token::IsEqualityOperator(kind)); |
490 PairLocation* left_pair = locs.in(0).AsPairLocation(); | 465 PairLocation* left_pair = locs.in(0).AsPairLocation(); |
491 Register left1 = left_pair->At(0).reg(); | 466 Register left1 = left_pair->At(0).reg(); |
492 Register left2 = left_pair->At(1).reg(); | 467 Register left2 = left_pair->At(1).reg(); |
493 PairLocation* right_pair = locs.in(1).AsPairLocation(); | 468 PairLocation* right_pair = locs.in(1).AsPairLocation(); |
494 Register right1 = right_pair->At(0).reg(); | 469 Register right1 = right_pair->At(0).reg(); |
495 Register right2 = right_pair->At(1).reg(); | 470 Register right2 = right_pair->At(1).reg(); |
496 Label done; | 471 Label done; |
497 // Compare lower. | 472 // Compare lower. |
498 __ cmpl(left1, right1); | 473 __ cmpl(left1, right1); |
499 __ j(NOT_EQUAL, &done); | 474 __ j(NOT_EQUAL, &done); |
500 // Lower is equal, compare upper. | 475 // Lower is equal, compare upper. |
501 __ cmpl(left2, right2); | 476 __ cmpl(left2, right2); |
502 __ Bind(&done); | 477 __ Bind(&done); |
503 Condition true_condition = TokenKindToMintCondition(kind); | 478 Condition true_condition = TokenKindToMintCondition(kind); |
504 return true_condition; | 479 return true_condition; |
505 } | 480 } |
506 | 481 |
507 | |
508 static Condition EmitUnboxedMintComparisonOp(FlowGraphCompiler* compiler, | 482 static Condition EmitUnboxedMintComparisonOp(FlowGraphCompiler* compiler, |
509 const LocationSummary& locs, | 483 const LocationSummary& locs, |
510 Token::Kind kind, | 484 Token::Kind kind, |
511 BranchLabels labels) { | 485 BranchLabels labels) { |
512 PairLocation* left_pair = locs.in(0).AsPairLocation(); | 486 PairLocation* left_pair = locs.in(0).AsPairLocation(); |
513 Register left1 = left_pair->At(0).reg(); | 487 Register left1 = left_pair->At(0).reg(); |
514 Register left2 = left_pair->At(1).reg(); | 488 Register left2 = left_pair->At(1).reg(); |
515 PairLocation* right_pair = locs.in(1).AsPairLocation(); | 489 PairLocation* right_pair = locs.in(1).AsPairLocation(); |
516 Register right1 = right_pair->At(0).reg(); | 490 Register right1 = right_pair->At(0).reg(); |
517 Register right2 = right_pair->At(1).reg(); | 491 Register right2 = right_pair->At(1).reg(); |
(...skipping 23 matching lines...) Expand all Loading... |
541 // Compare upper halves first. | 515 // Compare upper halves first. |
542 __ cmpl(left2, right2); | 516 __ cmpl(left2, right2); |
543 __ j(hi_cond, labels.true_label); | 517 __ j(hi_cond, labels.true_label); |
544 __ j(FlipCondition(hi_cond), labels.false_label); | 518 __ j(FlipCondition(hi_cond), labels.false_label); |
545 | 519 |
546 // If upper is equal, compare lower half. | 520 // If upper is equal, compare lower half. |
547 __ cmpl(left1, right1); | 521 __ cmpl(left1, right1); |
548 return lo_cond; | 522 return lo_cond; |
549 } | 523 } |
550 | 524 |
551 | |
552 static Condition TokenKindToDoubleCondition(Token::Kind kind) { | 525 static Condition TokenKindToDoubleCondition(Token::Kind kind) { |
553 switch (kind) { | 526 switch (kind) { |
554 case Token::kEQ: | 527 case Token::kEQ: |
555 return EQUAL; | 528 return EQUAL; |
556 case Token::kNE: | 529 case Token::kNE: |
557 return NOT_EQUAL; | 530 return NOT_EQUAL; |
558 case Token::kLT: | 531 case Token::kLT: |
559 return BELOW; | 532 return BELOW; |
560 case Token::kGT: | 533 case Token::kGT: |
561 return ABOVE; | 534 return ABOVE; |
562 case Token::kLTE: | 535 case Token::kLTE: |
563 return BELOW_EQUAL; | 536 return BELOW_EQUAL; |
564 case Token::kGTE: | 537 case Token::kGTE: |
565 return ABOVE_EQUAL; | 538 return ABOVE_EQUAL; |
566 default: | 539 default: |
567 UNREACHABLE(); | 540 UNREACHABLE(); |
568 return OVERFLOW; | 541 return OVERFLOW; |
569 } | 542 } |
570 } | 543 } |
571 | 544 |
572 | |
573 static Condition EmitDoubleComparisonOp(FlowGraphCompiler* compiler, | 545 static Condition EmitDoubleComparisonOp(FlowGraphCompiler* compiler, |
574 const LocationSummary& locs, | 546 const LocationSummary& locs, |
575 Token::Kind kind, | 547 Token::Kind kind, |
576 BranchLabels labels) { | 548 BranchLabels labels) { |
577 XmmRegister left = locs.in(0).fpu_reg(); | 549 XmmRegister left = locs.in(0).fpu_reg(); |
578 XmmRegister right = locs.in(1).fpu_reg(); | 550 XmmRegister right = locs.in(1).fpu_reg(); |
579 | 551 |
580 __ comisd(left, right); | 552 __ comisd(left, right); |
581 | 553 |
582 Condition true_condition = TokenKindToDoubleCondition(kind); | 554 Condition true_condition = TokenKindToDoubleCondition(kind); |
583 Label* nan_result = | 555 Label* nan_result = |
584 (true_condition == NOT_EQUAL) ? labels.true_label : labels.false_label; | 556 (true_condition == NOT_EQUAL) ? labels.true_label : labels.false_label; |
585 __ j(PARITY_EVEN, nan_result); | 557 __ j(PARITY_EVEN, nan_result); |
586 return true_condition; | 558 return true_condition; |
587 } | 559 } |
588 | 560 |
589 | |
590 Condition EqualityCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler, | 561 Condition EqualityCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
591 BranchLabels labels) { | 562 BranchLabels labels) { |
592 if (operation_cid() == kSmiCid) { | 563 if (operation_cid() == kSmiCid) { |
593 return EmitSmiComparisonOp(compiler, *locs(), kind(), labels); | 564 return EmitSmiComparisonOp(compiler, *locs(), kind(), labels); |
594 } else if (operation_cid() == kMintCid) { | 565 } else if (operation_cid() == kMintCid) { |
595 return EmitUnboxedMintEqualityOp(compiler, *locs(), kind(), labels); | 566 return EmitUnboxedMintEqualityOp(compiler, *locs(), kind(), labels); |
596 } else { | 567 } else { |
597 ASSERT(operation_cid() == kDoubleCid); | 568 ASSERT(operation_cid() == kDoubleCid); |
598 return EmitDoubleComparisonOp(compiler, *locs(), kind(), labels); | 569 return EmitDoubleComparisonOp(compiler, *locs(), kind(), labels); |
599 } | 570 } |
600 } | 571 } |
601 | 572 |
602 | |
603 void ComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 573 void ComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
604 Label is_true, is_false; | 574 Label is_true, is_false; |
605 BranchLabels labels = {&is_true, &is_false, &is_false}; | 575 BranchLabels labels = {&is_true, &is_false, &is_false}; |
606 Condition true_condition = EmitComparisonCode(compiler, labels); | 576 Condition true_condition = EmitComparisonCode(compiler, labels); |
607 if (true_condition != INVALID_CONDITION) { | 577 if (true_condition != INVALID_CONDITION) { |
608 EmitBranchOnCondition(compiler, true_condition, labels); | 578 EmitBranchOnCondition(compiler, true_condition, labels); |
609 } | 579 } |
610 | 580 |
611 Register result = locs()->out(0).reg(); | 581 Register result = locs()->out(0).reg(); |
612 Label done; | 582 Label done; |
613 __ Bind(&is_false); | 583 __ Bind(&is_false); |
614 __ LoadObject(result, Bool::False()); | 584 __ LoadObject(result, Bool::False()); |
615 __ jmp(&done, Assembler::kNearJump); | 585 __ jmp(&done, Assembler::kNearJump); |
616 __ Bind(&is_true); | 586 __ Bind(&is_true); |
617 __ LoadObject(result, Bool::True()); | 587 __ LoadObject(result, Bool::True()); |
618 __ Bind(&done); | 588 __ Bind(&done); |
619 } | 589 } |
620 | 590 |
621 | |
622 void ComparisonInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 591 void ComparisonInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
623 BranchInstr* branch) { | 592 BranchInstr* branch) { |
624 BranchLabels labels = compiler->CreateBranchLabels(branch); | 593 BranchLabels labels = compiler->CreateBranchLabels(branch); |
625 Condition true_condition = EmitComparisonCode(compiler, labels); | 594 Condition true_condition = EmitComparisonCode(compiler, labels); |
626 if (true_condition != INVALID_CONDITION) { | 595 if (true_condition != INVALID_CONDITION) { |
627 EmitBranchOnCondition(compiler, true_condition, labels); | 596 EmitBranchOnCondition(compiler, true_condition, labels); |
628 } | 597 } |
629 } | 598 } |
630 | 599 |
631 | |
632 LocationSummary* TestSmiInstr::MakeLocationSummary(Zone* zone, bool opt) const { | 600 LocationSummary* TestSmiInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
633 const intptr_t kNumInputs = 2; | 601 const intptr_t kNumInputs = 2; |
634 const intptr_t kNumTemps = 0; | 602 const intptr_t kNumTemps = 0; |
635 LocationSummary* locs = new (zone) | 603 LocationSummary* locs = new (zone) |
636 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 604 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
637 locs->set_in(0, Location::RequiresRegister()); | 605 locs->set_in(0, Location::RequiresRegister()); |
638 // Only one input can be a constant operand. The case of two constant | 606 // Only one input can be a constant operand. The case of two constant |
639 // operands should be handled by constant propagation. | 607 // operands should be handled by constant propagation. |
640 locs->set_in(1, Location::RegisterOrConstant(right())); | 608 locs->set_in(1, Location::RegisterOrConstant(right())); |
641 return locs; | 609 return locs; |
642 } | 610 } |
643 | 611 |
644 | |
645 Condition TestSmiInstr::EmitComparisonCode(FlowGraphCompiler* compiler, | 612 Condition TestSmiInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
646 BranchLabels labels) { | 613 BranchLabels labels) { |
647 Register left = locs()->in(0).reg(); | 614 Register left = locs()->in(0).reg(); |
648 Location right = locs()->in(1); | 615 Location right = locs()->in(1); |
649 if (right.IsConstant()) { | 616 if (right.IsConstant()) { |
650 ASSERT(right.constant().IsSmi()); | 617 ASSERT(right.constant().IsSmi()); |
651 const int32_t imm = reinterpret_cast<int32_t>(right.constant().raw()); | 618 const int32_t imm = reinterpret_cast<int32_t>(right.constant().raw()); |
652 __ testl(left, Immediate(imm)); | 619 __ testl(left, Immediate(imm)); |
653 } else { | 620 } else { |
654 __ testl(left, right.reg()); | 621 __ testl(left, right.reg()); |
655 } | 622 } |
656 Condition true_condition = (kind() == Token::kNE) ? NOT_ZERO : ZERO; | 623 Condition true_condition = (kind() == Token::kNE) ? NOT_ZERO : ZERO; |
657 return true_condition; | 624 return true_condition; |
658 } | 625 } |
659 | 626 |
660 | |
661 LocationSummary* TestCidsInstr::MakeLocationSummary(Zone* zone, | 627 LocationSummary* TestCidsInstr::MakeLocationSummary(Zone* zone, |
662 bool opt) const { | 628 bool opt) const { |
663 const intptr_t kNumInputs = 1; | 629 const intptr_t kNumInputs = 1; |
664 const intptr_t kNumTemps = 1; | 630 const intptr_t kNumTemps = 1; |
665 LocationSummary* locs = new (zone) | 631 LocationSummary* locs = new (zone) |
666 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 632 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
667 locs->set_in(0, Location::RequiresRegister()); | 633 locs->set_in(0, Location::RequiresRegister()); |
668 locs->set_temp(0, Location::RequiresRegister()); | 634 locs->set_temp(0, Location::RequiresRegister()); |
669 locs->set_out(0, Location::RequiresRegister()); | 635 locs->set_out(0, Location::RequiresRegister()); |
670 return locs; | 636 return locs; |
671 } | 637 } |
672 | 638 |
673 | |
674 Condition TestCidsInstr::EmitComparisonCode(FlowGraphCompiler* compiler, | 639 Condition TestCidsInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
675 BranchLabels labels) { | 640 BranchLabels labels) { |
676 ASSERT((kind() == Token::kIS) || (kind() == Token::kISNOT)); | 641 ASSERT((kind() == Token::kIS) || (kind() == Token::kISNOT)); |
677 Register val_reg = locs()->in(0).reg(); | 642 Register val_reg = locs()->in(0).reg(); |
678 Register cid_reg = locs()->temp(0).reg(); | 643 Register cid_reg = locs()->temp(0).reg(); |
679 | 644 |
680 Label* deopt = | 645 Label* deopt = CanDeoptimize() ? compiler->AddDeoptStub( |
681 CanDeoptimize() | 646 deopt_id(), ICData::kDeoptTestCids, |
682 ? compiler->AddDeoptStub(deopt_id(), ICData::kDeoptTestCids, | 647 licm_hoisted_ ? ICData::kHoisted : 0) |
683 licm_hoisted_ ? ICData::kHoisted : 0) | 648 : NULL; |
684 : NULL; | |
685 | 649 |
686 const intptr_t true_result = (kind() == Token::kIS) ? 1 : 0; | 650 const intptr_t true_result = (kind() == Token::kIS) ? 1 : 0; |
687 const ZoneGrowableArray<intptr_t>& data = cid_results(); | 651 const ZoneGrowableArray<intptr_t>& data = cid_results(); |
688 ASSERT(data[0] == kSmiCid); | 652 ASSERT(data[0] == kSmiCid); |
689 bool result = data[1] == true_result; | 653 bool result = data[1] == true_result; |
690 __ testl(val_reg, Immediate(kSmiTagMask)); | 654 __ testl(val_reg, Immediate(kSmiTagMask)); |
691 __ j(ZERO, result ? labels.true_label : labels.false_label); | 655 __ j(ZERO, result ? labels.true_label : labels.false_label); |
692 __ LoadClassId(cid_reg, val_reg); | 656 __ LoadClassId(cid_reg, val_reg); |
693 for (intptr_t i = 2; i < data.length(); i += 2) { | 657 for (intptr_t i = 2; i < data.length(); i += 2) { |
694 const intptr_t test_cid = data[i]; | 658 const intptr_t test_cid = data[i]; |
(...skipping 12 matching lines...) Expand all Loading... |
707 __ jmp(target); | 671 __ jmp(target); |
708 } | 672 } |
709 } else { | 673 } else { |
710 __ jmp(deopt); | 674 __ jmp(deopt); |
711 } | 675 } |
712 // Dummy result as this method already did the jump, there's no need | 676 // Dummy result as this method already did the jump, there's no need |
713 // for the caller to branch on a condition. | 677 // for the caller to branch on a condition. |
714 return INVALID_CONDITION; | 678 return INVALID_CONDITION; |
715 } | 679 } |
716 | 680 |
717 | |
718 LocationSummary* RelationalOpInstr::MakeLocationSummary(Zone* zone, | 681 LocationSummary* RelationalOpInstr::MakeLocationSummary(Zone* zone, |
719 bool opt) const { | 682 bool opt) const { |
720 const intptr_t kNumInputs = 2; | 683 const intptr_t kNumInputs = 2; |
721 const intptr_t kNumTemps = 0; | 684 const intptr_t kNumTemps = 0; |
722 if (operation_cid() == kMintCid) { | 685 if (operation_cid() == kMintCid) { |
723 const intptr_t kNumTemps = 0; | 686 const intptr_t kNumTemps = 0; |
724 LocationSummary* locs = new (zone) | 687 LocationSummary* locs = new (zone) |
725 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 688 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
726 locs->set_in(0, Location::Pair(Location::RequiresRegister(), | 689 locs->set_in(0, Location::Pair(Location::RequiresRegister(), |
727 Location::RequiresRegister())); | 690 Location::RequiresRegister())); |
(...skipping 16 matching lines...) Expand all Loading... |
744 summary->set_in(0, Location::RegisterOrConstant(left())); | 707 summary->set_in(0, Location::RegisterOrConstant(left())); |
745 // Only one input can be a constant operand. The case of two constant | 708 // Only one input can be a constant operand. The case of two constant |
746 // operands should be handled by constant propagation. | 709 // operands should be handled by constant propagation. |
747 summary->set_in(1, summary->in(0).IsConstant() | 710 summary->set_in(1, summary->in(0).IsConstant() |
748 ? Location::RequiresRegister() | 711 ? Location::RequiresRegister() |
749 : Location::RegisterOrConstant(right())); | 712 : Location::RegisterOrConstant(right())); |
750 summary->set_out(0, Location::RequiresRegister()); | 713 summary->set_out(0, Location::RequiresRegister()); |
751 return summary; | 714 return summary; |
752 } | 715 } |
753 | 716 |
754 | |
755 Condition RelationalOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler, | 717 Condition RelationalOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
756 BranchLabels labels) { | 718 BranchLabels labels) { |
757 if (operation_cid() == kSmiCid) { | 719 if (operation_cid() == kSmiCid) { |
758 return EmitSmiComparisonOp(compiler, *locs(), kind(), labels); | 720 return EmitSmiComparisonOp(compiler, *locs(), kind(), labels); |
759 } else if (operation_cid() == kMintCid) { | 721 } else if (operation_cid() == kMintCid) { |
760 return EmitUnboxedMintComparisonOp(compiler, *locs(), kind(), labels); | 722 return EmitUnboxedMintComparisonOp(compiler, *locs(), kind(), labels); |
761 } else { | 723 } else { |
762 ASSERT(operation_cid() == kDoubleCid); | 724 ASSERT(operation_cid() == kDoubleCid); |
763 return EmitDoubleComparisonOp(compiler, *locs(), kind(), labels); | 725 return EmitDoubleComparisonOp(compiler, *locs(), kind(), labels); |
764 } | 726 } |
765 } | 727 } |
766 | 728 |
767 | |
768 LocationSummary* NativeCallInstr::MakeLocationSummary(Zone* zone, | 729 LocationSummary* NativeCallInstr::MakeLocationSummary(Zone* zone, |
769 bool opt) const { | 730 bool opt) const { |
770 return MakeCallSummary(zone); | 731 return MakeCallSummary(zone); |
771 } | 732 } |
772 | 733 |
773 | |
774 void NativeCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 734 void NativeCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
775 SetupNative(); | 735 SetupNative(); |
776 Register result = locs()->out(0).reg(); | 736 Register result = locs()->out(0).reg(); |
777 const intptr_t argc_tag = NativeArguments::ComputeArgcTag(function()); | 737 const intptr_t argc_tag = NativeArguments::ComputeArgcTag(function()); |
778 | 738 |
779 // Push the result place holder initialized to NULL. | 739 // Push the result place holder initialized to NULL. |
780 __ PushObject(Object::null_object()); | 740 __ PushObject(Object::null_object()); |
781 // Pass a pointer to the first argument in EAX. | 741 // Pass a pointer to the first argument in EAX. |
782 if (!function().HasOptionalParameters()) { | 742 if (!function().HasOptionalParameters()) { |
783 __ leal(EAX, | 743 __ leal(EAX, |
(...skipping 16 matching lines...) Expand all Loading... |
800 stub_entry = StubCode::CallNoScopeNative_entry(); | 760 stub_entry = StubCode::CallNoScopeNative_entry(); |
801 } | 761 } |
802 const ExternalLabel label(reinterpret_cast<uword>(native_c_function())); | 762 const ExternalLabel label(reinterpret_cast<uword>(native_c_function())); |
803 __ movl(ECX, Immediate(label.address())); | 763 __ movl(ECX, Immediate(label.address())); |
804 compiler->GenerateCall(token_pos(), *stub_entry, RawPcDescriptors::kOther, | 764 compiler->GenerateCall(token_pos(), *stub_entry, RawPcDescriptors::kOther, |
805 locs()); | 765 locs()); |
806 | 766 |
807 __ popl(result); | 767 __ popl(result); |
808 } | 768 } |
809 | 769 |
810 | |
811 static bool CanBeImmediateIndex(Value* value, intptr_t cid) { | 770 static bool CanBeImmediateIndex(Value* value, intptr_t cid) { |
812 ConstantInstr* constant = value->definition()->AsConstant(); | 771 ConstantInstr* constant = value->definition()->AsConstant(); |
813 if ((constant == NULL) || !Assembler::IsSafeSmi(constant->value())) { | 772 if ((constant == NULL) || !Assembler::IsSafeSmi(constant->value())) { |
814 return false; | 773 return false; |
815 } | 774 } |
816 const int64_t index = Smi::Cast(constant->value()).AsInt64Value(); | 775 const int64_t index = Smi::Cast(constant->value()).AsInt64Value(); |
817 const intptr_t scale = Instance::ElementSizeFor(cid); | 776 const intptr_t scale = Instance::ElementSizeFor(cid); |
818 const intptr_t offset = Instance::DataOffsetFor(cid); | 777 const intptr_t offset = Instance::DataOffsetFor(cid); |
819 const int64_t displacement = index * scale + offset; | 778 const int64_t displacement = index * scale + offset; |
820 return Utils::IsInt(32, displacement); | 779 return Utils::IsInt(32, displacement); |
821 } | 780 } |
822 | 781 |
823 | |
824 LocationSummary* OneByteStringFromCharCodeInstr::MakeLocationSummary( | 782 LocationSummary* OneByteStringFromCharCodeInstr::MakeLocationSummary( |
825 Zone* zone, | 783 Zone* zone, |
826 bool opt) const { | 784 bool opt) const { |
827 const intptr_t kNumInputs = 1; | 785 const intptr_t kNumInputs = 1; |
828 // TODO(fschneider): Allow immediate operands for the char code. | 786 // TODO(fschneider): Allow immediate operands for the char code. |
829 return LocationSummary::Make(zone, kNumInputs, Location::RequiresRegister(), | 787 return LocationSummary::Make(zone, kNumInputs, Location::RequiresRegister(), |
830 LocationSummary::kNoCall); | 788 LocationSummary::kNoCall); |
831 } | 789 } |
832 | 790 |
833 | |
834 void OneByteStringFromCharCodeInstr::EmitNativeCode( | 791 void OneByteStringFromCharCodeInstr::EmitNativeCode( |
835 FlowGraphCompiler* compiler) { | 792 FlowGraphCompiler* compiler) { |
836 Register char_code = locs()->in(0).reg(); | 793 Register char_code = locs()->in(0).reg(); |
837 Register result = locs()->out(0).reg(); | 794 Register result = locs()->out(0).reg(); |
838 __ movl(result, | 795 __ movl(result, |
839 Immediate(reinterpret_cast<uword>(Symbols::PredefinedAddress()))); | 796 Immediate(reinterpret_cast<uword>(Symbols::PredefinedAddress()))); |
840 __ movl(result, Address(result, char_code, | 797 __ movl(result, Address(result, char_code, |
841 TIMES_HALF_WORD_SIZE, // Char code is a smi. | 798 TIMES_HALF_WORD_SIZE, // Char code is a smi. |
842 Symbols::kNullCharCodeSymbolOffset * kWordSize)); | 799 Symbols::kNullCharCodeSymbolOffset * kWordSize)); |
843 } | 800 } |
844 | 801 |
845 | |
846 LocationSummary* StringToCharCodeInstr::MakeLocationSummary(Zone* zone, | 802 LocationSummary* StringToCharCodeInstr::MakeLocationSummary(Zone* zone, |
847 bool opt) const { | 803 bool opt) const { |
848 const intptr_t kNumInputs = 1; | 804 const intptr_t kNumInputs = 1; |
849 return LocationSummary::Make(zone, kNumInputs, Location::RequiresRegister(), | 805 return LocationSummary::Make(zone, kNumInputs, Location::RequiresRegister(), |
850 LocationSummary::kNoCall); | 806 LocationSummary::kNoCall); |
851 } | 807 } |
852 | 808 |
853 | |
854 void StringToCharCodeInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 809 void StringToCharCodeInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
855 ASSERT(cid_ == kOneByteStringCid); | 810 ASSERT(cid_ == kOneByteStringCid); |
856 Register str = locs()->in(0).reg(); | 811 Register str = locs()->in(0).reg(); |
857 Register result = locs()->out(0).reg(); | 812 Register result = locs()->out(0).reg(); |
858 Label is_one, done; | 813 Label is_one, done; |
859 __ movl(result, FieldAddress(str, String::length_offset())); | 814 __ movl(result, FieldAddress(str, String::length_offset())); |
860 __ cmpl(result, Immediate(Smi::RawValue(1))); | 815 __ cmpl(result, Immediate(Smi::RawValue(1))); |
861 __ j(EQUAL, &is_one, Assembler::kNearJump); | 816 __ j(EQUAL, &is_one, Assembler::kNearJump); |
862 __ movl(result, Immediate(Smi::RawValue(-1))); | 817 __ movl(result, Immediate(Smi::RawValue(-1))); |
863 __ jmp(&done); | 818 __ jmp(&done); |
864 __ Bind(&is_one); | 819 __ Bind(&is_one); |
865 __ movzxb(result, FieldAddress(str, OneByteString::data_offset())); | 820 __ movzxb(result, FieldAddress(str, OneByteString::data_offset())); |
866 __ SmiTag(result); | 821 __ SmiTag(result); |
867 __ Bind(&done); | 822 __ Bind(&done); |
868 } | 823 } |
869 | 824 |
870 | |
871 LocationSummary* StringInterpolateInstr::MakeLocationSummary(Zone* zone, | 825 LocationSummary* StringInterpolateInstr::MakeLocationSummary(Zone* zone, |
872 bool opt) const { | 826 bool opt) const { |
873 const intptr_t kNumInputs = 1; | 827 const intptr_t kNumInputs = 1; |
874 const intptr_t kNumTemps = 0; | 828 const intptr_t kNumTemps = 0; |
875 LocationSummary* summary = new (zone) | 829 LocationSummary* summary = new (zone) |
876 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 830 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
877 summary->set_in(0, Location::RegisterLocation(EAX)); | 831 summary->set_in(0, Location::RegisterLocation(EAX)); |
878 summary->set_out(0, Location::RegisterLocation(EAX)); | 832 summary->set_out(0, Location::RegisterLocation(EAX)); |
879 return summary; | 833 return summary; |
880 } | 834 } |
881 | 835 |
882 | |
883 void StringInterpolateInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 836 void StringInterpolateInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
884 Register array = locs()->in(0).reg(); | 837 Register array = locs()->in(0).reg(); |
885 __ pushl(array); | 838 __ pushl(array); |
886 const int kTypeArgsLen = 0; | 839 const int kTypeArgsLen = 0; |
887 const int kNumberOfArguments = 1; | 840 const int kNumberOfArguments = 1; |
888 const Array& kNoArgumentNames = Object::null_array(); | 841 const Array& kNoArgumentNames = Object::null_array(); |
889 ArgumentsInfo args_info(kTypeArgsLen, kNumberOfArguments, kNoArgumentNames); | 842 ArgumentsInfo args_info(kTypeArgsLen, kNumberOfArguments, kNoArgumentNames); |
890 compiler->GenerateStaticCall(deopt_id(), token_pos(), CallFunction(), | 843 compiler->GenerateStaticCall(deopt_id(), token_pos(), CallFunction(), |
891 args_info, locs(), ICData::Handle()); | 844 args_info, locs(), ICData::Handle()); |
892 ASSERT(locs()->out(0).reg() == EAX); | 845 ASSERT(locs()->out(0).reg() == EAX); |
893 } | 846 } |
894 | 847 |
895 | |
896 LocationSummary* LoadUntaggedInstr::MakeLocationSummary(Zone* zone, | 848 LocationSummary* LoadUntaggedInstr::MakeLocationSummary(Zone* zone, |
897 bool opt) const { | 849 bool opt) const { |
898 const intptr_t kNumInputs = 1; | 850 const intptr_t kNumInputs = 1; |
899 return LocationSummary::Make(zone, kNumInputs, Location::SameAsFirstInput(), | 851 return LocationSummary::Make(zone, kNumInputs, Location::SameAsFirstInput(), |
900 LocationSummary::kNoCall); | 852 LocationSummary::kNoCall); |
901 } | 853 } |
902 | 854 |
903 | |
904 void LoadUntaggedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 855 void LoadUntaggedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
905 Register obj = locs()->in(0).reg(); | 856 Register obj = locs()->in(0).reg(); |
906 Register result = locs()->out(0).reg(); | 857 Register result = locs()->out(0).reg(); |
907 if (object()->definition()->representation() == kUntagged) { | 858 if (object()->definition()->representation() == kUntagged) { |
908 __ movl(result, Address(obj, offset())); | 859 __ movl(result, Address(obj, offset())); |
909 } else { | 860 } else { |
910 ASSERT(object()->definition()->representation() == kTagged); | 861 ASSERT(object()->definition()->representation() == kTagged); |
911 __ movl(result, FieldAddress(obj, offset())); | 862 __ movl(result, FieldAddress(obj, offset())); |
912 } | 863 } |
913 } | 864 } |
914 | 865 |
915 | |
916 LocationSummary* LoadClassIdInstr::MakeLocationSummary(Zone* zone, | 866 LocationSummary* LoadClassIdInstr::MakeLocationSummary(Zone* zone, |
917 bool opt) const { | 867 bool opt) const { |
918 const intptr_t kNumInputs = 1; | 868 const intptr_t kNumInputs = 1; |
919 return LocationSummary::Make(zone, kNumInputs, Location::RequiresRegister(), | 869 return LocationSummary::Make(zone, kNumInputs, Location::RequiresRegister(), |
920 LocationSummary::kNoCall); | 870 LocationSummary::kNoCall); |
921 } | 871 } |
922 | 872 |
923 | |
924 void LoadClassIdInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 873 void LoadClassIdInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
925 const Register object = locs()->in(0).reg(); | 874 const Register object = locs()->in(0).reg(); |
926 const Register result = locs()->out(0).reg(); | 875 const Register result = locs()->out(0).reg(); |
927 const AbstractType& value_type = *this->object()->Type()->ToAbstractType(); | 876 const AbstractType& value_type = *this->object()->Type()->ToAbstractType(); |
928 if (CompileType::Smi().IsAssignableTo(value_type) || | 877 if (CompileType::Smi().IsAssignableTo(value_type) || |
929 value_type.IsTypeParameter()) { | 878 value_type.IsTypeParameter()) { |
930 // We don't use Assembler::LoadTaggedClassIdMayBeSmi() here---which uses | 879 // We don't use Assembler::LoadTaggedClassIdMayBeSmi() here---which uses |
931 // a conditional move instead, and requires an additional register---because | 880 // a conditional move instead, and requires an additional register---because |
932 // it is slower, probably due to branch prediction usually working just fine | 881 // it is slower, probably due to branch prediction usually working just fine |
933 // in this case. | 882 // in this case. |
934 ASSERT(result != object); | 883 ASSERT(result != object); |
935 Label done; | 884 Label done; |
936 __ movl(result, Immediate(kSmiCid << 1)); | 885 __ movl(result, Immediate(kSmiCid << 1)); |
937 __ testl(object, Immediate(kSmiTagMask)); | 886 __ testl(object, Immediate(kSmiTagMask)); |
938 __ j(EQUAL, &done, Assembler::kNearJump); | 887 __ j(EQUAL, &done, Assembler::kNearJump); |
939 __ LoadClassId(result, object); | 888 __ LoadClassId(result, object); |
940 __ SmiTag(result); | 889 __ SmiTag(result); |
941 __ Bind(&done); | 890 __ Bind(&done); |
942 } else { | 891 } else { |
943 __ LoadClassId(result, object); | 892 __ LoadClassId(result, object); |
944 __ SmiTag(result); | 893 __ SmiTag(result); |
945 } | 894 } |
946 } | 895 } |
947 | 896 |
948 | |
949 CompileType LoadIndexedInstr::ComputeType() const { | 897 CompileType LoadIndexedInstr::ComputeType() const { |
950 switch (class_id_) { | 898 switch (class_id_) { |
951 case kArrayCid: | 899 case kArrayCid: |
952 case kImmutableArrayCid: | 900 case kImmutableArrayCid: |
953 return CompileType::Dynamic(); | 901 return CompileType::Dynamic(); |
954 | 902 |
955 case kTypedDataFloat32ArrayCid: | 903 case kTypedDataFloat32ArrayCid: |
956 case kTypedDataFloat64ArrayCid: | 904 case kTypedDataFloat64ArrayCid: |
957 return CompileType::FromCid(kDoubleCid); | 905 return CompileType::FromCid(kDoubleCid); |
958 case kTypedDataFloat32x4ArrayCid: | 906 case kTypedDataFloat32x4ArrayCid: |
(...skipping 19 matching lines...) Expand all Loading... |
978 case kTypedDataInt32ArrayCid: | 926 case kTypedDataInt32ArrayCid: |
979 case kTypedDataUint32ArrayCid: | 927 case kTypedDataUint32ArrayCid: |
980 return CompileType::Int(); | 928 return CompileType::Int(); |
981 | 929 |
982 default: | 930 default: |
983 UNIMPLEMENTED(); | 931 UNIMPLEMENTED(); |
984 return CompileType::Dynamic(); | 932 return CompileType::Dynamic(); |
985 } | 933 } |
986 } | 934 } |
987 | 935 |
988 | |
989 Representation LoadIndexedInstr::representation() const { | 936 Representation LoadIndexedInstr::representation() const { |
990 switch (class_id_) { | 937 switch (class_id_) { |
991 case kArrayCid: | 938 case kArrayCid: |
992 case kImmutableArrayCid: | 939 case kImmutableArrayCid: |
993 case kTypedDataInt8ArrayCid: | 940 case kTypedDataInt8ArrayCid: |
994 case kTypedDataUint8ArrayCid: | 941 case kTypedDataUint8ArrayCid: |
995 case kTypedDataUint8ClampedArrayCid: | 942 case kTypedDataUint8ClampedArrayCid: |
996 case kExternalTypedDataUint8ArrayCid: | 943 case kExternalTypedDataUint8ArrayCid: |
997 case kExternalTypedDataUint8ClampedArrayCid: | 944 case kExternalTypedDataUint8ClampedArrayCid: |
998 case kTypedDataInt16ArrayCid: | 945 case kTypedDataInt16ArrayCid: |
(...skipping 15 matching lines...) Expand all Loading... |
1014 case kTypedDataInt32x4ArrayCid: | 961 case kTypedDataInt32x4ArrayCid: |
1015 return kUnboxedInt32x4; | 962 return kUnboxedInt32x4; |
1016 case kTypedDataFloat64x2ArrayCid: | 963 case kTypedDataFloat64x2ArrayCid: |
1017 return kUnboxedFloat64x2; | 964 return kUnboxedFloat64x2; |
1018 default: | 965 default: |
1019 UNIMPLEMENTED(); | 966 UNIMPLEMENTED(); |
1020 return kTagged; | 967 return kTagged; |
1021 } | 968 } |
1022 } | 969 } |
1023 | 970 |
1024 | |
1025 LocationSummary* LoadIndexedInstr::MakeLocationSummary(Zone* zone, | 971 LocationSummary* LoadIndexedInstr::MakeLocationSummary(Zone* zone, |
1026 bool opt) const { | 972 bool opt) const { |
1027 const intptr_t kNumInputs = 2; | 973 const intptr_t kNumInputs = 2; |
1028 const intptr_t kNumTemps = 0; | 974 const intptr_t kNumTemps = 0; |
1029 LocationSummary* locs = new (zone) | 975 LocationSummary* locs = new (zone) |
1030 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 976 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
1031 locs->set_in(0, Location::RequiresRegister()); | 977 locs->set_in(0, Location::RequiresRegister()); |
1032 if (CanBeImmediateIndex(index(), class_id())) { | 978 if (CanBeImmediateIndex(index(), class_id())) { |
1033 // CanBeImmediateIndex must return false for unsafe smis. | 979 // CanBeImmediateIndex must return false for unsafe smis. |
1034 locs->set_in(1, Location::Constant(index()->definition()->AsConstant())); | 980 locs->set_in(1, Location::Constant(index()->definition()->AsConstant())); |
(...skipping 14 matching lines...) Expand all Loading... |
1049 } else if (representation() == kUnboxedInt32) { | 995 } else if (representation() == kUnboxedInt32) { |
1050 ASSERT(class_id() == kTypedDataInt32ArrayCid); | 996 ASSERT(class_id() == kTypedDataInt32ArrayCid); |
1051 locs->set_out(0, Location::RequiresRegister()); | 997 locs->set_out(0, Location::RequiresRegister()); |
1052 } else { | 998 } else { |
1053 ASSERT(representation() == kTagged); | 999 ASSERT(representation() == kTagged); |
1054 locs->set_out(0, Location::RequiresRegister()); | 1000 locs->set_out(0, Location::RequiresRegister()); |
1055 } | 1001 } |
1056 return locs; | 1002 return locs; |
1057 } | 1003 } |
1058 | 1004 |
1059 | |
1060 void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1005 void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
1061 // The array register points to the backing store for external arrays. | 1006 // The array register points to the backing store for external arrays. |
1062 const Register array = locs()->in(0).reg(); | 1007 const Register array = locs()->in(0).reg(); |
1063 const Location index = locs()->in(1); | 1008 const Location index = locs()->in(1); |
1064 | 1009 |
1065 Address element_address = | 1010 Address element_address = |
1066 index.IsRegister() | 1011 index.IsRegister() |
1067 ? Assembler::ElementAddressForRegIndex( | 1012 ? Assembler::ElementAddressForRegIndex( |
1068 IsExternal(), class_id(), index_scale(), array, index.reg()) | 1013 IsExternal(), class_id(), index_scale(), array, index.reg()) |
1069 : Assembler::ElementAddressForIntIndex( | 1014 : Assembler::ElementAddressForIntIndex( |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1149 __ movzxw(result, element_address); | 1094 __ movzxw(result, element_address); |
1150 __ SmiTag(result); | 1095 __ SmiTag(result); |
1151 break; | 1096 break; |
1152 default: | 1097 default: |
1153 ASSERT((class_id() == kArrayCid) || (class_id() == kImmutableArrayCid)); | 1098 ASSERT((class_id() == kArrayCid) || (class_id() == kImmutableArrayCid)); |
1154 __ movl(result, element_address); | 1099 __ movl(result, element_address); |
1155 break; | 1100 break; |
1156 } | 1101 } |
1157 } | 1102 } |
1158 | 1103 |
1159 | |
1160 Representation StoreIndexedInstr::RequiredInputRepresentation( | 1104 Representation StoreIndexedInstr::RequiredInputRepresentation( |
1161 intptr_t idx) const { | 1105 intptr_t idx) const { |
1162 // Array can be a Dart object or a pointer to external data. | 1106 // Array can be a Dart object or a pointer to external data. |
1163 if (idx == 0) return kNoRepresentation; // Flexible input representation. | 1107 if (idx == 0) return kNoRepresentation; // Flexible input representation. |
1164 if (idx == 1) return kTagged; // Index is a smi. | 1108 if (idx == 1) return kTagged; // Index is a smi. |
1165 ASSERT(idx == 2); | 1109 ASSERT(idx == 2); |
1166 switch (class_id_) { | 1110 switch (class_id_) { |
1167 case kArrayCid: | 1111 case kArrayCid: |
1168 case kOneByteStringCid: | 1112 case kOneByteStringCid: |
1169 case kTypedDataInt8ArrayCid: | 1113 case kTypedDataInt8ArrayCid: |
(...skipping 16 matching lines...) Expand all Loading... |
1186 case kTypedDataInt32x4ArrayCid: | 1130 case kTypedDataInt32x4ArrayCid: |
1187 return kUnboxedInt32x4; | 1131 return kUnboxedInt32x4; |
1188 case kTypedDataFloat64x2ArrayCid: | 1132 case kTypedDataFloat64x2ArrayCid: |
1189 return kUnboxedFloat64x2; | 1133 return kUnboxedFloat64x2; |
1190 default: | 1134 default: |
1191 UNIMPLEMENTED(); | 1135 UNIMPLEMENTED(); |
1192 return kTagged; | 1136 return kTagged; |
1193 } | 1137 } |
1194 } | 1138 } |
1195 | 1139 |
1196 | |
1197 LocationSummary* StoreIndexedInstr::MakeLocationSummary(Zone* zone, | 1140 LocationSummary* StoreIndexedInstr::MakeLocationSummary(Zone* zone, |
1198 bool opt) const { | 1141 bool opt) const { |
1199 const intptr_t kNumInputs = 3; | 1142 const intptr_t kNumInputs = 3; |
1200 const intptr_t kNumTemps = 0; | 1143 const intptr_t kNumTemps = 0; |
1201 LocationSummary* locs = new (zone) | 1144 LocationSummary* locs = new (zone) |
1202 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1145 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
1203 locs->set_in(0, Location::RequiresRegister()); | 1146 locs->set_in(0, Location::RequiresRegister()); |
1204 if (CanBeImmediateIndex(index(), class_id())) { | 1147 if (CanBeImmediateIndex(index(), class_id())) { |
1205 // CanBeImmediateIndex must return false for unsafe smis. | 1148 // CanBeImmediateIndex must return false for unsafe smis. |
1206 locs->set_in(1, Location::Constant(index()->definition()->AsConstant())); | 1149 locs->set_in(1, Location::Constant(index()->definition()->AsConstant())); |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1245 case kTypedDataFloat64x2ArrayCid: | 1188 case kTypedDataFloat64x2ArrayCid: |
1246 locs->set_in(2, Location::RequiresFpuRegister()); | 1189 locs->set_in(2, Location::RequiresFpuRegister()); |
1247 break; | 1190 break; |
1248 default: | 1191 default: |
1249 UNREACHABLE(); | 1192 UNREACHABLE(); |
1250 return NULL; | 1193 return NULL; |
1251 } | 1194 } |
1252 return locs; | 1195 return locs; |
1253 } | 1196 } |
1254 | 1197 |
1255 | |
1256 void StoreIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1198 void StoreIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
1257 // The array register points to the backing store for external arrays. | 1199 // The array register points to the backing store for external arrays. |
1258 const Register array = locs()->in(0).reg(); | 1200 const Register array = locs()->in(0).reg(); |
1259 const Location index = locs()->in(1); | 1201 const Location index = locs()->in(1); |
1260 | 1202 |
1261 Address element_address = | 1203 Address element_address = |
1262 index.IsRegister() | 1204 index.IsRegister() |
1263 ? Assembler::ElementAddressForRegIndex( | 1205 ? Assembler::ElementAddressForRegIndex( |
1264 IsExternal(), class_id(), index_scale(), array, index.reg()) | 1206 IsExternal(), class_id(), index_scale(), array, index.reg()) |
1265 : Assembler::ElementAddressForIntIndex( | 1207 : Assembler::ElementAddressForIntIndex( |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1345 case kTypedDataInt32x4ArrayCid: | 1287 case kTypedDataInt32x4ArrayCid: |
1346 case kTypedDataFloat32x4ArrayCid: | 1288 case kTypedDataFloat32x4ArrayCid: |
1347 case kTypedDataFloat64x2ArrayCid: | 1289 case kTypedDataFloat64x2ArrayCid: |
1348 __ movups(element_address, locs()->in(2).fpu_reg()); | 1290 __ movups(element_address, locs()->in(2).fpu_reg()); |
1349 break; | 1291 break; |
1350 default: | 1292 default: |
1351 UNREACHABLE(); | 1293 UNREACHABLE(); |
1352 } | 1294 } |
1353 } | 1295 } |
1354 | 1296 |
1355 | |
1356 LocationSummary* GuardFieldClassInstr::MakeLocationSummary(Zone* zone, | 1297 LocationSummary* GuardFieldClassInstr::MakeLocationSummary(Zone* zone, |
1357 bool opt) const { | 1298 bool opt) const { |
1358 const intptr_t kNumInputs = 1; | 1299 const intptr_t kNumInputs = 1; |
1359 | 1300 |
1360 const intptr_t value_cid = value()->Type()->ToCid(); | 1301 const intptr_t value_cid = value()->Type()->ToCid(); |
1361 const intptr_t field_cid = field().guarded_cid(); | 1302 const intptr_t field_cid = field().guarded_cid(); |
1362 | 1303 |
1363 const bool emit_full_guard = !opt || (field_cid == kIllegalCid); | 1304 const bool emit_full_guard = !opt || (field_cid == kIllegalCid); |
1364 const bool needs_value_cid_temp_reg = | 1305 const bool needs_value_cid_temp_reg = |
1365 (value_cid == kDynamicCid) && (emit_full_guard || (field_cid != kSmiCid)); | 1306 (value_cid == kDynamicCid) && (emit_full_guard || (field_cid != kSmiCid)); |
(...skipping 11 matching lines...) Expand all Loading... |
1377 LocationSummary(zone, kNumInputs, num_temps, LocationSummary::kNoCall); | 1318 LocationSummary(zone, kNumInputs, num_temps, LocationSummary::kNoCall); |
1378 summary->set_in(0, Location::RequiresRegister()); | 1319 summary->set_in(0, Location::RequiresRegister()); |
1379 | 1320 |
1380 for (intptr_t i = 0; i < num_temps; i++) { | 1321 for (intptr_t i = 0; i < num_temps; i++) { |
1381 summary->set_temp(i, Location::RequiresRegister()); | 1322 summary->set_temp(i, Location::RequiresRegister()); |
1382 } | 1323 } |
1383 | 1324 |
1384 return summary; | 1325 return summary; |
1385 } | 1326 } |
1386 | 1327 |
1387 | |
1388 void GuardFieldClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1328 void GuardFieldClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
1389 ASSERT(sizeof(classid_t) == kInt16Size); | 1329 ASSERT(sizeof(classid_t) == kInt16Size); |
1390 const intptr_t value_cid = value()->Type()->ToCid(); | 1330 const intptr_t value_cid = value()->Type()->ToCid(); |
1391 const intptr_t field_cid = field().guarded_cid(); | 1331 const intptr_t field_cid = field().guarded_cid(); |
1392 const intptr_t nullability = field().is_nullable() ? kNullCid : kIllegalCid; | 1332 const intptr_t nullability = field().is_nullable() ? kNullCid : kIllegalCid; |
1393 | 1333 |
1394 if (field_cid == kDynamicCid) { | 1334 if (field_cid == kDynamicCid) { |
1395 if (Compiler::IsBackgroundCompilation()) { | 1335 if (Compiler::IsBackgroundCompilation()) { |
1396 // Field state changed while compiling. | 1336 // Field state changed while compiling. |
1397 Compiler::AbortBackgroundCompilation( | 1337 Compiler::AbortBackgroundCompilation( |
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1523 __ j(NOT_EQUAL, fail); | 1463 __ j(NOT_EQUAL, fail); |
1524 } else { | 1464 } else { |
1525 // Both value's and field's class id is known. | 1465 // Both value's and field's class id is known. |
1526 ASSERT((value_cid != field_cid) && (value_cid != nullability)); | 1466 ASSERT((value_cid != field_cid) && (value_cid != nullability)); |
1527 __ jmp(fail); | 1467 __ jmp(fail); |
1528 } | 1468 } |
1529 } | 1469 } |
1530 __ Bind(&ok); | 1470 __ Bind(&ok); |
1531 } | 1471 } |
1532 | 1472 |
1533 | |
1534 LocationSummary* GuardFieldLengthInstr::MakeLocationSummary(Zone* zone, | 1473 LocationSummary* GuardFieldLengthInstr::MakeLocationSummary(Zone* zone, |
1535 bool opt) const { | 1474 bool opt) const { |
1536 const intptr_t kNumInputs = 1; | 1475 const intptr_t kNumInputs = 1; |
1537 if (!opt || (field().guarded_list_length() == Field::kUnknownFixedLength)) { | 1476 if (!opt || (field().guarded_list_length() == Field::kUnknownFixedLength)) { |
1538 const intptr_t kNumTemps = 3; | 1477 const intptr_t kNumTemps = 3; |
1539 LocationSummary* summary = new (zone) | 1478 LocationSummary* summary = new (zone) |
1540 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1479 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
1541 summary->set_in(0, Location::RequiresRegister()); | 1480 summary->set_in(0, Location::RequiresRegister()); |
1542 // We need temporaries for field object, length offset and expected length. | 1481 // We need temporaries for field object, length offset and expected length. |
1543 summary->set_temp(0, Location::RequiresRegister()); | 1482 summary->set_temp(0, Location::RequiresRegister()); |
1544 summary->set_temp(1, Location::RequiresRegister()); | 1483 summary->set_temp(1, Location::RequiresRegister()); |
1545 summary->set_temp(2, Location::RequiresRegister()); | 1484 summary->set_temp(2, Location::RequiresRegister()); |
1546 return summary; | 1485 return summary; |
1547 } else { | 1486 } else { |
1548 LocationSummary* summary = new (zone) | 1487 LocationSummary* summary = new (zone) |
1549 LocationSummary(zone, kNumInputs, 0, LocationSummary::kNoCall); | 1488 LocationSummary(zone, kNumInputs, 0, LocationSummary::kNoCall); |
1550 summary->set_in(0, Location::RequiresRegister()); | 1489 summary->set_in(0, Location::RequiresRegister()); |
1551 return summary; | 1490 return summary; |
1552 } | 1491 } |
1553 UNREACHABLE(); | 1492 UNREACHABLE(); |
1554 } | 1493 } |
1555 | 1494 |
1556 | |
1557 void GuardFieldLengthInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1495 void GuardFieldLengthInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
1558 if (field().guarded_list_length() == Field::kNoFixedLength) { | 1496 if (field().guarded_list_length() == Field::kNoFixedLength) { |
1559 if (Compiler::IsBackgroundCompilation()) { | 1497 if (Compiler::IsBackgroundCompilation()) { |
1560 // Field state changed while compiling. | 1498 // Field state changed while compiling. |
1561 Compiler::AbortBackgroundCompilation( | 1499 Compiler::AbortBackgroundCompilation( |
1562 deopt_id(), | 1500 deopt_id(), |
1563 "GuardFieldLengthInstr: field state changed while compiling"); | 1501 "GuardFieldLengthInstr: field state changed while compiling"); |
1564 } | 1502 } |
1565 ASSERT(!compiler->is_optimizing()); | 1503 ASSERT(!compiler->is_optimizing()); |
1566 return; // Nothing to emit. | 1504 return; // Nothing to emit. |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1617 ASSERT(field().guarded_list_length_in_object_offset() != | 1555 ASSERT(field().guarded_list_length_in_object_offset() != |
1618 Field::kUnknownLengthOffset); | 1556 Field::kUnknownLengthOffset); |
1619 | 1557 |
1620 __ cmpl( | 1558 __ cmpl( |
1621 FieldAddress(value_reg, field().guarded_list_length_in_object_offset()), | 1559 FieldAddress(value_reg, field().guarded_list_length_in_object_offset()), |
1622 Immediate(Smi::RawValue(field().guarded_list_length()))); | 1560 Immediate(Smi::RawValue(field().guarded_list_length()))); |
1623 __ j(NOT_EQUAL, deopt); | 1561 __ j(NOT_EQUAL, deopt); |
1624 } | 1562 } |
1625 } | 1563 } |
1626 | 1564 |
1627 | |
1628 class BoxAllocationSlowPath : public SlowPathCode { | 1565 class BoxAllocationSlowPath : public SlowPathCode { |
1629 public: | 1566 public: |
1630 BoxAllocationSlowPath(Instruction* instruction, | 1567 BoxAllocationSlowPath(Instruction* instruction, |
1631 const Class& cls, | 1568 const Class& cls, |
1632 Register result) | 1569 Register result) |
1633 : instruction_(instruction), cls_(cls), result_(result) {} | 1570 : instruction_(instruction), cls_(cls), result_(result) {} |
1634 | 1571 |
1635 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { | 1572 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |
1636 if (Assembler::EmittingComments()) { | 1573 if (Assembler::EmittingComments()) { |
1637 __ Comment("%s slow path allocation of %s", instruction_->DebugName(), | 1574 __ Comment("%s slow path allocation of %s", instruction_->DebugName(), |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1673 __ Bind(slow_path->exit_label()); | 1610 __ Bind(slow_path->exit_label()); |
1674 } | 1611 } |
1675 } | 1612 } |
1676 | 1613 |
1677 private: | 1614 private: |
1678 Instruction* instruction_; | 1615 Instruction* instruction_; |
1679 const Class& cls_; | 1616 const Class& cls_; |
1680 const Register result_; | 1617 const Register result_; |
1681 }; | 1618 }; |
1682 | 1619 |
1683 | |
1684 LocationSummary* StoreInstanceFieldInstr::MakeLocationSummary(Zone* zone, | 1620 LocationSummary* StoreInstanceFieldInstr::MakeLocationSummary(Zone* zone, |
1685 bool opt) const { | 1621 bool opt) const { |
1686 const intptr_t kNumInputs = 2; | 1622 const intptr_t kNumInputs = 2; |
1687 const intptr_t kNumTemps = | 1623 const intptr_t kNumTemps = |
1688 (IsUnboxedStore() && opt) ? 2 : ((IsPotentialUnboxedStore()) ? 3 : 0); | 1624 (IsUnboxedStore() && opt) ? 2 : ((IsPotentialUnboxedStore()) ? 3 : 0); |
1689 LocationSummary* summary = new (zone) | 1625 LocationSummary* summary = new (zone) |
1690 LocationSummary(zone, kNumInputs, kNumTemps, | 1626 LocationSummary(zone, kNumInputs, kNumTemps, |
1691 ((IsUnboxedStore() && opt && is_initialization()) || | 1627 ((IsUnboxedStore() && opt && is_initialization()) || |
1692 IsPotentialUnboxedStore()) | 1628 IsPotentialUnboxedStore()) |
1693 ? LocationSummary::kCallOnSlowPath | 1629 ? LocationSummary::kCallOnSlowPath |
(...skipping 12 matching lines...) Expand all Loading... |
1706 summary->set_temp(2, opt ? Location::RequiresFpuRegister() | 1642 summary->set_temp(2, opt ? Location::RequiresFpuRegister() |
1707 : Location::FpuRegisterLocation(XMM1)); | 1643 : Location::FpuRegisterLocation(XMM1)); |
1708 } else { | 1644 } else { |
1709 summary->set_in(1, ShouldEmitStoreBarrier() | 1645 summary->set_in(1, ShouldEmitStoreBarrier() |
1710 ? Location::WritableRegister() | 1646 ? Location::WritableRegister() |
1711 : Location::RegisterOrConstant(value())); | 1647 : Location::RegisterOrConstant(value())); |
1712 } | 1648 } |
1713 return summary; | 1649 return summary; |
1714 } | 1650 } |
1715 | 1651 |
1716 | |
1717 static void EnsureMutableBox(FlowGraphCompiler* compiler, | 1652 static void EnsureMutableBox(FlowGraphCompiler* compiler, |
1718 StoreInstanceFieldInstr* instruction, | 1653 StoreInstanceFieldInstr* instruction, |
1719 Register box_reg, | 1654 Register box_reg, |
1720 const Class& cls, | 1655 const Class& cls, |
1721 Register instance_reg, | 1656 Register instance_reg, |
1722 intptr_t offset, | 1657 intptr_t offset, |
1723 Register temp) { | 1658 Register temp) { |
1724 Label done; | 1659 Label done; |
1725 const Immediate& raw_null = | 1660 const Immediate& raw_null = |
1726 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 1661 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
1727 __ movl(box_reg, FieldAddress(instance_reg, offset)); | 1662 __ movl(box_reg, FieldAddress(instance_reg, offset)); |
1728 __ cmpl(box_reg, raw_null); | 1663 __ cmpl(box_reg, raw_null); |
1729 __ j(NOT_EQUAL, &done); | 1664 __ j(NOT_EQUAL, &done); |
1730 BoxAllocationSlowPath::Allocate(compiler, instruction, cls, box_reg, temp); | 1665 BoxAllocationSlowPath::Allocate(compiler, instruction, cls, box_reg, temp); |
1731 __ movl(temp, box_reg); | 1666 __ movl(temp, box_reg); |
1732 __ StoreIntoObject(instance_reg, FieldAddress(instance_reg, offset), temp); | 1667 __ StoreIntoObject(instance_reg, FieldAddress(instance_reg, offset), temp); |
1733 | 1668 |
1734 __ Bind(&done); | 1669 __ Bind(&done); |
1735 } | 1670 } |
1736 | 1671 |
1737 | |
1738 void StoreInstanceFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1672 void StoreInstanceFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
1739 ASSERT(sizeof(classid_t) == kInt16Size); | 1673 ASSERT(sizeof(classid_t) == kInt16Size); |
1740 Label skip_store; | 1674 Label skip_store; |
1741 | 1675 |
1742 Register instance_reg = locs()->in(0).reg(); | 1676 Register instance_reg = locs()->in(0).reg(); |
1743 | 1677 |
1744 if (IsUnboxedStore() && compiler->is_optimizing()) { | 1678 if (IsUnboxedStore() && compiler->is_optimizing()) { |
1745 XmmRegister value = locs()->in(1).fpu_reg(); | 1679 XmmRegister value = locs()->in(1).fpu_reg(); |
1746 Register temp = locs()->temp(0).reg(); | 1680 Register temp = locs()->temp(0).reg(); |
1747 Register temp2 = locs()->temp(1).reg(); | 1681 Register temp2 = locs()->temp(1).reg(); |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1825 Immediate(kFloat32x4Cid)); | 1759 Immediate(kFloat32x4Cid)); |
1826 __ j(EQUAL, &store_float32x4); | 1760 __ j(EQUAL, &store_float32x4); |
1827 | 1761 |
1828 __ cmpw(FieldAddress(temp, Field::guarded_cid_offset()), | 1762 __ cmpw(FieldAddress(temp, Field::guarded_cid_offset()), |
1829 Immediate(kFloat64x2Cid)); | 1763 Immediate(kFloat64x2Cid)); |
1830 __ j(EQUAL, &store_float64x2); | 1764 __ j(EQUAL, &store_float64x2); |
1831 | 1765 |
1832 // Fall through. | 1766 // Fall through. |
1833 __ jmp(&store_pointer); | 1767 __ jmp(&store_pointer); |
1834 | 1768 |
1835 | |
1836 if (!compiler->is_optimizing()) { | 1769 if (!compiler->is_optimizing()) { |
1837 locs()->live_registers()->Add(locs()->in(0)); | 1770 locs()->live_registers()->Add(locs()->in(0)); |
1838 locs()->live_registers()->Add(locs()->in(1)); | 1771 locs()->live_registers()->Add(locs()->in(1)); |
1839 } | 1772 } |
1840 | 1773 |
1841 { | 1774 { |
1842 __ Bind(&store_double); | 1775 __ Bind(&store_double); |
1843 EnsureMutableBox(compiler, this, temp, compiler->double_class(), | 1776 EnsureMutableBox(compiler, this, temp, compiler->double_class(), |
1844 instance_reg, offset_in_bytes_, temp2); | 1777 instance_reg, offset_in_bytes_, temp2); |
1845 __ movsd(fpu_temp, FieldAddress(value_reg, Double::value_offset())); | 1778 __ movsd(fpu_temp, FieldAddress(value_reg, Double::value_offset())); |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1881 } else { | 1814 } else { |
1882 Register value_reg = locs()->in(1).reg(); | 1815 Register value_reg = locs()->in(1).reg(); |
1883 __ StoreIntoObjectNoBarrier(instance_reg, | 1816 __ StoreIntoObjectNoBarrier(instance_reg, |
1884 FieldAddress(instance_reg, offset_in_bytes_), | 1817 FieldAddress(instance_reg, offset_in_bytes_), |
1885 value_reg); | 1818 value_reg); |
1886 } | 1819 } |
1887 } | 1820 } |
1888 __ Bind(&skip_store); | 1821 __ Bind(&skip_store); |
1889 } | 1822 } |
1890 | 1823 |
1891 | |
1892 LocationSummary* LoadStaticFieldInstr::MakeLocationSummary(Zone* zone, | 1824 LocationSummary* LoadStaticFieldInstr::MakeLocationSummary(Zone* zone, |
1893 bool opt) const { | 1825 bool opt) const { |
1894 const intptr_t kNumInputs = 1; | 1826 const intptr_t kNumInputs = 1; |
1895 const intptr_t kNumTemps = 0; | 1827 const intptr_t kNumTemps = 0; |
1896 LocationSummary* summary = new (zone) | 1828 LocationSummary* summary = new (zone) |
1897 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1829 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
1898 summary->set_in(0, Location::RequiresRegister()); | 1830 summary->set_in(0, Location::RequiresRegister()); |
1899 // By specifying same register as input, our simple register allocator can | 1831 // By specifying same register as input, our simple register allocator can |
1900 // generate better code. | 1832 // generate better code. |
1901 summary->set_out(0, Location::SameAsFirstInput()); | 1833 summary->set_out(0, Location::SameAsFirstInput()); |
1902 return summary; | 1834 return summary; |
1903 } | 1835 } |
1904 | 1836 |
1905 | |
1906 // When the parser is building an implicit static getter for optimization, | 1837 // When the parser is building an implicit static getter for optimization, |
1907 // it can generate a function body where deoptimization ids do not line up | 1838 // it can generate a function body where deoptimization ids do not line up |
1908 // with the unoptimized code. | 1839 // with the unoptimized code. |
1909 // | 1840 // |
1910 // This is safe only so long as LoadStaticFieldInstr cannot deoptimize. | 1841 // This is safe only so long as LoadStaticFieldInstr cannot deoptimize. |
1911 void LoadStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1842 void LoadStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
1912 Register field = locs()->in(0).reg(); | 1843 Register field = locs()->in(0).reg(); |
1913 Register result = locs()->out(0).reg(); | 1844 Register result = locs()->out(0).reg(); |
1914 __ movl(result, FieldAddress(field, Field::static_value_offset())); | 1845 __ movl(result, FieldAddress(field, Field::static_value_offset())); |
1915 } | 1846 } |
1916 | 1847 |
1917 | |
1918 LocationSummary* StoreStaticFieldInstr::MakeLocationSummary(Zone* zone, | 1848 LocationSummary* StoreStaticFieldInstr::MakeLocationSummary(Zone* zone, |
1919 bool opt) const { | 1849 bool opt) const { |
1920 LocationSummary* locs = | 1850 LocationSummary* locs = |
1921 new (zone) LocationSummary(zone, 1, 1, LocationSummary::kNoCall); | 1851 new (zone) LocationSummary(zone, 1, 1, LocationSummary::kNoCall); |
1922 locs->set_in(0, value()->NeedsStoreBuffer() ? Location::WritableRegister() | 1852 locs->set_in(0, value()->NeedsStoreBuffer() ? Location::WritableRegister() |
1923 : Location::RequiresRegister()); | 1853 : Location::RequiresRegister()); |
1924 locs->set_temp(0, Location::RequiresRegister()); | 1854 locs->set_temp(0, Location::RequiresRegister()); |
1925 return locs; | 1855 return locs; |
1926 } | 1856 } |
1927 | 1857 |
1928 | |
1929 void StoreStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1858 void StoreStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
1930 Register value = locs()->in(0).reg(); | 1859 Register value = locs()->in(0).reg(); |
1931 Register temp = locs()->temp(0).reg(); | 1860 Register temp = locs()->temp(0).reg(); |
1932 | 1861 |
1933 __ LoadObject(temp, Field::ZoneHandle(Z, field().Original())); | 1862 __ LoadObject(temp, Field::ZoneHandle(Z, field().Original())); |
1934 if (this->value()->NeedsStoreBuffer()) { | 1863 if (this->value()->NeedsStoreBuffer()) { |
1935 __ StoreIntoObject(temp, FieldAddress(temp, Field::static_value_offset()), | 1864 __ StoreIntoObject(temp, FieldAddress(temp, Field::static_value_offset()), |
1936 value, CanValueBeSmi()); | 1865 value, CanValueBeSmi()); |
1937 } else { | 1866 } else { |
1938 __ StoreIntoObjectNoBarrier( | 1867 __ StoreIntoObjectNoBarrier( |
1939 temp, FieldAddress(temp, Field::static_value_offset()), value); | 1868 temp, FieldAddress(temp, Field::static_value_offset()), value); |
1940 } | 1869 } |
1941 } | 1870 } |
1942 | 1871 |
1943 | |
1944 LocationSummary* InstanceOfInstr::MakeLocationSummary(Zone* zone, | 1872 LocationSummary* InstanceOfInstr::MakeLocationSummary(Zone* zone, |
1945 bool opt) const { | 1873 bool opt) const { |
1946 const intptr_t kNumInputs = 3; | 1874 const intptr_t kNumInputs = 3; |
1947 const intptr_t kNumTemps = 0; | 1875 const intptr_t kNumTemps = 0; |
1948 LocationSummary* summary = new (zone) | 1876 LocationSummary* summary = new (zone) |
1949 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 1877 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
1950 summary->set_in(0, Location::RegisterLocation(EAX)); // Instance. | 1878 summary->set_in(0, Location::RegisterLocation(EAX)); // Instance. |
1951 summary->set_in(1, Location::RegisterLocation(EDX)); // Instant. type args. | 1879 summary->set_in(1, Location::RegisterLocation(EDX)); // Instant. type args. |
1952 summary->set_in(2, Location::RegisterLocation(ECX)); // Function type args. | 1880 summary->set_in(2, Location::RegisterLocation(ECX)); // Function type args. |
1953 summary->set_out(0, Location::RegisterLocation(EAX)); | 1881 summary->set_out(0, Location::RegisterLocation(EAX)); |
1954 return summary; | 1882 return summary; |
1955 } | 1883 } |
1956 | 1884 |
1957 | |
1958 void InstanceOfInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1885 void InstanceOfInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
1959 ASSERT(locs()->in(0).reg() == EAX); // Value. | 1886 ASSERT(locs()->in(0).reg() == EAX); // Value. |
1960 ASSERT(locs()->in(1).reg() == EDX); // Instantiator type arguments. | 1887 ASSERT(locs()->in(1).reg() == EDX); // Instantiator type arguments. |
1961 ASSERT(locs()->in(2).reg() == ECX); // Function type arguments. | 1888 ASSERT(locs()->in(2).reg() == ECX); // Function type arguments. |
1962 | 1889 |
1963 compiler->GenerateInstanceOf(token_pos(), deopt_id(), type(), locs()); | 1890 compiler->GenerateInstanceOf(token_pos(), deopt_id(), type(), locs()); |
1964 ASSERT(locs()->out(0).reg() == EAX); | 1891 ASSERT(locs()->out(0).reg() == EAX); |
1965 } | 1892 } |
1966 | 1893 |
1967 | |
1968 // TODO(srdjan): In case of constant inputs make CreateArray kNoCall and | 1894 // TODO(srdjan): In case of constant inputs make CreateArray kNoCall and |
1969 // use slow path stub. | 1895 // use slow path stub. |
1970 LocationSummary* CreateArrayInstr::MakeLocationSummary(Zone* zone, | 1896 LocationSummary* CreateArrayInstr::MakeLocationSummary(Zone* zone, |
1971 bool opt) const { | 1897 bool opt) const { |
1972 const intptr_t kNumInputs = 2; | 1898 const intptr_t kNumInputs = 2; |
1973 const intptr_t kNumTemps = 0; | 1899 const intptr_t kNumTemps = 0; |
1974 LocationSummary* locs = new (zone) | 1900 LocationSummary* locs = new (zone) |
1975 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 1901 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
1976 locs->set_in(0, Location::RegisterLocation(ECX)); | 1902 locs->set_in(0, Location::RegisterLocation(ECX)); |
1977 locs->set_in(1, Location::RegisterLocation(EDX)); | 1903 locs->set_in(1, Location::RegisterLocation(EDX)); |
1978 locs->set_out(0, Location::RegisterLocation(EAX)); | 1904 locs->set_out(0, Location::RegisterLocation(EAX)); |
1979 return locs; | 1905 return locs; |
1980 } | 1906 } |
1981 | 1907 |
1982 | |
1983 // Inlines array allocation for known constant values. | 1908 // Inlines array allocation for known constant values. |
1984 static void InlineArrayAllocation(FlowGraphCompiler* compiler, | 1909 static void InlineArrayAllocation(FlowGraphCompiler* compiler, |
1985 intptr_t num_elements, | 1910 intptr_t num_elements, |
1986 Label* slow_path, | 1911 Label* slow_path, |
1987 Label* done) { | 1912 Label* done) { |
1988 const int kInlineArraySize = 12; // Same as kInlineInstanceSize. | 1913 const int kInlineArraySize = 12; // Same as kInlineInstanceSize. |
1989 const Register kLengthReg = EDX; | 1914 const Register kLengthReg = EDX; |
1990 const Register kElemTypeReg = ECX; | 1915 const Register kElemTypeReg = ECX; |
1991 const intptr_t instance_size = Array::InstanceSize(num_elements); | 1916 const intptr_t instance_size = Array::InstanceSize(num_elements); |
1992 | 1917 |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2027 __ Bind(&init_loop); | 1952 __ Bind(&init_loop); |
2028 __ StoreIntoObjectNoBarrier(EAX, Address(EDI, 0), Object::null_object()); | 1953 __ StoreIntoObjectNoBarrier(EAX, Address(EDI, 0), Object::null_object()); |
2029 __ addl(EDI, Immediate(kWordSize)); | 1954 __ addl(EDI, Immediate(kWordSize)); |
2030 __ cmpl(EDI, EBX); | 1955 __ cmpl(EDI, EBX); |
2031 __ j(BELOW, &init_loop, Assembler::kNearJump); | 1956 __ j(BELOW, &init_loop, Assembler::kNearJump); |
2032 } | 1957 } |
2033 } | 1958 } |
2034 __ jmp(done, Assembler::kNearJump); | 1959 __ jmp(done, Assembler::kNearJump); |
2035 } | 1960 } |
2036 | 1961 |
2037 | |
2038 void CreateArrayInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1962 void CreateArrayInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
2039 // Allocate the array. EDX = length, ECX = element type. | 1963 // Allocate the array. EDX = length, ECX = element type. |
2040 const Register kLengthReg = EDX; | 1964 const Register kLengthReg = EDX; |
2041 const Register kElemTypeReg = ECX; | 1965 const Register kElemTypeReg = ECX; |
2042 const Register kResultReg = EAX; | 1966 const Register kResultReg = EAX; |
2043 ASSERT(locs()->in(0).reg() == kElemTypeReg); | 1967 ASSERT(locs()->in(0).reg() == kElemTypeReg); |
2044 ASSERT(locs()->in(1).reg() == kLengthReg); | 1968 ASSERT(locs()->in(1).reg() == kLengthReg); |
2045 | 1969 |
2046 Label slow_path, done; | 1970 Label slow_path, done; |
2047 if (compiler->is_optimizing() && num_elements()->BindsToConstant() && | 1971 if (compiler->is_optimizing() && num_elements()->BindsToConstant() && |
(...skipping 19 matching lines...) Expand all Loading... |
2067 const Code& stub = Code::ZoneHandle(compiler->zone(), | 1991 const Code& stub = Code::ZoneHandle(compiler->zone(), |
2068 StubCode::AllocateArray_entry()->code()); | 1992 StubCode::AllocateArray_entry()->code()); |
2069 compiler->AddStubCallTarget(stub); | 1993 compiler->AddStubCallTarget(stub); |
2070 compiler->GenerateCallWithDeopt(token_pos(), deopt_id(), | 1994 compiler->GenerateCallWithDeopt(token_pos(), deopt_id(), |
2071 *StubCode::AllocateArray_entry(), | 1995 *StubCode::AllocateArray_entry(), |
2072 RawPcDescriptors::kOther, locs()); | 1996 RawPcDescriptors::kOther, locs()); |
2073 __ Bind(&done); | 1997 __ Bind(&done); |
2074 ASSERT(locs()->out(0).reg() == kResultReg); | 1998 ASSERT(locs()->out(0).reg() == kResultReg); |
2075 } | 1999 } |
2076 | 2000 |
2077 | |
2078 LocationSummary* LoadFieldInstr::MakeLocationSummary(Zone* zone, | 2001 LocationSummary* LoadFieldInstr::MakeLocationSummary(Zone* zone, |
2079 bool opt) const { | 2002 bool opt) const { |
2080 const intptr_t kNumInputs = 1; | 2003 const intptr_t kNumInputs = 1; |
2081 const intptr_t kNumTemps = | 2004 const intptr_t kNumTemps = |
2082 (IsUnboxedLoad() && opt) ? 1 : ((IsPotentialUnboxedLoad()) ? 2 : 0); | 2005 (IsUnboxedLoad() && opt) ? 1 : ((IsPotentialUnboxedLoad()) ? 2 : 0); |
2083 | 2006 |
2084 LocationSummary* locs = new (zone) LocationSummary( | 2007 LocationSummary* locs = new (zone) LocationSummary( |
2085 zone, kNumInputs, kNumTemps, (opt && !IsPotentialUnboxedLoad()) | 2008 zone, kNumInputs, kNumTemps, |
2086 ? LocationSummary::kNoCall | 2009 (opt && !IsPotentialUnboxedLoad()) ? LocationSummary::kNoCall |
2087 : LocationSummary::kCallOnSlowPath); | 2010 : LocationSummary::kCallOnSlowPath); |
2088 | 2011 |
2089 locs->set_in(0, Location::RequiresRegister()); | 2012 locs->set_in(0, Location::RequiresRegister()); |
2090 | 2013 |
2091 if (IsUnboxedLoad() && opt) { | 2014 if (IsUnboxedLoad() && opt) { |
2092 locs->set_temp(0, Location::RequiresRegister()); | 2015 locs->set_temp(0, Location::RequiresRegister()); |
2093 } else if (IsPotentialUnboxedLoad()) { | 2016 } else if (IsPotentialUnboxedLoad()) { |
2094 locs->set_temp(0, opt ? Location::RequiresFpuRegister() | 2017 locs->set_temp(0, opt ? Location::RequiresFpuRegister() |
2095 : Location::FpuRegisterLocation(XMM1)); | 2018 : Location::FpuRegisterLocation(XMM1)); |
2096 locs->set_temp(1, Location::RequiresRegister()); | 2019 locs->set_temp(1, Location::RequiresRegister()); |
2097 } | 2020 } |
2098 locs->set_out(0, Location::RequiresRegister()); | 2021 locs->set_out(0, Location::RequiresRegister()); |
2099 return locs; | 2022 return locs; |
2100 } | 2023 } |
2101 | 2024 |
2102 | |
2103 void LoadFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2025 void LoadFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
2104 ASSERT(sizeof(classid_t) == kInt16Size); | 2026 ASSERT(sizeof(classid_t) == kInt16Size); |
2105 | 2027 |
2106 Register instance_reg = locs()->in(0).reg(); | 2028 Register instance_reg = locs()->in(0).reg(); |
2107 if (IsUnboxedLoad() && compiler->is_optimizing()) { | 2029 if (IsUnboxedLoad() && compiler->is_optimizing()) { |
2108 XmmRegister result = locs()->out(0).fpu_reg(); | 2030 XmmRegister result = locs()->out(0).fpu_reg(); |
2109 Register temp = locs()->temp(0).reg(); | 2031 Register temp = locs()->temp(0).reg(); |
2110 __ movl(temp, FieldAddress(instance_reg, offset_in_bytes())); | 2032 __ movl(temp, FieldAddress(instance_reg, offset_in_bytes())); |
2111 const intptr_t cid = field()->UnboxedFieldCid(); | 2033 const intptr_t cid = field()->UnboxedFieldCid(); |
2112 switch (cid) { | 2034 switch (cid) { |
(...skipping 14 matching lines...) Expand all Loading... |
2127 } | 2049 } |
2128 return; | 2050 return; |
2129 } | 2051 } |
2130 | 2052 |
2131 Label done; | 2053 Label done; |
2132 Register result = locs()->out(0).reg(); | 2054 Register result = locs()->out(0).reg(); |
2133 if (IsPotentialUnboxedLoad()) { | 2055 if (IsPotentialUnboxedLoad()) { |
2134 Register temp = locs()->temp(1).reg(); | 2056 Register temp = locs()->temp(1).reg(); |
2135 XmmRegister value = locs()->temp(0).fpu_reg(); | 2057 XmmRegister value = locs()->temp(0).fpu_reg(); |
2136 | 2058 |
2137 | |
2138 Label load_pointer; | 2059 Label load_pointer; |
2139 Label load_double; | 2060 Label load_double; |
2140 Label load_float32x4; | 2061 Label load_float32x4; |
2141 Label load_float64x2; | 2062 Label load_float64x2; |
2142 | 2063 |
2143 __ LoadObject(result, Field::ZoneHandle(field()->Original())); | 2064 __ LoadObject(result, Field::ZoneHandle(field()->Original())); |
2144 | 2065 |
2145 FieldAddress field_cid_operand(result, Field::guarded_cid_offset()); | 2066 FieldAddress field_cid_operand(result, Field::guarded_cid_offset()); |
2146 FieldAddress field_nullability_operand(result, Field::is_nullable_offset()); | 2067 FieldAddress field_nullability_operand(result, Field::is_nullable_offset()); |
2147 | 2068 |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2193 __ movups(FieldAddress(result, Float64x2::value_offset()), value); | 2114 __ movups(FieldAddress(result, Float64x2::value_offset()), value); |
2194 __ jmp(&done); | 2115 __ jmp(&done); |
2195 } | 2116 } |
2196 | 2117 |
2197 __ Bind(&load_pointer); | 2118 __ Bind(&load_pointer); |
2198 } | 2119 } |
2199 __ movl(result, FieldAddress(instance_reg, offset_in_bytes())); | 2120 __ movl(result, FieldAddress(instance_reg, offset_in_bytes())); |
2200 __ Bind(&done); | 2121 __ Bind(&done); |
2201 } | 2122 } |
2202 | 2123 |
2203 | |
2204 LocationSummary* InstantiateTypeInstr::MakeLocationSummary(Zone* zone, | 2124 LocationSummary* InstantiateTypeInstr::MakeLocationSummary(Zone* zone, |
2205 bool opt) const { | 2125 bool opt) const { |
2206 const intptr_t kNumInputs = 2; | 2126 const intptr_t kNumInputs = 2; |
2207 const intptr_t kNumTemps = 0; | 2127 const intptr_t kNumTemps = 0; |
2208 LocationSummary* locs = new (zone) | 2128 LocationSummary* locs = new (zone) |
2209 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 2129 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
2210 locs->set_in(0, Location::RegisterLocation(EAX)); // Instant. type args. | 2130 locs->set_in(0, Location::RegisterLocation(EAX)); // Instant. type args. |
2211 locs->set_in(1, Location::RegisterLocation(EDX)); // Function type args. | 2131 locs->set_in(1, Location::RegisterLocation(EDX)); // Function type args. |
2212 locs->set_out(0, Location::RegisterLocation(EAX)); | 2132 locs->set_out(0, Location::RegisterLocation(EAX)); |
2213 return locs; | 2133 return locs; |
2214 } | 2134 } |
2215 | 2135 |
2216 | |
2217 void InstantiateTypeInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2136 void InstantiateTypeInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
2218 Register instantiator_type_args_reg = locs()->in(0).reg(); | 2137 Register instantiator_type_args_reg = locs()->in(0).reg(); |
2219 Register function_type_args_reg = locs()->in(1).reg(); | 2138 Register function_type_args_reg = locs()->in(1).reg(); |
2220 Register result_reg = locs()->out(0).reg(); | 2139 Register result_reg = locs()->out(0).reg(); |
2221 | 2140 |
2222 // 'instantiator_type_args_reg' is a TypeArguments object (or null). | 2141 // 'instantiator_type_args_reg' is a TypeArguments object (or null). |
2223 // 'function_type_args_reg' is a TypeArguments object (or null). | 2142 // 'function_type_args_reg' is a TypeArguments object (or null). |
2224 // A runtime call to instantiate the type is required. | 2143 // A runtime call to instantiate the type is required. |
2225 __ PushObject(Object::null_object()); // Make room for the result. | 2144 __ PushObject(Object::null_object()); // Make room for the result. |
2226 __ PushObject(type()); | 2145 __ PushObject(type()); |
2227 __ pushl(instantiator_type_args_reg); // Push instantiator type arguments. | 2146 __ pushl(instantiator_type_args_reg); // Push instantiator type arguments. |
2228 __ pushl(function_type_args_reg); // Push function type arguments. | 2147 __ pushl(function_type_args_reg); // Push function type arguments. |
2229 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), | 2148 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), |
2230 kInstantiateTypeRuntimeEntry, 3, locs()); | 2149 kInstantiateTypeRuntimeEntry, 3, locs()); |
2231 __ Drop(3); // Drop 2 type argument vectors and uninstantiated type. | 2150 __ Drop(3); // Drop 2 type argument vectors and uninstantiated type. |
2232 __ popl(result_reg); // Pop instantiated type. | 2151 __ popl(result_reg); // Pop instantiated type. |
2233 ASSERT(instantiator_type_args_reg == result_reg); | 2152 ASSERT(instantiator_type_args_reg == result_reg); |
2234 } | 2153 } |
2235 | 2154 |
2236 | |
2237 LocationSummary* InstantiateTypeArgumentsInstr::MakeLocationSummary( | 2155 LocationSummary* InstantiateTypeArgumentsInstr::MakeLocationSummary( |
2238 Zone* zone, | 2156 Zone* zone, |
2239 bool opt) const { | 2157 bool opt) const { |
2240 const intptr_t kNumInputs = 2; | 2158 const intptr_t kNumInputs = 2; |
2241 const intptr_t kNumTemps = 0; | 2159 const intptr_t kNumTemps = 0; |
2242 LocationSummary* locs = new (zone) | 2160 LocationSummary* locs = new (zone) |
2243 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 2161 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
2244 locs->set_in(0, Location::RegisterLocation(EAX)); // Instant. type args. | 2162 locs->set_in(0, Location::RegisterLocation(EAX)); // Instant. type args. |
2245 locs->set_in(1, Location::RegisterLocation(ECX)); // Function type args. | 2163 locs->set_in(1, Location::RegisterLocation(ECX)); // Function type args. |
2246 locs->set_out(0, Location::RegisterLocation(EAX)); | 2164 locs->set_out(0, Location::RegisterLocation(EAX)); |
2247 return locs; | 2165 return locs; |
2248 } | 2166 } |
2249 | 2167 |
2250 | |
2251 void InstantiateTypeArgumentsInstr::EmitNativeCode( | 2168 void InstantiateTypeArgumentsInstr::EmitNativeCode( |
2252 FlowGraphCompiler* compiler) { | 2169 FlowGraphCompiler* compiler) { |
2253 Register instantiator_type_args_reg = locs()->in(0).reg(); | 2170 Register instantiator_type_args_reg = locs()->in(0).reg(); |
2254 Register function_type_args_reg = locs()->in(1).reg(); | 2171 Register function_type_args_reg = locs()->in(1).reg(); |
2255 Register result_reg = locs()->out(0).reg(); | 2172 Register result_reg = locs()->out(0).reg(); |
2256 ASSERT(instantiator_type_args_reg == EAX); | 2173 ASSERT(instantiator_type_args_reg == EAX); |
2257 ASSERT(instantiator_type_args_reg == result_reg); | 2174 ASSERT(instantiator_type_args_reg == result_reg); |
2258 | 2175 |
2259 // 'instantiator_type_args_reg' is a TypeArguments object (or null). | 2176 // 'instantiator_type_args_reg' is a TypeArguments object (or null). |
2260 // 'function_type_args_reg' is a TypeArguments object (or null). | 2177 // 'function_type_args_reg' is a TypeArguments object (or null). |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2309 __ pushl(instantiator_type_args_reg); // Push instantiator type arguments. | 2226 __ pushl(instantiator_type_args_reg); // Push instantiator type arguments. |
2310 __ pushl(function_type_args_reg); // Push function type arguments. | 2227 __ pushl(function_type_args_reg); // Push function type arguments. |
2311 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), | 2228 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), |
2312 kInstantiateTypeArgumentsRuntimeEntry, 3, | 2229 kInstantiateTypeArgumentsRuntimeEntry, 3, |
2313 locs()); | 2230 locs()); |
2314 __ Drop(3); // Drop 2 type argument vectors and uninstantiated args. | 2231 __ Drop(3); // Drop 2 type argument vectors and uninstantiated args. |
2315 __ popl(result_reg); // Pop instantiated type arguments. | 2232 __ popl(result_reg); // Pop instantiated type arguments. |
2316 __ Bind(&type_arguments_instantiated); | 2233 __ Bind(&type_arguments_instantiated); |
2317 } | 2234 } |
2318 | 2235 |
2319 | |
2320 LocationSummary* AllocateUninitializedContextInstr::MakeLocationSummary( | 2236 LocationSummary* AllocateUninitializedContextInstr::MakeLocationSummary( |
2321 Zone* zone, | 2237 Zone* zone, |
2322 bool opt) const { | 2238 bool opt) const { |
2323 ASSERT(opt); | 2239 ASSERT(opt); |
2324 const intptr_t kNumInputs = 0; | 2240 const intptr_t kNumInputs = 0; |
2325 const intptr_t kNumTemps = 2; | 2241 const intptr_t kNumTemps = 2; |
2326 LocationSummary* locs = new (zone) LocationSummary( | 2242 LocationSummary* locs = new (zone) LocationSummary( |
2327 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); | 2243 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); |
2328 locs->set_temp(0, Location::RegisterLocation(ECX)); | 2244 locs->set_temp(0, Location::RegisterLocation(ECX)); |
2329 locs->set_temp(1, Location::RegisterLocation(EDI)); | 2245 locs->set_temp(1, Location::RegisterLocation(EDI)); |
2330 locs->set_out(0, Location::RegisterLocation(EAX)); | 2246 locs->set_out(0, Location::RegisterLocation(EAX)); |
2331 return locs; | 2247 return locs; |
2332 } | 2248 } |
2333 | 2249 |
2334 | |
2335 class AllocateContextSlowPath : public SlowPathCode { | 2250 class AllocateContextSlowPath : public SlowPathCode { |
2336 public: | 2251 public: |
2337 explicit AllocateContextSlowPath( | 2252 explicit AllocateContextSlowPath( |
2338 AllocateUninitializedContextInstr* instruction) | 2253 AllocateUninitializedContextInstr* instruction) |
2339 : instruction_(instruction) {} | 2254 : instruction_(instruction) {} |
2340 | 2255 |
2341 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { | 2256 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |
2342 __ Comment("AllocateContextSlowPath"); | 2257 __ Comment("AllocateContextSlowPath"); |
2343 __ Bind(entry_label()); | 2258 __ Bind(entry_label()); |
2344 | 2259 |
(...skipping 11 matching lines...) Expand all Loading... |
2356 RawPcDescriptors::kOther, locs); | 2271 RawPcDescriptors::kOther, locs); |
2357 ASSERT(instruction_->locs()->out(0).reg() == EAX); | 2272 ASSERT(instruction_->locs()->out(0).reg() == EAX); |
2358 compiler->RestoreLiveRegisters(instruction_->locs()); | 2273 compiler->RestoreLiveRegisters(instruction_->locs()); |
2359 __ jmp(exit_label()); | 2274 __ jmp(exit_label()); |
2360 } | 2275 } |
2361 | 2276 |
2362 private: | 2277 private: |
2363 AllocateUninitializedContextInstr* instruction_; | 2278 AllocateUninitializedContextInstr* instruction_; |
2364 }; | 2279 }; |
2365 | 2280 |
2366 | |
2367 void AllocateUninitializedContextInstr::EmitNativeCode( | 2281 void AllocateUninitializedContextInstr::EmitNativeCode( |
2368 FlowGraphCompiler* compiler) { | 2282 FlowGraphCompiler* compiler) { |
2369 ASSERT(compiler->is_optimizing()); | 2283 ASSERT(compiler->is_optimizing()); |
2370 Register temp = locs()->temp(0).reg(); | 2284 Register temp = locs()->temp(0).reg(); |
2371 Register temp2 = locs()->temp(1).reg(); | 2285 Register temp2 = locs()->temp(1).reg(); |
2372 Register result = locs()->out(0).reg(); | 2286 Register result = locs()->out(0).reg(); |
2373 // Try allocate the object. | 2287 // Try allocate the object. |
2374 AllocateContextSlowPath* slow_path = new AllocateContextSlowPath(this); | 2288 AllocateContextSlowPath* slow_path = new AllocateContextSlowPath(this); |
2375 compiler->AddSlowPathCode(slow_path); | 2289 compiler->AddSlowPathCode(slow_path); |
2376 intptr_t instance_size = Context::InstanceSize(num_context_variables()); | 2290 intptr_t instance_size = Context::InstanceSize(num_context_variables()); |
2377 | 2291 |
2378 __ TryAllocateArray(kContextCid, instance_size, slow_path->entry_label(), | 2292 __ TryAllocateArray(kContextCid, instance_size, slow_path->entry_label(), |
2379 Assembler::kFarJump, | 2293 Assembler::kFarJump, |
2380 result, // instance | 2294 result, // instance |
2381 temp, // end address | 2295 temp, // end address |
2382 temp2); // temp | 2296 temp2); // temp |
2383 | 2297 |
2384 // Setup up number of context variables field. | 2298 // Setup up number of context variables field. |
2385 __ movl(FieldAddress(result, Context::num_variables_offset()), | 2299 __ movl(FieldAddress(result, Context::num_variables_offset()), |
2386 Immediate(num_context_variables())); | 2300 Immediate(num_context_variables())); |
2387 | 2301 |
2388 __ Bind(slow_path->exit_label()); | 2302 __ Bind(slow_path->exit_label()); |
2389 } | 2303 } |
2390 | 2304 |
2391 | |
2392 LocationSummary* AllocateContextInstr::MakeLocationSummary(Zone* zone, | 2305 LocationSummary* AllocateContextInstr::MakeLocationSummary(Zone* zone, |
2393 bool opt) const { | 2306 bool opt) const { |
2394 const intptr_t kNumInputs = 0; | 2307 const intptr_t kNumInputs = 0; |
2395 const intptr_t kNumTemps = 1; | 2308 const intptr_t kNumTemps = 1; |
2396 LocationSummary* locs = new (zone) | 2309 LocationSummary* locs = new (zone) |
2397 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 2310 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
2398 locs->set_temp(0, Location::RegisterLocation(EDX)); | 2311 locs->set_temp(0, Location::RegisterLocation(EDX)); |
2399 locs->set_out(0, Location::RegisterLocation(EAX)); | 2312 locs->set_out(0, Location::RegisterLocation(EAX)); |
2400 return locs; | 2313 return locs; |
2401 } | 2314 } |
2402 | 2315 |
2403 | |
2404 void AllocateContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2316 void AllocateContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
2405 ASSERT(locs()->temp(0).reg() == EDX); | 2317 ASSERT(locs()->temp(0).reg() == EDX); |
2406 ASSERT(locs()->out(0).reg() == EAX); | 2318 ASSERT(locs()->out(0).reg() == EAX); |
2407 | 2319 |
2408 __ movl(EDX, Immediate(num_context_variables())); | 2320 __ movl(EDX, Immediate(num_context_variables())); |
2409 compiler->GenerateCall(token_pos(), *StubCode::AllocateContext_entry(), | 2321 compiler->GenerateCall(token_pos(), *StubCode::AllocateContext_entry(), |
2410 RawPcDescriptors::kOther, locs()); | 2322 RawPcDescriptors::kOther, locs()); |
2411 } | 2323 } |
2412 | 2324 |
2413 | |
2414 LocationSummary* InitStaticFieldInstr::MakeLocationSummary(Zone* zone, | 2325 LocationSummary* InitStaticFieldInstr::MakeLocationSummary(Zone* zone, |
2415 bool opt) const { | 2326 bool opt) const { |
2416 const intptr_t kNumInputs = 1; | 2327 const intptr_t kNumInputs = 1; |
2417 const intptr_t kNumTemps = 1; | 2328 const intptr_t kNumTemps = 1; |
2418 LocationSummary* locs = new (zone) | 2329 LocationSummary* locs = new (zone) |
2419 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 2330 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
2420 locs->set_in(0, Location::RegisterLocation(EAX)); | 2331 locs->set_in(0, Location::RegisterLocation(EAX)); |
2421 locs->set_temp(0, Location::RegisterLocation(ECX)); | 2332 locs->set_temp(0, Location::RegisterLocation(ECX)); |
2422 return locs; | 2333 return locs; |
2423 } | 2334 } |
2424 | 2335 |
2425 | |
2426 void InitStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2336 void InitStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
2427 Register field = locs()->in(0).reg(); | 2337 Register field = locs()->in(0).reg(); |
2428 Register temp = locs()->temp(0).reg(); | 2338 Register temp = locs()->temp(0).reg(); |
2429 | 2339 |
2430 Label call_runtime, no_call; | 2340 Label call_runtime, no_call; |
2431 | 2341 |
2432 __ movl(temp, FieldAddress(field, Field::static_value_offset())); | 2342 __ movl(temp, FieldAddress(field, Field::static_value_offset())); |
2433 __ CompareObject(temp, Object::sentinel()); | 2343 __ CompareObject(temp, Object::sentinel()); |
2434 __ j(EQUAL, &call_runtime); | 2344 __ j(EQUAL, &call_runtime); |
2435 | 2345 |
2436 __ CompareObject(temp, Object::transition_sentinel()); | 2346 __ CompareObject(temp, Object::transition_sentinel()); |
2437 __ j(NOT_EQUAL, &no_call); | 2347 __ j(NOT_EQUAL, &no_call); |
2438 | 2348 |
2439 __ Bind(&call_runtime); | 2349 __ Bind(&call_runtime); |
2440 __ PushObject(Object::null_object()); // Make room for (unused) result. | 2350 __ PushObject(Object::null_object()); // Make room for (unused) result. |
2441 __ pushl(field); | 2351 __ pushl(field); |
2442 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), | 2352 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), |
2443 kInitStaticFieldRuntimeEntry, 1, locs()); | 2353 kInitStaticFieldRuntimeEntry, 1, locs()); |
2444 __ Drop(2); // Remove argument and unused result. | 2354 __ Drop(2); // Remove argument and unused result. |
2445 __ Bind(&no_call); | 2355 __ Bind(&no_call); |
2446 } | 2356 } |
2447 | 2357 |
2448 | |
2449 LocationSummary* CloneContextInstr::MakeLocationSummary(Zone* zone, | 2358 LocationSummary* CloneContextInstr::MakeLocationSummary(Zone* zone, |
2450 bool opt) const { | 2359 bool opt) const { |
2451 const intptr_t kNumInputs = 1; | 2360 const intptr_t kNumInputs = 1; |
2452 const intptr_t kNumTemps = 0; | 2361 const intptr_t kNumTemps = 0; |
2453 LocationSummary* locs = new (zone) | 2362 LocationSummary* locs = new (zone) |
2454 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 2363 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
2455 locs->set_in(0, Location::RegisterLocation(EAX)); | 2364 locs->set_in(0, Location::RegisterLocation(EAX)); |
2456 locs->set_out(0, Location::RegisterLocation(EAX)); | 2365 locs->set_out(0, Location::RegisterLocation(EAX)); |
2457 return locs; | 2366 return locs; |
2458 } | 2367 } |
2459 | 2368 |
2460 | |
2461 void CloneContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2369 void CloneContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
2462 Register context_value = locs()->in(0).reg(); | 2370 Register context_value = locs()->in(0).reg(); |
2463 Register result = locs()->out(0).reg(); | 2371 Register result = locs()->out(0).reg(); |
2464 | 2372 |
2465 __ PushObject(Object::null_object()); // Make room for the result. | 2373 __ PushObject(Object::null_object()); // Make room for the result. |
2466 __ pushl(context_value); | 2374 __ pushl(context_value); |
2467 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), | 2375 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), |
2468 kCloneContextRuntimeEntry, 1, locs()); | 2376 kCloneContextRuntimeEntry, 1, locs()); |
2469 __ popl(result); // Remove argument. | 2377 __ popl(result); // Remove argument. |
2470 __ popl(result); // Get result (cloned context). | 2378 __ popl(result); // Get result (cloned context). |
2471 } | 2379 } |
2472 | 2380 |
2473 | |
2474 LocationSummary* CatchBlockEntryInstr::MakeLocationSummary(Zone* zone, | 2381 LocationSummary* CatchBlockEntryInstr::MakeLocationSummary(Zone* zone, |
2475 bool opt) const { | 2382 bool opt) const { |
2476 UNREACHABLE(); | 2383 UNREACHABLE(); |
2477 return NULL; | 2384 return NULL; |
2478 } | 2385 } |
2479 | 2386 |
2480 | |
2481 void CatchBlockEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2387 void CatchBlockEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
2482 __ Bind(compiler->GetJumpLabel(this)); | 2388 __ Bind(compiler->GetJumpLabel(this)); |
2483 compiler->AddExceptionHandler(catch_try_index(), try_index(), | 2389 compiler->AddExceptionHandler(catch_try_index(), try_index(), |
2484 compiler->assembler()->CodeSize(), | 2390 compiler->assembler()->CodeSize(), |
2485 handler_token_pos(), is_generated(), | 2391 handler_token_pos(), is_generated(), |
2486 catch_handler_types_, needs_stacktrace()); | 2392 catch_handler_types_, needs_stacktrace()); |
2487 // On lazy deoptimization we patch the optimized code here to enter the | 2393 // On lazy deoptimization we patch the optimized code here to enter the |
2488 // deoptimization stub. | 2394 // deoptimization stub. |
2489 const intptr_t deopt_id = Thread::ToDeoptAfter(GetDeoptId()); | 2395 const intptr_t deopt_id = Thread::ToDeoptAfter(GetDeoptId()); |
2490 if (compiler->is_optimizing()) { | 2396 if (compiler->is_optimizing()) { |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2545 } else { | 2451 } else { |
2546 // Restore stack and initialize the two exception variables: | 2452 // Restore stack and initialize the two exception variables: |
2547 // exception and stack trace variables. | 2453 // exception and stack trace variables. |
2548 __ movl(Address(EBP, exception_var().index() * kWordSize), | 2454 __ movl(Address(EBP, exception_var().index() * kWordSize), |
2549 kExceptionObjectReg); | 2455 kExceptionObjectReg); |
2550 __ movl(Address(EBP, stacktrace_var().index() * kWordSize), | 2456 __ movl(Address(EBP, stacktrace_var().index() * kWordSize), |
2551 kStackTraceObjectReg); | 2457 kStackTraceObjectReg); |
2552 } | 2458 } |
2553 } | 2459 } |
2554 | 2460 |
2555 | |
2556 LocationSummary* CheckStackOverflowInstr::MakeLocationSummary(Zone* zone, | 2461 LocationSummary* CheckStackOverflowInstr::MakeLocationSummary(Zone* zone, |
2557 bool opt) const { | 2462 bool opt) const { |
2558 const intptr_t kNumInputs = 0; | 2463 const intptr_t kNumInputs = 0; |
2559 const intptr_t kNumTemps = opt ? 0 : 1; | 2464 const intptr_t kNumTemps = opt ? 0 : 1; |
2560 LocationSummary* summary = new (zone) LocationSummary( | 2465 LocationSummary* summary = new (zone) LocationSummary( |
2561 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); | 2466 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); |
2562 if (!opt) { | 2467 if (!opt) { |
2563 summary->set_temp(0, Location::RequiresRegister()); | 2468 summary->set_temp(0, Location::RequiresRegister()); |
2564 } | 2469 } |
2565 return summary; | 2470 return summary; |
2566 } | 2471 } |
2567 | 2472 |
2568 | |
2569 class CheckStackOverflowSlowPath : public SlowPathCode { | 2473 class CheckStackOverflowSlowPath : public SlowPathCode { |
2570 public: | 2474 public: |
2571 explicit CheckStackOverflowSlowPath(CheckStackOverflowInstr* instruction) | 2475 explicit CheckStackOverflowSlowPath(CheckStackOverflowInstr* instruction) |
2572 : instruction_(instruction) {} | 2476 : instruction_(instruction) {} |
2573 | 2477 |
2574 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { | 2478 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |
2575 if (compiler->isolate()->use_osr() && osr_entry_label()->IsLinked()) { | 2479 if (compiler->isolate()->use_osr() && osr_entry_label()->IsLinked()) { |
2576 __ Comment("CheckStackOverflowSlowPathOsr"); | 2480 __ Comment("CheckStackOverflowSlowPathOsr"); |
2577 __ Bind(osr_entry_label()); | 2481 __ Bind(osr_entry_label()); |
2578 __ movl(Address(THR, Thread::stack_overflow_flags_offset()), | 2482 __ movl(Address(THR, Thread::stack_overflow_flags_offset()), |
(...skipping 26 matching lines...) Expand all Loading... |
2605 Label* osr_entry_label() { | 2509 Label* osr_entry_label() { |
2606 ASSERT(Isolate::Current()->use_osr()); | 2510 ASSERT(Isolate::Current()->use_osr()); |
2607 return &osr_entry_label_; | 2511 return &osr_entry_label_; |
2608 } | 2512 } |
2609 | 2513 |
2610 private: | 2514 private: |
2611 CheckStackOverflowInstr* instruction_; | 2515 CheckStackOverflowInstr* instruction_; |
2612 Label osr_entry_label_; | 2516 Label osr_entry_label_; |
2613 }; | 2517 }; |
2614 | 2518 |
2615 | |
2616 void CheckStackOverflowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2519 void CheckStackOverflowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
2617 CheckStackOverflowSlowPath* slow_path = new CheckStackOverflowSlowPath(this); | 2520 CheckStackOverflowSlowPath* slow_path = new CheckStackOverflowSlowPath(this); |
2618 compiler->AddSlowPathCode(slow_path); | 2521 compiler->AddSlowPathCode(slow_path); |
2619 | 2522 |
2620 __ cmpl(ESP, Address(THR, Thread::stack_limit_offset())); | 2523 __ cmpl(ESP, Address(THR, Thread::stack_limit_offset())); |
2621 __ j(BELOW_EQUAL, slow_path->entry_label()); | 2524 __ j(BELOW_EQUAL, slow_path->entry_label()); |
2622 if (compiler->CanOSRFunction() && in_loop()) { | 2525 if (compiler->CanOSRFunction() && in_loop()) { |
2623 // In unoptimized code check the usage counter to trigger OSR at loop | 2526 // In unoptimized code check the usage counter to trigger OSR at loop |
2624 // stack checks. Use progressively higher thresholds for more deeply | 2527 // stack checks. Use progressively higher thresholds for more deeply |
2625 // nested loops to attempt to hit outer loops with OSR when possible. | 2528 // nested loops to attempt to hit outer loops with OSR when possible. |
2626 __ LoadObject(EDI, compiler->parsed_function().function()); | 2529 __ LoadObject(EDI, compiler->parsed_function().function()); |
2627 intptr_t threshold = | 2530 intptr_t threshold = |
2628 FLAG_optimization_counter_threshold * (loop_depth() + 1); | 2531 FLAG_optimization_counter_threshold * (loop_depth() + 1); |
2629 __ cmpl(FieldAddress(EDI, Function::usage_counter_offset()), | 2532 __ cmpl(FieldAddress(EDI, Function::usage_counter_offset()), |
2630 Immediate(threshold)); | 2533 Immediate(threshold)); |
2631 __ j(GREATER_EQUAL, slow_path->osr_entry_label()); | 2534 __ j(GREATER_EQUAL, slow_path->osr_entry_label()); |
2632 } | 2535 } |
2633 if (compiler->ForceSlowPathForStackOverflow()) { | 2536 if (compiler->ForceSlowPathForStackOverflow()) { |
2634 // TODO(turnidge): Implement stack overflow count in assembly to | 2537 // TODO(turnidge): Implement stack overflow count in assembly to |
2635 // make --stacktrace-every and --deoptimize-every faster. | 2538 // make --stacktrace-every and --deoptimize-every faster. |
2636 __ jmp(slow_path->entry_label()); | 2539 __ jmp(slow_path->entry_label()); |
2637 } | 2540 } |
2638 __ Bind(slow_path->exit_label()); | 2541 __ Bind(slow_path->exit_label()); |
2639 } | 2542 } |
2640 | 2543 |
2641 | |
2642 static void EmitSmiShiftLeft(FlowGraphCompiler* compiler, | 2544 static void EmitSmiShiftLeft(FlowGraphCompiler* compiler, |
2643 BinarySmiOpInstr* shift_left) { | 2545 BinarySmiOpInstr* shift_left) { |
2644 const LocationSummary& locs = *shift_left->locs(); | 2546 const LocationSummary& locs = *shift_left->locs(); |
2645 Register left = locs.in(0).reg(); | 2547 Register left = locs.in(0).reg(); |
2646 Register result = locs.out(0).reg(); | 2548 Register result = locs.out(0).reg(); |
2647 ASSERT(left == result); | 2549 ASSERT(left == result); |
2648 Label* deopt = shift_left->CanDeoptimize() | 2550 Label* deopt = shift_left->CanDeoptimize() |
2649 ? compiler->AddDeoptStub(shift_left->deopt_id(), | 2551 ? compiler->AddDeoptStub(shift_left->deopt_id(), |
2650 ICData::kDeoptBinarySmiOp) | 2552 ICData::kDeoptBinarySmiOp) |
2651 : NULL; | 2553 : NULL; |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2743 // Overflow test (preserve temp and right); | 2645 // Overflow test (preserve temp and right); |
2744 __ shll(left, right); | 2646 __ shll(left, right); |
2745 __ sarl(left, right); | 2647 __ sarl(left, right); |
2746 __ cmpl(left, temp); | 2648 __ cmpl(left, temp); |
2747 __ j(NOT_EQUAL, deopt); // Overflow. | 2649 __ j(NOT_EQUAL, deopt); // Overflow. |
2748 // Shift for result now we know there is no overflow. | 2650 // Shift for result now we know there is no overflow. |
2749 __ shll(left, right); | 2651 __ shll(left, right); |
2750 } | 2652 } |
2751 } | 2653 } |
2752 | 2654 |
2753 | |
2754 LocationSummary* CheckedSmiOpInstr::MakeLocationSummary(Zone* zone, | 2655 LocationSummary* CheckedSmiOpInstr::MakeLocationSummary(Zone* zone, |
2755 bool opt) const { | 2656 bool opt) const { |
2756 // Only for precompiled code, not on ia32 currently. | 2657 // Only for precompiled code, not on ia32 currently. |
2757 UNIMPLEMENTED(); | 2658 UNIMPLEMENTED(); |
2758 return NULL; | 2659 return NULL; |
2759 } | 2660 } |
2760 | 2661 |
2761 | |
2762 void CheckedSmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2662 void CheckedSmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
2763 // Only for precompiled code, not on ia32 currently. | 2663 // Only for precompiled code, not on ia32 currently. |
2764 UNIMPLEMENTED(); | 2664 UNIMPLEMENTED(); |
2765 } | 2665 } |
2766 | 2666 |
2767 | |
2768 LocationSummary* CheckedSmiComparisonInstr::MakeLocationSummary( | 2667 LocationSummary* CheckedSmiComparisonInstr::MakeLocationSummary( |
2769 Zone* zone, | 2668 Zone* zone, |
2770 bool opt) const { | 2669 bool opt) const { |
2771 // Only for precompiled code, not on ia32 currently. | 2670 // Only for precompiled code, not on ia32 currently. |
2772 UNIMPLEMENTED(); | 2671 UNIMPLEMENTED(); |
2773 return NULL; | 2672 return NULL; |
2774 } | 2673 } |
2775 | 2674 |
2776 | |
2777 Condition CheckedSmiComparisonInstr::EmitComparisonCode( | 2675 Condition CheckedSmiComparisonInstr::EmitComparisonCode( |
2778 FlowGraphCompiler* compiler, | 2676 FlowGraphCompiler* compiler, |
2779 BranchLabels labels) { | 2677 BranchLabels labels) { |
2780 // Only for precompiled code, not on ia32 currently. | 2678 // Only for precompiled code, not on ia32 currently. |
2781 UNIMPLEMENTED(); | 2679 UNIMPLEMENTED(); |
2782 return ZERO; | 2680 return ZERO; |
2783 } | 2681 } |
2784 | 2682 |
2785 | |
2786 void CheckedSmiComparisonInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 2683 void CheckedSmiComparisonInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
2787 BranchInstr* instr) { | 2684 BranchInstr* instr) { |
2788 // Only for precompiled code, not on ia32 currently. | 2685 // Only for precompiled code, not on ia32 currently. |
2789 UNIMPLEMENTED(); | 2686 UNIMPLEMENTED(); |
2790 } | 2687 } |
2791 | 2688 |
2792 | |
2793 void CheckedSmiComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2689 void CheckedSmiComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
2794 // Only for precompiled code, not on ia32 currently. | 2690 // Only for precompiled code, not on ia32 currently. |
2795 UNIMPLEMENTED(); | 2691 UNIMPLEMENTED(); |
2796 } | 2692 } |
2797 | 2693 |
2798 | |
2799 static bool IsSmiValue(const Object& constant, intptr_t value) { | 2694 static bool IsSmiValue(const Object& constant, intptr_t value) { |
2800 return constant.IsSmi() && (Smi::Cast(constant).Value() == value); | 2695 return constant.IsSmi() && (Smi::Cast(constant).Value() == value); |
2801 } | 2696 } |
2802 | 2697 |
2803 | |
2804 LocationSummary* BinarySmiOpInstr::MakeLocationSummary(Zone* zone, | 2698 LocationSummary* BinarySmiOpInstr::MakeLocationSummary(Zone* zone, |
2805 bool opt) const { | 2699 bool opt) const { |
2806 const intptr_t kNumInputs = 2; | 2700 const intptr_t kNumInputs = 2; |
2807 if (op_kind() == Token::kTRUNCDIV) { | 2701 if (op_kind() == Token::kTRUNCDIV) { |
2808 const intptr_t kNumTemps = 1; | 2702 const intptr_t kNumTemps = 1; |
2809 LocationSummary* summary = new (zone) | 2703 LocationSummary* summary = new (zone) |
2810 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 2704 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
2811 if (RightIsPowerOfTwoConstant()) { | 2705 if (RightIsPowerOfTwoConstant()) { |
2812 summary->set_in(0, Location::RequiresRegister()); | 2706 summary->set_in(0, Location::RequiresRegister()); |
2813 ConstantInstr* right_constant = right()->definition()->AsConstant(); | 2707 ConstantInstr* right_constant = right()->definition()->AsConstant(); |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2867 if (constant != NULL) { | 2761 if (constant != NULL) { |
2868 summary->set_in(1, Location::RegisterOrSmiConstant(right())); | 2762 summary->set_in(1, Location::RegisterOrSmiConstant(right())); |
2869 } else { | 2763 } else { |
2870 summary->set_in(1, Location::PrefersRegister()); | 2764 summary->set_in(1, Location::PrefersRegister()); |
2871 } | 2765 } |
2872 summary->set_out(0, Location::SameAsFirstInput()); | 2766 summary->set_out(0, Location::SameAsFirstInput()); |
2873 return summary; | 2767 return summary; |
2874 } | 2768 } |
2875 } | 2769 } |
2876 | 2770 |
2877 | |
2878 template <typename OperandType> | 2771 template <typename OperandType> |
2879 static void EmitIntegerArithmetic(FlowGraphCompiler* compiler, | 2772 static void EmitIntegerArithmetic(FlowGraphCompiler* compiler, |
2880 Token::Kind op_kind, | 2773 Token::Kind op_kind, |
2881 Register left, | 2774 Register left, |
2882 const OperandType& right, | 2775 const OperandType& right, |
2883 Label* deopt) { | 2776 Label* deopt) { |
2884 switch (op_kind) { | 2777 switch (op_kind) { |
2885 case Token::kADD: | 2778 case Token::kADD: |
2886 __ addl(left, right); | 2779 __ addl(left, right); |
2887 break; | 2780 break; |
(...skipping 11 matching lines...) Expand all Loading... |
2899 break; | 2792 break; |
2900 case Token::kMUL: | 2793 case Token::kMUL: |
2901 __ imull(left, right); | 2794 __ imull(left, right); |
2902 break; | 2795 break; |
2903 default: | 2796 default: |
2904 UNREACHABLE(); | 2797 UNREACHABLE(); |
2905 } | 2798 } |
2906 if (deopt != NULL) __ j(OVERFLOW, deopt); | 2799 if (deopt != NULL) __ j(OVERFLOW, deopt); |
2907 } | 2800 } |
2908 | 2801 |
2909 | |
2910 void BinarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2802 void BinarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
2911 if (op_kind() == Token::kSHL) { | 2803 if (op_kind() == Token::kSHL) { |
2912 EmitSmiShiftLeft(compiler, this); | 2804 EmitSmiShiftLeft(compiler, this); |
2913 return; | 2805 return; |
2914 } | 2806 } |
2915 | 2807 |
2916 Register left = locs()->in(0).reg(); | 2808 Register left = locs()->in(0).reg(); |
2917 Register result = locs()->out(0).reg(); | 2809 Register result = locs()->out(0).reg(); |
2918 ASSERT(left == result); | 2810 ASSERT(left == result); |
2919 Label* deopt = NULL; | 2811 Label* deopt = NULL; |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2991 case Token::kBIT_AND: | 2883 case Token::kBIT_AND: |
2992 case Token::kBIT_OR: | 2884 case Token::kBIT_OR: |
2993 case Token::kBIT_XOR: | 2885 case Token::kBIT_XOR: |
2994 case Token::kMUL: | 2886 case Token::kMUL: |
2995 if (op_kind() == Token::kMUL) { | 2887 if (op_kind() == Token::kMUL) { |
2996 __ SmiUntag(left); | 2888 __ SmiUntag(left); |
2997 } | 2889 } |
2998 EmitIntegerArithmetic(compiler, op_kind(), left, right, deopt); | 2890 EmitIntegerArithmetic(compiler, op_kind(), left, right, deopt); |
2999 break; | 2891 break; |
3000 | 2892 |
3001 | |
3002 case Token::kTRUNCDIV: { | 2893 case Token::kTRUNCDIV: { |
3003 if (RangeUtils::CanBeZero(right_range())) { | 2894 if (RangeUtils::CanBeZero(right_range())) { |
3004 // Handle divide by zero in runtime. | 2895 // Handle divide by zero in runtime. |
3005 __ testl(right, right); | 2896 __ testl(right, right); |
3006 __ j(ZERO, deopt); | 2897 __ j(ZERO, deopt); |
3007 } | 2898 } |
3008 ASSERT(left == EAX); | 2899 ASSERT(left == EAX); |
3009 ASSERT((right != EDX) && (right != EAX)); | 2900 ASSERT((right != EDX) && (right != EAX)); |
3010 ASSERT(locs()->temp(0).reg() == EDX); | 2901 ASSERT(locs()->temp(0).reg() == EDX); |
3011 ASSERT(result == EAX); | 2902 ASSERT(result == EAX); |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3100 // behavior (short-circuit evaluation). | 2991 // behavior (short-circuit evaluation). |
3101 UNREACHABLE(); | 2992 UNREACHABLE(); |
3102 break; | 2993 break; |
3103 } | 2994 } |
3104 default: | 2995 default: |
3105 UNREACHABLE(); | 2996 UNREACHABLE(); |
3106 break; | 2997 break; |
3107 } | 2998 } |
3108 } | 2999 } |
3109 | 3000 |
3110 | |
3111 LocationSummary* BinaryInt32OpInstr::MakeLocationSummary(Zone* zone, | 3001 LocationSummary* BinaryInt32OpInstr::MakeLocationSummary(Zone* zone, |
3112 bool opt) const { | 3002 bool opt) const { |
3113 const intptr_t kNumInputs = 2; | 3003 const intptr_t kNumInputs = 2; |
3114 if (op_kind() == Token::kTRUNCDIV) { | 3004 if (op_kind() == Token::kTRUNCDIV) { |
3115 UNREACHABLE(); | 3005 UNREACHABLE(); |
3116 return NULL; | 3006 return NULL; |
3117 } else if (op_kind() == Token::kMOD) { | 3007 } else if (op_kind() == Token::kMOD) { |
3118 UNREACHABLE(); | 3008 UNREACHABLE(); |
3119 return NULL; | 3009 return NULL; |
3120 } else if (op_kind() == Token::kSHR) { | 3010 } else if (op_kind() == Token::kSHR) { |
(...skipping 24 matching lines...) Expand all Loading... |
3145 if (constant != NULL) { | 3035 if (constant != NULL) { |
3146 summary->set_in(1, Location::RegisterOrSmiConstant(right())); | 3036 summary->set_in(1, Location::RegisterOrSmiConstant(right())); |
3147 } else { | 3037 } else { |
3148 summary->set_in(1, Location::PrefersRegister()); | 3038 summary->set_in(1, Location::PrefersRegister()); |
3149 } | 3039 } |
3150 summary->set_out(0, Location::SameAsFirstInput()); | 3040 summary->set_out(0, Location::SameAsFirstInput()); |
3151 return summary; | 3041 return summary; |
3152 } | 3042 } |
3153 } | 3043 } |
3154 | 3044 |
3155 | |
3156 static void EmitInt32ShiftLeft(FlowGraphCompiler* compiler, | 3045 static void EmitInt32ShiftLeft(FlowGraphCompiler* compiler, |
3157 BinaryInt32OpInstr* shift_left) { | 3046 BinaryInt32OpInstr* shift_left) { |
3158 const LocationSummary& locs = *shift_left->locs(); | 3047 const LocationSummary& locs = *shift_left->locs(); |
3159 Register left = locs.in(0).reg(); | 3048 Register left = locs.in(0).reg(); |
3160 Register result = locs.out(0).reg(); | 3049 Register result = locs.out(0).reg(); |
3161 ASSERT(left == result); | 3050 ASSERT(left == result); |
3162 Label* deopt = shift_left->CanDeoptimize() | 3051 Label* deopt = shift_left->CanDeoptimize() |
3163 ? compiler->AddDeoptStub(shift_left->deopt_id(), | 3052 ? compiler->AddDeoptStub(shift_left->deopt_id(), |
3164 ICData::kDeoptBinarySmiOp) | 3053 ICData::kDeoptBinarySmiOp) |
3165 : NULL; | 3054 : NULL; |
(...skipping 11 matching lines...) Expand all Loading... |
3177 __ movl(temp, left); | 3066 __ movl(temp, left); |
3178 __ shll(left, Immediate(value)); | 3067 __ shll(left, Immediate(value)); |
3179 __ sarl(left, Immediate(value)); | 3068 __ sarl(left, Immediate(value)); |
3180 __ cmpl(left, temp); | 3069 __ cmpl(left, temp); |
3181 __ j(NOT_EQUAL, deopt); // Overflow. | 3070 __ j(NOT_EQUAL, deopt); // Overflow. |
3182 } | 3071 } |
3183 // Shift for result now we know there is no overflow. | 3072 // Shift for result now we know there is no overflow. |
3184 __ shll(left, Immediate(value)); | 3073 __ shll(left, Immediate(value)); |
3185 } | 3074 } |
3186 | 3075 |
3187 | |
3188 void BinaryInt32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3076 void BinaryInt32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
3189 if (op_kind() == Token::kSHL) { | 3077 if (op_kind() == Token::kSHL) { |
3190 EmitInt32ShiftLeft(compiler, this); | 3078 EmitInt32ShiftLeft(compiler, this); |
3191 return; | 3079 return; |
3192 } | 3080 } |
3193 | 3081 |
3194 Register left = locs()->in(0).reg(); | 3082 Register left = locs()->in(0).reg(); |
3195 Register result = locs()->out(0).reg(); | 3083 Register result = locs()->out(0).reg(); |
3196 ASSERT(left == result); | 3084 ASSERT(left == result); |
3197 Label* deopt = NULL; | 3085 Label* deopt = NULL; |
3198 if (CanDeoptimize()) { | 3086 if (CanDeoptimize()) { |
3199 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinarySmiOp); | 3087 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinarySmiOp); |
3200 } | 3088 } |
3201 | 3089 |
3202 if (locs()->in(1).IsConstant()) { | 3090 if (locs()->in(1).IsConstant()) { |
3203 const Object& constant = locs()->in(1).constant(); | 3091 const Object& constant = locs()->in(1).constant(); |
3204 ASSERT(constant.IsSmi()); | 3092 ASSERT(constant.IsSmi()); |
3205 const intptr_t value = Smi::Cast(constant).Value(); | 3093 const intptr_t value = Smi::Cast(constant).Value(); |
3206 switch (op_kind()) { | 3094 switch (op_kind()) { |
3207 case Token::kADD: | 3095 case Token::kADD: |
3208 case Token::kSUB: | 3096 case Token::kSUB: |
3209 case Token::kMUL: | 3097 case Token::kMUL: |
3210 case Token::kBIT_AND: | 3098 case Token::kBIT_AND: |
3211 case Token::kBIT_OR: | 3099 case Token::kBIT_OR: |
3212 case Token::kBIT_XOR: | 3100 case Token::kBIT_XOR: |
3213 EmitIntegerArithmetic(compiler, op_kind(), left, Immediate(value), | 3101 EmitIntegerArithmetic(compiler, op_kind(), left, Immediate(value), |
3214 deopt); | 3102 deopt); |
3215 break; | 3103 break; |
3216 | 3104 |
3217 | |
3218 case Token::kTRUNCDIV: { | 3105 case Token::kTRUNCDIV: { |
3219 UNREACHABLE(); | 3106 UNREACHABLE(); |
3220 break; | 3107 break; |
3221 } | 3108 } |
3222 | 3109 |
3223 case Token::kSHR: { | 3110 case Token::kSHR: { |
3224 // sarl operation masks the count to 5 bits. | 3111 // sarl operation masks the count to 5 bits. |
3225 const intptr_t kCountLimit = 0x1F; | 3112 const intptr_t kCountLimit = 0x1F; |
3226 __ sarl(left, Immediate(Utils::Minimum(value, kCountLimit))); | 3113 __ sarl(left, Immediate(Utils::Minimum(value, kCountLimit))); |
3227 break; | 3114 break; |
(...skipping 23 matching lines...) Expand all Loading... |
3251 case Token::kBIT_XOR: | 3138 case Token::kBIT_XOR: |
3252 EmitIntegerArithmetic(compiler, op_kind(), left, right, deopt); | 3139 EmitIntegerArithmetic(compiler, op_kind(), left, right, deopt); |
3253 break; | 3140 break; |
3254 | 3141 |
3255 default: | 3142 default: |
3256 UNREACHABLE(); | 3143 UNREACHABLE(); |
3257 break; | 3144 break; |
3258 } | 3145 } |
3259 } | 3146 } |
3260 | 3147 |
3261 | |
3262 LocationSummary* BinaryUint32OpInstr::MakeLocationSummary(Zone* zone, | 3148 LocationSummary* BinaryUint32OpInstr::MakeLocationSummary(Zone* zone, |
3263 bool opt) const { | 3149 bool opt) const { |
3264 const intptr_t kNumInputs = 2; | 3150 const intptr_t kNumInputs = 2; |
3265 const intptr_t kNumTemps = (op_kind() == Token::kMUL) ? 1 : 0; | 3151 const intptr_t kNumTemps = (op_kind() == Token::kMUL) ? 1 : 0; |
3266 LocationSummary* summary = new (zone) | 3152 LocationSummary* summary = new (zone) |
3267 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3153 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
3268 if (op_kind() == Token::kMUL) { | 3154 if (op_kind() == Token::kMUL) { |
3269 summary->set_in(0, Location::RegisterLocation(EAX)); | 3155 summary->set_in(0, Location::RegisterLocation(EAX)); |
3270 summary->set_temp(0, Location::RegisterLocation(EDX)); | 3156 summary->set_temp(0, Location::RegisterLocation(EDX)); |
3271 } else { | 3157 } else { |
3272 summary->set_in(0, Location::RequiresRegister()); | 3158 summary->set_in(0, Location::RequiresRegister()); |
3273 } | 3159 } |
3274 summary->set_in(1, Location::RequiresRegister()); | 3160 summary->set_in(1, Location::RequiresRegister()); |
3275 summary->set_out(0, Location::SameAsFirstInput()); | 3161 summary->set_out(0, Location::SameAsFirstInput()); |
3276 return summary; | 3162 return summary; |
3277 } | 3163 } |
3278 | 3164 |
3279 | |
3280 void BinaryUint32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3165 void BinaryUint32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
3281 Register left = locs()->in(0).reg(); | 3166 Register left = locs()->in(0).reg(); |
3282 Register right = locs()->in(1).reg(); | 3167 Register right = locs()->in(1).reg(); |
3283 Register out = locs()->out(0).reg(); | 3168 Register out = locs()->out(0).reg(); |
3284 ASSERT(out == left); | 3169 ASSERT(out == left); |
3285 switch (op_kind()) { | 3170 switch (op_kind()) { |
3286 case Token::kBIT_AND: | 3171 case Token::kBIT_AND: |
3287 case Token::kBIT_OR: | 3172 case Token::kBIT_OR: |
3288 case Token::kBIT_XOR: | 3173 case Token::kBIT_XOR: |
3289 case Token::kADD: | 3174 case Token::kADD: |
3290 case Token::kSUB: | 3175 case Token::kSUB: |
3291 EmitIntegerArithmetic(compiler, op_kind(), left, right, NULL); | 3176 EmitIntegerArithmetic(compiler, op_kind(), left, right, NULL); |
3292 return; | 3177 return; |
3293 | 3178 |
3294 case Token::kMUL: | 3179 case Token::kMUL: |
3295 __ mull(right); // Result in EDX:EAX. | 3180 __ mull(right); // Result in EDX:EAX. |
3296 ASSERT(out == EAX); | 3181 ASSERT(out == EAX); |
3297 ASSERT(locs()->temp(0).reg() == EDX); | 3182 ASSERT(locs()->temp(0).reg() == EDX); |
3298 break; | 3183 break; |
3299 default: | 3184 default: |
3300 UNREACHABLE(); | 3185 UNREACHABLE(); |
3301 } | 3186 } |
3302 } | 3187 } |
3303 | 3188 |
3304 | |
3305 LocationSummary* CheckEitherNonSmiInstr::MakeLocationSummary(Zone* zone, | 3189 LocationSummary* CheckEitherNonSmiInstr::MakeLocationSummary(Zone* zone, |
3306 bool opt) const { | 3190 bool opt) const { |
3307 intptr_t left_cid = left()->Type()->ToCid(); | 3191 intptr_t left_cid = left()->Type()->ToCid(); |
3308 intptr_t right_cid = right()->Type()->ToCid(); | 3192 intptr_t right_cid = right()->Type()->ToCid(); |
3309 ASSERT((left_cid != kDoubleCid) && (right_cid != kDoubleCid)); | 3193 ASSERT((left_cid != kDoubleCid) && (right_cid != kDoubleCid)); |
3310 const intptr_t kNumInputs = 2; | 3194 const intptr_t kNumInputs = 2; |
3311 const bool need_temp = (left()->definition() != right()->definition()) && | 3195 const bool need_temp = (left()->definition() != right()->definition()) && |
3312 (left_cid != kSmiCid) && (right_cid != kSmiCid); | 3196 (left_cid != kSmiCid) && (right_cid != kSmiCid); |
3313 const intptr_t kNumTemps = need_temp ? 1 : 0; | 3197 const intptr_t kNumTemps = need_temp ? 1 : 0; |
3314 LocationSummary* summary = new (zone) | 3198 LocationSummary* summary = new (zone) |
3315 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3199 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
3316 summary->set_in(0, Location::RequiresRegister()); | 3200 summary->set_in(0, Location::RequiresRegister()); |
3317 summary->set_in(1, Location::RequiresRegister()); | 3201 summary->set_in(1, Location::RequiresRegister()); |
3318 if (need_temp) summary->set_temp(0, Location::RequiresRegister()); | 3202 if (need_temp) summary->set_temp(0, Location::RequiresRegister()); |
3319 return summary; | 3203 return summary; |
3320 } | 3204 } |
3321 | 3205 |
3322 | |
3323 void CheckEitherNonSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3206 void CheckEitherNonSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
3324 Label* deopt = | 3207 Label* deopt = |
3325 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryDoubleOp, | 3208 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryDoubleOp, |
3326 licm_hoisted_ ? ICData::kHoisted : 0); | 3209 licm_hoisted_ ? ICData::kHoisted : 0); |
3327 intptr_t left_cid = left()->Type()->ToCid(); | 3210 intptr_t left_cid = left()->Type()->ToCid(); |
3328 intptr_t right_cid = right()->Type()->ToCid(); | 3211 intptr_t right_cid = right()->Type()->ToCid(); |
3329 Register left = locs()->in(0).reg(); | 3212 Register left = locs()->in(0).reg(); |
3330 Register right = locs()->in(1).reg(); | 3213 Register right = locs()->in(1).reg(); |
3331 if (this->left()->definition() == this->right()->definition()) { | 3214 if (this->left()->definition() == this->right()->definition()) { |
3332 __ testl(left, Immediate(kSmiTagMask)); | 3215 __ testl(left, Immediate(kSmiTagMask)); |
3333 } else if (left_cid == kSmiCid) { | 3216 } else if (left_cid == kSmiCid) { |
3334 __ testl(right, Immediate(kSmiTagMask)); | 3217 __ testl(right, Immediate(kSmiTagMask)); |
3335 } else if (right_cid == kSmiCid) { | 3218 } else if (right_cid == kSmiCid) { |
3336 __ testl(left, Immediate(kSmiTagMask)); | 3219 __ testl(left, Immediate(kSmiTagMask)); |
3337 } else { | 3220 } else { |
3338 Register temp = locs()->temp(0).reg(); | 3221 Register temp = locs()->temp(0).reg(); |
3339 __ movl(temp, left); | 3222 __ movl(temp, left); |
3340 __ orl(temp, right); | 3223 __ orl(temp, right); |
3341 __ testl(temp, Immediate(kSmiTagMask)); | 3224 __ testl(temp, Immediate(kSmiTagMask)); |
3342 } | 3225 } |
3343 __ j(ZERO, deopt); | 3226 __ j(ZERO, deopt); |
3344 } | 3227 } |
3345 | 3228 |
3346 | |
3347 LocationSummary* BoxInstr::MakeLocationSummary(Zone* zone, bool opt) const { | 3229 LocationSummary* BoxInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
3348 const intptr_t kNumInputs = 1; | 3230 const intptr_t kNumInputs = 1; |
3349 const intptr_t kNumTemps = 1; | 3231 const intptr_t kNumTemps = 1; |
3350 LocationSummary* summary = new (zone) LocationSummary( | 3232 LocationSummary* summary = new (zone) LocationSummary( |
3351 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); | 3233 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); |
3352 summary->set_in(0, Location::RequiresFpuRegister()); | 3234 summary->set_in(0, Location::RequiresFpuRegister()); |
3353 summary->set_temp(0, Location::RequiresRegister()); | 3235 summary->set_temp(0, Location::RequiresRegister()); |
3354 summary->set_out(0, Location::RequiresRegister()); | 3236 summary->set_out(0, Location::RequiresRegister()); |
3355 return summary; | 3237 return summary; |
3356 } | 3238 } |
3357 | 3239 |
3358 | |
3359 void BoxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3240 void BoxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
3360 Register out_reg = locs()->out(0).reg(); | 3241 Register out_reg = locs()->out(0).reg(); |
3361 XmmRegister value = locs()->in(0).fpu_reg(); | 3242 XmmRegister value = locs()->in(0).fpu_reg(); |
3362 | 3243 |
3363 BoxAllocationSlowPath::Allocate(compiler, this, | 3244 BoxAllocationSlowPath::Allocate(compiler, this, |
3364 compiler->BoxClassFor(from_representation()), | 3245 compiler->BoxClassFor(from_representation()), |
3365 out_reg, locs()->temp(0).reg()); | 3246 out_reg, locs()->temp(0).reg()); |
3366 | 3247 |
3367 switch (from_representation()) { | 3248 switch (from_representation()) { |
3368 case kUnboxedDouble: | 3249 case kUnboxedDouble: |
3369 __ movsd(FieldAddress(out_reg, ValueOffset()), value); | 3250 __ movsd(FieldAddress(out_reg, ValueOffset()), value); |
3370 break; | 3251 break; |
3371 case kUnboxedFloat32x4: | 3252 case kUnboxedFloat32x4: |
3372 case kUnboxedFloat64x2: | 3253 case kUnboxedFloat64x2: |
3373 case kUnboxedInt32x4: | 3254 case kUnboxedInt32x4: |
3374 __ movups(FieldAddress(out_reg, ValueOffset()), value); | 3255 __ movups(FieldAddress(out_reg, ValueOffset()), value); |
3375 break; | 3256 break; |
3376 default: | 3257 default: |
3377 UNREACHABLE(); | 3258 UNREACHABLE(); |
3378 break; | 3259 break; |
3379 } | 3260 } |
3380 } | 3261 } |
3381 | 3262 |
3382 | |
3383 LocationSummary* UnboxInstr::MakeLocationSummary(Zone* zone, bool opt) const { | 3263 LocationSummary* UnboxInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
3384 const bool needs_temp = | 3264 const bool needs_temp = |
3385 CanDeoptimize() || | 3265 CanDeoptimize() || |
3386 (CanConvertSmi() && (value()->Type()->ToCid() == kSmiCid)); | 3266 (CanConvertSmi() && (value()->Type()->ToCid() == kSmiCid)); |
3387 | 3267 |
3388 const intptr_t kNumInputs = 1; | 3268 const intptr_t kNumInputs = 1; |
3389 const intptr_t kNumTemps = needs_temp ? 1 : 0; | 3269 const intptr_t kNumTemps = needs_temp ? 1 : 0; |
3390 LocationSummary* summary = new (zone) | 3270 LocationSummary* summary = new (zone) |
3391 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3271 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
3392 summary->set_in(0, Location::RequiresRegister()); | 3272 summary->set_in(0, Location::RequiresRegister()); |
3393 if (needs_temp) { | 3273 if (needs_temp) { |
3394 summary->set_temp(0, Location::RequiresRegister()); | 3274 summary->set_temp(0, Location::RequiresRegister()); |
3395 } | 3275 } |
3396 if (representation() == kUnboxedMint) { | 3276 if (representation() == kUnboxedMint) { |
3397 summary->set_out(0, Location::Pair(Location::RegisterLocation(EAX), | 3277 summary->set_out(0, Location::Pair(Location::RegisterLocation(EAX), |
3398 Location::RegisterLocation(EDX))); | 3278 Location::RegisterLocation(EDX))); |
3399 } else { | 3279 } else { |
3400 summary->set_out(0, Location::RequiresFpuRegister()); | 3280 summary->set_out(0, Location::RequiresFpuRegister()); |
3401 } | 3281 } |
3402 return summary; | 3282 return summary; |
3403 } | 3283 } |
3404 | 3284 |
3405 | |
3406 void UnboxInstr::EmitLoadFromBox(FlowGraphCompiler* compiler) { | 3285 void UnboxInstr::EmitLoadFromBox(FlowGraphCompiler* compiler) { |
3407 const Register box = locs()->in(0).reg(); | 3286 const Register box = locs()->in(0).reg(); |
3408 | 3287 |
3409 switch (representation()) { | 3288 switch (representation()) { |
3410 case kUnboxedMint: { | 3289 case kUnboxedMint: { |
3411 PairLocation* result = locs()->out(0).AsPairLocation(); | 3290 PairLocation* result = locs()->out(0).AsPairLocation(); |
3412 __ movl(result->At(0).reg(), FieldAddress(box, ValueOffset())); | 3291 __ movl(result->At(0).reg(), FieldAddress(box, ValueOffset())); |
3413 __ movl(result->At(1).reg(), | 3292 __ movl(result->At(1).reg(), |
3414 FieldAddress(box, ValueOffset() + kWordSize)); | 3293 FieldAddress(box, ValueOffset() + kWordSize)); |
3415 break; | 3294 break; |
(...skipping 12 matching lines...) Expand all Loading... |
3428 __ movups(result, FieldAddress(box, ValueOffset())); | 3307 __ movups(result, FieldAddress(box, ValueOffset())); |
3429 break; | 3308 break; |
3430 } | 3309 } |
3431 | 3310 |
3432 default: | 3311 default: |
3433 UNREACHABLE(); | 3312 UNREACHABLE(); |
3434 break; | 3313 break; |
3435 } | 3314 } |
3436 } | 3315 } |
3437 | 3316 |
3438 | |
3439 void UnboxInstr::EmitSmiConversion(FlowGraphCompiler* compiler) { | 3317 void UnboxInstr::EmitSmiConversion(FlowGraphCompiler* compiler) { |
3440 const Register box = locs()->in(0).reg(); | 3318 const Register box = locs()->in(0).reg(); |
3441 | 3319 |
3442 switch (representation()) { | 3320 switch (representation()) { |
3443 case kUnboxedMint: { | 3321 case kUnboxedMint: { |
3444 PairLocation* result = locs()->out(0).AsPairLocation(); | 3322 PairLocation* result = locs()->out(0).AsPairLocation(); |
3445 ASSERT(result->At(0).reg() == EAX); | 3323 ASSERT(result->At(0).reg() == EAX); |
3446 ASSERT(result->At(1).reg() == EDX); | 3324 ASSERT(result->At(1).reg() == EDX); |
3447 __ movl(EAX, box); | 3325 __ movl(EAX, box); |
3448 __ SmiUntag(EAX); | 3326 __ SmiUntag(EAX); |
3449 __ cdq(); | 3327 __ cdq(); |
3450 break; | 3328 break; |
3451 } | 3329 } |
3452 | 3330 |
3453 case kUnboxedDouble: { | 3331 case kUnboxedDouble: { |
3454 const Register temp = locs()->temp(0).reg(); | 3332 const Register temp = locs()->temp(0).reg(); |
3455 const FpuRegister result = locs()->out(0).fpu_reg(); | 3333 const FpuRegister result = locs()->out(0).fpu_reg(); |
3456 __ movl(temp, box); | 3334 __ movl(temp, box); |
3457 __ SmiUntag(temp); | 3335 __ SmiUntag(temp); |
3458 __ cvtsi2sd(result, temp); | 3336 __ cvtsi2sd(result, temp); |
3459 break; | 3337 break; |
3460 } | 3338 } |
3461 | 3339 |
3462 default: | 3340 default: |
3463 UNREACHABLE(); | 3341 UNREACHABLE(); |
3464 break; | 3342 break; |
3465 } | 3343 } |
3466 } | 3344 } |
3467 | 3345 |
3468 | |
3469 void UnboxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3346 void UnboxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
3470 const intptr_t value_cid = value()->Type()->ToCid(); | 3347 const intptr_t value_cid = value()->Type()->ToCid(); |
3471 const intptr_t box_cid = BoxCid(); | 3348 const intptr_t box_cid = BoxCid(); |
3472 | 3349 |
3473 if (value_cid == box_cid) { | 3350 if (value_cid == box_cid) { |
3474 EmitLoadFromBox(compiler); | 3351 EmitLoadFromBox(compiler); |
3475 } else if (CanConvertSmi() && (value_cid == kSmiCid)) { | 3352 } else if (CanConvertSmi() && (value_cid == kSmiCid)) { |
3476 EmitSmiConversion(compiler); | 3353 EmitSmiConversion(compiler); |
3477 } else { | 3354 } else { |
3478 const Register box = locs()->in(0).reg(); | 3355 const Register box = locs()->in(0).reg(); |
(...skipping 20 matching lines...) Expand all Loading... |
3499 if (is_smi.IsLinked()) { | 3376 if (is_smi.IsLinked()) { |
3500 Label done; | 3377 Label done; |
3501 __ jmp(&done); | 3378 __ jmp(&done); |
3502 __ Bind(&is_smi); | 3379 __ Bind(&is_smi); |
3503 EmitSmiConversion(compiler); | 3380 EmitSmiConversion(compiler); |
3504 __ Bind(&done); | 3381 __ Bind(&done); |
3505 } | 3382 } |
3506 } | 3383 } |
3507 } | 3384 } |
3508 | 3385 |
3509 | |
3510 LocationSummary* BoxInteger32Instr::MakeLocationSummary(Zone* zone, | 3386 LocationSummary* BoxInteger32Instr::MakeLocationSummary(Zone* zone, |
3511 bool opt) const { | 3387 bool opt) const { |
3512 const intptr_t kNumInputs = 1; | 3388 const intptr_t kNumInputs = 1; |
3513 const intptr_t kNumTemps = ValueFitsSmi() ? 0 : 1; | 3389 const intptr_t kNumTemps = ValueFitsSmi() ? 0 : 1; |
3514 LocationSummary* summary = new (zone) | 3390 LocationSummary* summary = new (zone) |
3515 LocationSummary(zone, kNumInputs, kNumTemps, | 3391 LocationSummary(zone, kNumInputs, kNumTemps, |
3516 ValueFitsSmi() ? LocationSummary::kNoCall | 3392 ValueFitsSmi() ? LocationSummary::kNoCall |
3517 : LocationSummary::kCallOnSlowPath); | 3393 : LocationSummary::kCallOnSlowPath); |
3518 const bool needs_writable_input = | 3394 const bool needs_writable_input = |
3519 ValueFitsSmi() || (from_representation() == kUnboxedUint32); | 3395 ValueFitsSmi() || (from_representation() == kUnboxedUint32); |
3520 summary->set_in(0, needs_writable_input ? Location::RequiresRegister() | 3396 summary->set_in(0, needs_writable_input ? Location::RequiresRegister() |
3521 : Location::WritableRegister()); | 3397 : Location::WritableRegister()); |
3522 if (!ValueFitsSmi()) { | 3398 if (!ValueFitsSmi()) { |
3523 summary->set_temp(0, Location::RequiresRegister()); | 3399 summary->set_temp(0, Location::RequiresRegister()); |
3524 } | 3400 } |
3525 summary->set_out(0, ValueFitsSmi() ? Location::SameAsFirstInput() | 3401 summary->set_out(0, ValueFitsSmi() ? Location::SameAsFirstInput() |
3526 : Location::RequiresRegister()); | 3402 : Location::RequiresRegister()); |
3527 return summary; | 3403 return summary; |
3528 } | 3404 } |
3529 | 3405 |
3530 | |
3531 void BoxInteger32Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3406 void BoxInteger32Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
3532 const Register value = locs()->in(0).reg(); | 3407 const Register value = locs()->in(0).reg(); |
3533 const Register out = locs()->out(0).reg(); | 3408 const Register out = locs()->out(0).reg(); |
3534 | 3409 |
3535 __ MoveRegister(out, value); | 3410 __ MoveRegister(out, value); |
3536 __ shll(out, Immediate(kSmiTagSize)); | 3411 __ shll(out, Immediate(kSmiTagSize)); |
3537 if (!ValueFitsSmi()) { | 3412 if (!ValueFitsSmi()) { |
3538 Label done; | 3413 Label done; |
3539 ASSERT(value != out); | 3414 ASSERT(value != out); |
3540 if (from_representation() == kUnboxedInt32) { | 3415 if (from_representation() == kUnboxedInt32) { |
(...skipping 14 matching lines...) Expand all Loading... |
3555 __ sarl(value, Immediate(31)); // Sign extend. | 3430 __ sarl(value, Immediate(31)); // Sign extend. |
3556 __ movl(FieldAddress(out, Mint::value_offset() + kWordSize), value); | 3431 __ movl(FieldAddress(out, Mint::value_offset() + kWordSize), value); |
3557 } else { | 3432 } else { |
3558 __ movl(FieldAddress(out, Mint::value_offset() + kWordSize), | 3433 __ movl(FieldAddress(out, Mint::value_offset() + kWordSize), |
3559 Immediate(0)); | 3434 Immediate(0)); |
3560 } | 3435 } |
3561 __ Bind(&done); | 3436 __ Bind(&done); |
3562 } | 3437 } |
3563 } | 3438 } |
3564 | 3439 |
3565 | |
3566 LocationSummary* BoxInt64Instr::MakeLocationSummary(Zone* zone, | 3440 LocationSummary* BoxInt64Instr::MakeLocationSummary(Zone* zone, |
3567 bool opt) const { | 3441 bool opt) const { |
3568 const intptr_t kNumInputs = 1; | 3442 const intptr_t kNumInputs = 1; |
3569 const intptr_t kNumTemps = ValueFitsSmi() ? 0 : 1; | 3443 const intptr_t kNumTemps = ValueFitsSmi() ? 0 : 1; |
3570 LocationSummary* summary = new (zone) | 3444 LocationSummary* summary = new (zone) |
3571 LocationSummary(zone, kNumInputs, kNumTemps, | 3445 LocationSummary(zone, kNumInputs, kNumTemps, |
3572 ValueFitsSmi() ? LocationSummary::kNoCall | 3446 ValueFitsSmi() ? LocationSummary::kNoCall |
3573 : LocationSummary::kCallOnSlowPath); | 3447 : LocationSummary::kCallOnSlowPath); |
3574 summary->set_in(0, Location::Pair(Location::RequiresRegister(), | 3448 summary->set_in(0, Location::Pair(Location::RequiresRegister(), |
3575 Location::RequiresRegister())); | 3449 Location::RequiresRegister())); |
3576 if (!ValueFitsSmi()) { | 3450 if (!ValueFitsSmi()) { |
3577 summary->set_temp(0, Location::RequiresRegister()); | 3451 summary->set_temp(0, Location::RequiresRegister()); |
3578 } | 3452 } |
3579 summary->set_out(0, Location::RequiresRegister()); | 3453 summary->set_out(0, Location::RequiresRegister()); |
3580 return summary; | 3454 return summary; |
3581 } | 3455 } |
3582 | 3456 |
3583 | |
3584 void BoxInt64Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3457 void BoxInt64Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
3585 if (ValueFitsSmi()) { | 3458 if (ValueFitsSmi()) { |
3586 PairLocation* value_pair = locs()->in(0).AsPairLocation(); | 3459 PairLocation* value_pair = locs()->in(0).AsPairLocation(); |
3587 Register value_lo = value_pair->At(0).reg(); | 3460 Register value_lo = value_pair->At(0).reg(); |
3588 Register out_reg = locs()->out(0).reg(); | 3461 Register out_reg = locs()->out(0).reg(); |
3589 __ movl(out_reg, value_lo); | 3462 __ movl(out_reg, value_lo); |
3590 __ SmiTag(out_reg); | 3463 __ SmiTag(out_reg); |
3591 return; | 3464 return; |
3592 } | 3465 } |
3593 | 3466 |
(...skipping 27 matching lines...) Expand all Loading... |
3621 // 3. Restore lower half of input before using it. | 3494 // 3. Restore lower half of input before using it. |
3622 __ subl(value_lo, Immediate(0x40000000)); | 3495 __ subl(value_lo, Immediate(0x40000000)); |
3623 | 3496 |
3624 BoxAllocationSlowPath::Allocate(compiler, this, compiler->mint_class(), | 3497 BoxAllocationSlowPath::Allocate(compiler, this, compiler->mint_class(), |
3625 out_reg, locs()->temp(0).reg()); | 3498 out_reg, locs()->temp(0).reg()); |
3626 __ movl(FieldAddress(out_reg, Mint::value_offset()), value_lo); | 3499 __ movl(FieldAddress(out_reg, Mint::value_offset()), value_lo); |
3627 __ movl(FieldAddress(out_reg, Mint::value_offset() + kWordSize), value_hi); | 3500 __ movl(FieldAddress(out_reg, Mint::value_offset() + kWordSize), value_hi); |
3628 __ Bind(&done); | 3501 __ Bind(&done); |
3629 } | 3502 } |
3630 | 3503 |
3631 | |
3632 LocationSummary* UnboxInteger32Instr::MakeLocationSummary(Zone* zone, | 3504 LocationSummary* UnboxInteger32Instr::MakeLocationSummary(Zone* zone, |
3633 bool opt) const { | 3505 bool opt) const { |
3634 const intptr_t value_cid = value()->Type()->ToCid(); | 3506 const intptr_t value_cid = value()->Type()->ToCid(); |
3635 const intptr_t kNumInputs = 1; | 3507 const intptr_t kNumInputs = 1; |
3636 intptr_t kNumTemps = 0; | 3508 intptr_t kNumTemps = 0; |
3637 | 3509 |
3638 if (CanDeoptimize()) { | 3510 if (CanDeoptimize()) { |
3639 if ((value_cid != kSmiCid) && (value_cid != kMintCid) && !is_truncating()) { | 3511 if ((value_cid != kSmiCid) && (value_cid != kMintCid) && !is_truncating()) { |
3640 kNumTemps = 2; | 3512 kNumTemps = 2; |
3641 } else { | 3513 } else { |
3642 kNumTemps = 1; | 3514 kNumTemps = 1; |
3643 } | 3515 } |
3644 } | 3516 } |
3645 | 3517 |
3646 LocationSummary* summary = new (zone) | 3518 LocationSummary* summary = new (zone) |
3647 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3519 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
3648 summary->set_in(0, Location::RequiresRegister()); | 3520 summary->set_in(0, Location::RequiresRegister()); |
3649 for (int i = 0; i < kNumTemps; i++) { | 3521 for (int i = 0; i < kNumTemps; i++) { |
3650 summary->set_temp(i, Location::RequiresRegister()); | 3522 summary->set_temp(i, Location::RequiresRegister()); |
3651 } | 3523 } |
3652 summary->set_out(0, ((value_cid == kSmiCid) || (value_cid != kMintCid)) | 3524 summary->set_out(0, ((value_cid == kSmiCid) || (value_cid != kMintCid)) |
3653 ? Location::SameAsFirstInput() | 3525 ? Location::SameAsFirstInput() |
3654 : Location::RequiresRegister()); | 3526 : Location::RequiresRegister()); |
3655 return summary; | 3527 return summary; |
3656 } | 3528 } |
3657 | 3529 |
3658 | |
3659 static void LoadInt32FromMint(FlowGraphCompiler* compiler, | 3530 static void LoadInt32FromMint(FlowGraphCompiler* compiler, |
3660 Register result, | 3531 Register result, |
3661 const Address& lo, | 3532 const Address& lo, |
3662 const Address& hi, | 3533 const Address& hi, |
3663 Register temp, | 3534 Register temp, |
3664 Label* deopt) { | 3535 Label* deopt) { |
3665 __ movl(result, lo); | 3536 __ movl(result, lo); |
3666 if (deopt != NULL) { | 3537 if (deopt != NULL) { |
3667 ASSERT(temp != result); | 3538 ASSERT(temp != result); |
3668 __ movl(temp, result); | 3539 __ movl(temp, result); |
3669 __ sarl(temp, Immediate(31)); | 3540 __ sarl(temp, Immediate(31)); |
3670 __ cmpl(temp, hi); | 3541 __ cmpl(temp, hi); |
3671 __ j(NOT_EQUAL, deopt); | 3542 __ j(NOT_EQUAL, deopt); |
3672 } | 3543 } |
3673 } | 3544 } |
3674 | 3545 |
3675 | |
3676 void UnboxInteger32Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3546 void UnboxInteger32Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
3677 const intptr_t value_cid = value()->Type()->ToCid(); | 3547 const intptr_t value_cid = value()->Type()->ToCid(); |
3678 Register value = locs()->in(0).reg(); | 3548 Register value = locs()->in(0).reg(); |
3679 const Register result = locs()->out(0).reg(); | 3549 const Register result = locs()->out(0).reg(); |
3680 const Register temp = CanDeoptimize() ? locs()->temp(0).reg() : kNoRegister; | 3550 const Register temp = CanDeoptimize() ? locs()->temp(0).reg() : kNoRegister; |
3681 Label* deopt = | 3551 Label* deopt = CanDeoptimize() ? compiler->AddDeoptStub( |
3682 CanDeoptimize() | 3552 GetDeoptId(), ICData::kDeoptUnboxInteger) |
3683 ? compiler->AddDeoptStub(GetDeoptId(), ICData::kDeoptUnboxInteger) | 3553 : NULL; |
3684 : NULL; | |
3685 Label* out_of_range = !is_truncating() ? deopt : NULL; | 3554 Label* out_of_range = !is_truncating() ? deopt : NULL; |
3686 | 3555 |
3687 const intptr_t lo_offset = Mint::value_offset(); | 3556 const intptr_t lo_offset = Mint::value_offset(); |
3688 const intptr_t hi_offset = Mint::value_offset() + kWordSize; | 3557 const intptr_t hi_offset = Mint::value_offset() + kWordSize; |
3689 | 3558 |
3690 if (value_cid == kSmiCid) { | 3559 if (value_cid == kSmiCid) { |
3691 ASSERT(value == result); | 3560 ASSERT(value == result); |
3692 __ SmiUntag(value); | 3561 __ SmiUntag(value); |
3693 } else if (value_cid == kMintCid) { | 3562 } else if (value_cid == kMintCid) { |
3694 ASSERT((value != result) || (out_of_range == NULL)); | 3563 ASSERT((value != result) || (out_of_range == NULL)); |
(...skipping 15 matching lines...) Expand all Loading... |
3710 Register value_temp = locs()->temp(1).reg(); | 3579 Register value_temp = locs()->temp(1).reg(); |
3711 __ movl(value_temp, value); | 3580 __ movl(value_temp, value); |
3712 value = value_temp; | 3581 value = value_temp; |
3713 } | 3582 } |
3714 LoadInt32FromMint(compiler, result, Address(value, TIMES_2, lo_offset), | 3583 LoadInt32FromMint(compiler, result, Address(value, TIMES_2, lo_offset), |
3715 Address(value, TIMES_2, hi_offset), temp, out_of_range); | 3584 Address(value, TIMES_2, hi_offset), temp, out_of_range); |
3716 __ Bind(&done); | 3585 __ Bind(&done); |
3717 } | 3586 } |
3718 } | 3587 } |
3719 | 3588 |
3720 | |
3721 LocationSummary* LoadCodeUnitsInstr::MakeLocationSummary(Zone* zone, | 3589 LocationSummary* LoadCodeUnitsInstr::MakeLocationSummary(Zone* zone, |
3722 bool opt) const { | 3590 bool opt) const { |
3723 const bool might_box = (representation() == kTagged) && !can_pack_into_smi(); | 3591 const bool might_box = (representation() == kTagged) && !can_pack_into_smi(); |
3724 const intptr_t kNumInputs = 2; | 3592 const intptr_t kNumInputs = 2; |
3725 const intptr_t kNumTemps = might_box ? 2 : 0; | 3593 const intptr_t kNumTemps = might_box ? 2 : 0; |
3726 LocationSummary* summary = new (zone) LocationSummary( | 3594 LocationSummary* summary = new (zone) LocationSummary( |
3727 zone, kNumInputs, kNumTemps, | 3595 zone, kNumInputs, kNumTemps, |
3728 might_box ? LocationSummary::kCallOnSlowPath : LocationSummary::kNoCall); | 3596 might_box ? LocationSummary::kCallOnSlowPath : LocationSummary::kNoCall); |
3729 summary->set_in(0, Location::RequiresRegister()); | 3597 summary->set_in(0, Location::RequiresRegister()); |
3730 // The smi index is either untagged (element size == 1), or it is left smi | 3598 // The smi index is either untagged (element size == 1), or it is left smi |
3731 // tagged (for all element sizes > 1). | 3599 // tagged (for all element sizes > 1). |
3732 summary->set_in(1, (index_scale() == 1) ? Location::WritableRegister() | 3600 summary->set_in(1, (index_scale() == 1) ? Location::WritableRegister() |
3733 : Location::RequiresRegister()); | 3601 : Location::RequiresRegister()); |
3734 if (might_box) { | 3602 if (might_box) { |
3735 summary->set_temp(0, Location::RequiresRegister()); | 3603 summary->set_temp(0, Location::RequiresRegister()); |
3736 summary->set_temp(1, Location::RequiresRegister()); | 3604 summary->set_temp(1, Location::RequiresRegister()); |
3737 } | 3605 } |
3738 | 3606 |
3739 if (representation() == kUnboxedMint) { | 3607 if (representation() == kUnboxedMint) { |
3740 summary->set_out(0, Location::Pair(Location::RequiresRegister(), | 3608 summary->set_out(0, Location::Pair(Location::RequiresRegister(), |
3741 Location::RequiresRegister())); | 3609 Location::RequiresRegister())); |
3742 } else { | 3610 } else { |
3743 ASSERT(representation() == kTagged); | 3611 ASSERT(representation() == kTagged); |
3744 summary->set_out(0, Location::RequiresRegister()); | 3612 summary->set_out(0, Location::RequiresRegister()); |
3745 } | 3613 } |
3746 | 3614 |
3747 return summary; | 3615 return summary; |
3748 } | 3616 } |
3749 | 3617 |
3750 | |
3751 void LoadCodeUnitsInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3618 void LoadCodeUnitsInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
3752 // The string register points to the backing store for external strings. | 3619 // The string register points to the backing store for external strings. |
3753 const Register str = locs()->in(0).reg(); | 3620 const Register str = locs()->in(0).reg(); |
3754 const Location index = locs()->in(1); | 3621 const Location index = locs()->in(1); |
3755 | 3622 |
3756 Address element_address = Assembler::ElementAddressForRegIndex( | 3623 Address element_address = Assembler::ElementAddressForRegIndex( |
3757 IsExternal(), class_id(), index_scale(), str, index.reg()); | 3624 IsExternal(), class_id(), index_scale(), str, index.reg()); |
3758 | 3625 |
3759 if ((index_scale() == 1)) { | 3626 if ((index_scale() == 1)) { |
3760 __ SmiUntag(index.reg()); | 3627 __ SmiUntag(index.reg()); |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3839 BoxAllocationSlowPath::Allocate(compiler, this, compiler->mint_class(), | 3706 BoxAllocationSlowPath::Allocate(compiler, this, compiler->mint_class(), |
3840 result, temp2); | 3707 result, temp2); |
3841 __ movl(FieldAddress(result, Mint::value_offset()), temp); | 3708 __ movl(FieldAddress(result, Mint::value_offset()), temp); |
3842 __ movl(FieldAddress(result, Mint::value_offset() + kWordSize), | 3709 __ movl(FieldAddress(result, Mint::value_offset() + kWordSize), |
3843 Immediate(0)); | 3710 Immediate(0)); |
3844 __ Bind(&done); | 3711 __ Bind(&done); |
3845 } | 3712 } |
3846 } | 3713 } |
3847 } | 3714 } |
3848 | 3715 |
3849 | |
3850 LocationSummary* BinaryDoubleOpInstr::MakeLocationSummary(Zone* zone, | 3716 LocationSummary* BinaryDoubleOpInstr::MakeLocationSummary(Zone* zone, |
3851 bool opt) const { | 3717 bool opt) const { |
3852 const intptr_t kNumInputs = 2; | 3718 const intptr_t kNumInputs = 2; |
3853 const intptr_t kNumTemps = 0; | 3719 const intptr_t kNumTemps = 0; |
3854 LocationSummary* summary = new (zone) | 3720 LocationSummary* summary = new (zone) |
3855 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3721 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
3856 summary->set_in(0, Location::RequiresFpuRegister()); | 3722 summary->set_in(0, Location::RequiresFpuRegister()); |
3857 summary->set_in(1, Location::RequiresFpuRegister()); | 3723 summary->set_in(1, Location::RequiresFpuRegister()); |
3858 summary->set_out(0, Location::SameAsFirstInput()); | 3724 summary->set_out(0, Location::SameAsFirstInput()); |
3859 return summary; | 3725 return summary; |
3860 } | 3726 } |
3861 | 3727 |
3862 | |
3863 void BinaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3728 void BinaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
3864 XmmRegister left = locs()->in(0).fpu_reg(); | 3729 XmmRegister left = locs()->in(0).fpu_reg(); |
3865 XmmRegister right = locs()->in(1).fpu_reg(); | 3730 XmmRegister right = locs()->in(1).fpu_reg(); |
3866 | 3731 |
3867 ASSERT(locs()->out(0).fpu_reg() == left); | 3732 ASSERT(locs()->out(0).fpu_reg() == left); |
3868 | 3733 |
3869 switch (op_kind()) { | 3734 switch (op_kind()) { |
3870 case Token::kADD: | 3735 case Token::kADD: |
3871 __ addsd(left, right); | 3736 __ addsd(left, right); |
3872 break; | 3737 break; |
3873 case Token::kSUB: | 3738 case Token::kSUB: |
3874 __ subsd(left, right); | 3739 __ subsd(left, right); |
3875 break; | 3740 break; |
3876 case Token::kMUL: | 3741 case Token::kMUL: |
3877 __ mulsd(left, right); | 3742 __ mulsd(left, right); |
3878 break; | 3743 break; |
3879 case Token::kDIV: | 3744 case Token::kDIV: |
3880 __ divsd(left, right); | 3745 __ divsd(left, right); |
3881 break; | 3746 break; |
3882 default: | 3747 default: |
3883 UNREACHABLE(); | 3748 UNREACHABLE(); |
3884 } | 3749 } |
3885 } | 3750 } |
3886 | 3751 |
3887 | |
3888 LocationSummary* DoubleTestOpInstr::MakeLocationSummary(Zone* zone, | 3752 LocationSummary* DoubleTestOpInstr::MakeLocationSummary(Zone* zone, |
3889 bool opt) const { | 3753 bool opt) const { |
3890 const intptr_t kNumInputs = 1; | 3754 const intptr_t kNumInputs = 1; |
3891 const intptr_t kNumTemps = | 3755 const intptr_t kNumTemps = |
3892 (op_kind() == MethodRecognizer::kDouble_getIsInfinite) ? 1 : 0; | 3756 (op_kind() == MethodRecognizer::kDouble_getIsInfinite) ? 1 : 0; |
3893 LocationSummary* summary = new (zone) | 3757 LocationSummary* summary = new (zone) |
3894 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3758 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
3895 summary->set_in(0, Location::RequiresFpuRegister()); | 3759 summary->set_in(0, Location::RequiresFpuRegister()); |
3896 if (op_kind() == MethodRecognizer::kDouble_getIsInfinite) { | 3760 if (op_kind() == MethodRecognizer::kDouble_getIsInfinite) { |
3897 summary->set_temp(0, Location::RequiresRegister()); | 3761 summary->set_temp(0, Location::RequiresRegister()); |
3898 } | 3762 } |
3899 summary->set_out(0, Location::RequiresRegister()); | 3763 summary->set_out(0, Location::RequiresRegister()); |
3900 return summary; | 3764 return summary; |
3901 } | 3765 } |
3902 | 3766 |
3903 | |
3904 Condition DoubleTestOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler, | 3767 Condition DoubleTestOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
3905 BranchLabels labels) { | 3768 BranchLabels labels) { |
3906 ASSERT(compiler->is_optimizing()); | 3769 ASSERT(compiler->is_optimizing()); |
3907 const XmmRegister value = locs()->in(0).fpu_reg(); | 3770 const XmmRegister value = locs()->in(0).fpu_reg(); |
3908 const bool is_negated = kind() != Token::kEQ; | 3771 const bool is_negated = kind() != Token::kEQ; |
3909 if (op_kind() == MethodRecognizer::kDouble_getIsNaN) { | 3772 if (op_kind() == MethodRecognizer::kDouble_getIsNaN) { |
3910 Label is_nan; | 3773 Label is_nan; |
3911 __ comisd(value, value); | 3774 __ comisd(value, value); |
3912 return is_negated ? PARITY_ODD : PARITY_EVEN; | 3775 return is_negated ? PARITY_ODD : PARITY_EVEN; |
3913 } else { | 3776 } else { |
(...skipping 13 matching lines...) Expand all Loading... |
3927 __ movl(temp, Address(ESP, kWordSize)); | 3790 __ movl(temp, Address(ESP, kWordSize)); |
3928 __ AddImmediate(ESP, Immediate(kDoubleSize)); | 3791 __ AddImmediate(ESP, Immediate(kDoubleSize)); |
3929 // Mask off sign bit. | 3792 // Mask off sign bit. |
3930 __ andl(temp, Immediate(0x7FFFFFFF)); | 3793 __ andl(temp, Immediate(0x7FFFFFFF)); |
3931 // Compare with +infinity. | 3794 // Compare with +infinity. |
3932 __ cmpl(temp, Immediate(0x7FF00000)); | 3795 __ cmpl(temp, Immediate(0x7FF00000)); |
3933 return is_negated ? NOT_EQUAL : EQUAL; | 3796 return is_negated ? NOT_EQUAL : EQUAL; |
3934 } | 3797 } |
3935 } | 3798 } |
3936 | 3799 |
3937 | |
3938 LocationSummary* BinaryFloat32x4OpInstr::MakeLocationSummary(Zone* zone, | 3800 LocationSummary* BinaryFloat32x4OpInstr::MakeLocationSummary(Zone* zone, |
3939 bool opt) const { | 3801 bool opt) const { |
3940 const intptr_t kNumInputs = 2; | 3802 const intptr_t kNumInputs = 2; |
3941 const intptr_t kNumTemps = 0; | 3803 const intptr_t kNumTemps = 0; |
3942 LocationSummary* summary = new (zone) | 3804 LocationSummary* summary = new (zone) |
3943 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3805 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
3944 summary->set_in(0, Location::RequiresFpuRegister()); | 3806 summary->set_in(0, Location::RequiresFpuRegister()); |
3945 summary->set_in(1, Location::RequiresFpuRegister()); | 3807 summary->set_in(1, Location::RequiresFpuRegister()); |
3946 summary->set_out(0, Location::SameAsFirstInput()); | 3808 summary->set_out(0, Location::SameAsFirstInput()); |
3947 return summary; | 3809 return summary; |
3948 } | 3810 } |
3949 | 3811 |
3950 | |
3951 void BinaryFloat32x4OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3812 void BinaryFloat32x4OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
3952 XmmRegister left = locs()->in(0).fpu_reg(); | 3813 XmmRegister left = locs()->in(0).fpu_reg(); |
3953 XmmRegister right = locs()->in(1).fpu_reg(); | 3814 XmmRegister right = locs()->in(1).fpu_reg(); |
3954 | 3815 |
3955 ASSERT(locs()->out(0).fpu_reg() == left); | 3816 ASSERT(locs()->out(0).fpu_reg() == left); |
3956 | 3817 |
3957 switch (op_kind()) { | 3818 switch (op_kind()) { |
3958 case Token::kADD: | 3819 case Token::kADD: |
3959 __ addps(left, right); | 3820 __ addps(left, right); |
3960 break; | 3821 break; |
3961 case Token::kSUB: | 3822 case Token::kSUB: |
3962 __ subps(left, right); | 3823 __ subps(left, right); |
3963 break; | 3824 break; |
3964 case Token::kMUL: | 3825 case Token::kMUL: |
3965 __ mulps(left, right); | 3826 __ mulps(left, right); |
3966 break; | 3827 break; |
3967 case Token::kDIV: | 3828 case Token::kDIV: |
3968 __ divps(left, right); | 3829 __ divps(left, right); |
3969 break; | 3830 break; |
3970 default: | 3831 default: |
3971 UNREACHABLE(); | 3832 UNREACHABLE(); |
3972 } | 3833 } |
3973 } | 3834 } |
3974 | 3835 |
3975 | |
3976 LocationSummary* BinaryFloat64x2OpInstr::MakeLocationSummary(Zone* zone, | 3836 LocationSummary* BinaryFloat64x2OpInstr::MakeLocationSummary(Zone* zone, |
3977 bool opt) const { | 3837 bool opt) const { |
3978 const intptr_t kNumInputs = 2; | 3838 const intptr_t kNumInputs = 2; |
3979 const intptr_t kNumTemps = 0; | 3839 const intptr_t kNumTemps = 0; |
3980 LocationSummary* summary = new (zone) | 3840 LocationSummary* summary = new (zone) |
3981 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3841 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
3982 summary->set_in(0, Location::RequiresFpuRegister()); | 3842 summary->set_in(0, Location::RequiresFpuRegister()); |
3983 summary->set_in(1, Location::RequiresFpuRegister()); | 3843 summary->set_in(1, Location::RequiresFpuRegister()); |
3984 summary->set_out(0, Location::SameAsFirstInput()); | 3844 summary->set_out(0, Location::SameAsFirstInput()); |
3985 return summary; | 3845 return summary; |
3986 } | 3846 } |
3987 | 3847 |
3988 | |
3989 void BinaryFloat64x2OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3848 void BinaryFloat64x2OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
3990 XmmRegister left = locs()->in(0).fpu_reg(); | 3849 XmmRegister left = locs()->in(0).fpu_reg(); |
3991 XmmRegister right = locs()->in(1).fpu_reg(); | 3850 XmmRegister right = locs()->in(1).fpu_reg(); |
3992 | 3851 |
3993 ASSERT(locs()->out(0).fpu_reg() == left); | 3852 ASSERT(locs()->out(0).fpu_reg() == left); |
3994 | 3853 |
3995 switch (op_kind()) { | 3854 switch (op_kind()) { |
3996 case Token::kADD: | 3855 case Token::kADD: |
3997 __ addpd(left, right); | 3856 __ addpd(left, right); |
3998 break; | 3857 break; |
3999 case Token::kSUB: | 3858 case Token::kSUB: |
4000 __ subpd(left, right); | 3859 __ subpd(left, right); |
4001 break; | 3860 break; |
4002 case Token::kMUL: | 3861 case Token::kMUL: |
4003 __ mulpd(left, right); | 3862 __ mulpd(left, right); |
4004 break; | 3863 break; |
4005 case Token::kDIV: | 3864 case Token::kDIV: |
4006 __ divpd(left, right); | 3865 __ divpd(left, right); |
4007 break; | 3866 break; |
4008 default: | 3867 default: |
4009 UNREACHABLE(); | 3868 UNREACHABLE(); |
4010 } | 3869 } |
4011 } | 3870 } |
4012 | 3871 |
4013 | |
4014 LocationSummary* Simd32x4ShuffleInstr::MakeLocationSummary(Zone* zone, | 3872 LocationSummary* Simd32x4ShuffleInstr::MakeLocationSummary(Zone* zone, |
4015 bool opt) const { | 3873 bool opt) const { |
4016 const intptr_t kNumInputs = 1; | 3874 const intptr_t kNumInputs = 1; |
4017 const intptr_t kNumTemps = 0; | 3875 const intptr_t kNumTemps = 0; |
4018 LocationSummary* summary = new (zone) | 3876 LocationSummary* summary = new (zone) |
4019 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3877 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4020 summary->set_in(0, Location::RequiresFpuRegister()); | 3878 summary->set_in(0, Location::RequiresFpuRegister()); |
4021 summary->set_out(0, Location::SameAsFirstInput()); | 3879 summary->set_out(0, Location::SameAsFirstInput()); |
4022 return summary; | 3880 return summary; |
4023 } | 3881 } |
4024 | 3882 |
4025 | |
4026 void Simd32x4ShuffleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3883 void Simd32x4ShuffleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4027 XmmRegister value = locs()->in(0).fpu_reg(); | 3884 XmmRegister value = locs()->in(0).fpu_reg(); |
4028 | 3885 |
4029 ASSERT(locs()->out(0).fpu_reg() == value); | 3886 ASSERT(locs()->out(0).fpu_reg() == value); |
4030 | 3887 |
4031 switch (op_kind()) { | 3888 switch (op_kind()) { |
4032 case MethodRecognizer::kFloat32x4ShuffleX: | 3889 case MethodRecognizer::kFloat32x4ShuffleX: |
4033 // Shuffle not necessary. | 3890 // Shuffle not necessary. |
4034 __ cvtss2sd(value, value); | 3891 __ cvtss2sd(value, value); |
4035 break; | 3892 break; |
(...skipping 11 matching lines...) Expand all Loading... |
4047 break; | 3904 break; |
4048 case MethodRecognizer::kFloat32x4Shuffle: | 3905 case MethodRecognizer::kFloat32x4Shuffle: |
4049 case MethodRecognizer::kInt32x4Shuffle: | 3906 case MethodRecognizer::kInt32x4Shuffle: |
4050 __ shufps(value, value, Immediate(mask_)); | 3907 __ shufps(value, value, Immediate(mask_)); |
4051 break; | 3908 break; |
4052 default: | 3909 default: |
4053 UNREACHABLE(); | 3910 UNREACHABLE(); |
4054 } | 3911 } |
4055 } | 3912 } |
4056 | 3913 |
4057 | |
4058 LocationSummary* Simd32x4ShuffleMixInstr::MakeLocationSummary(Zone* zone, | 3914 LocationSummary* Simd32x4ShuffleMixInstr::MakeLocationSummary(Zone* zone, |
4059 bool opt) const { | 3915 bool opt) const { |
4060 const intptr_t kNumInputs = 2; | 3916 const intptr_t kNumInputs = 2; |
4061 const intptr_t kNumTemps = 0; | 3917 const intptr_t kNumTemps = 0; |
4062 LocationSummary* summary = new (zone) | 3918 LocationSummary* summary = new (zone) |
4063 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3919 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4064 summary->set_in(0, Location::RequiresFpuRegister()); | 3920 summary->set_in(0, Location::RequiresFpuRegister()); |
4065 summary->set_in(1, Location::RequiresFpuRegister()); | 3921 summary->set_in(1, Location::RequiresFpuRegister()); |
4066 summary->set_out(0, Location::SameAsFirstInput()); | 3922 summary->set_out(0, Location::SameAsFirstInput()); |
4067 return summary; | 3923 return summary; |
4068 } | 3924 } |
4069 | 3925 |
4070 | |
4071 void Simd32x4ShuffleMixInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3926 void Simd32x4ShuffleMixInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4072 XmmRegister left = locs()->in(0).fpu_reg(); | 3927 XmmRegister left = locs()->in(0).fpu_reg(); |
4073 XmmRegister right = locs()->in(1).fpu_reg(); | 3928 XmmRegister right = locs()->in(1).fpu_reg(); |
4074 | 3929 |
4075 ASSERT(locs()->out(0).fpu_reg() == left); | 3930 ASSERT(locs()->out(0).fpu_reg() == left); |
4076 switch (op_kind()) { | 3931 switch (op_kind()) { |
4077 case MethodRecognizer::kFloat32x4ShuffleMix: | 3932 case MethodRecognizer::kFloat32x4ShuffleMix: |
4078 case MethodRecognizer::kInt32x4ShuffleMix: | 3933 case MethodRecognizer::kInt32x4ShuffleMix: |
4079 __ shufps(left, right, Immediate(mask_)); | 3934 __ shufps(left, right, Immediate(mask_)); |
4080 break; | 3935 break; |
4081 default: | 3936 default: |
4082 UNREACHABLE(); | 3937 UNREACHABLE(); |
4083 } | 3938 } |
4084 } | 3939 } |
4085 | 3940 |
4086 | |
4087 LocationSummary* Simd32x4GetSignMaskInstr::MakeLocationSummary(Zone* zone, | 3941 LocationSummary* Simd32x4GetSignMaskInstr::MakeLocationSummary(Zone* zone, |
4088 bool opt) const { | 3942 bool opt) const { |
4089 const intptr_t kNumInputs = 1; | 3943 const intptr_t kNumInputs = 1; |
4090 const intptr_t kNumTemps = 0; | 3944 const intptr_t kNumTemps = 0; |
4091 LocationSummary* summary = new (zone) | 3945 LocationSummary* summary = new (zone) |
4092 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3946 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4093 summary->set_in(0, Location::RequiresFpuRegister()); | 3947 summary->set_in(0, Location::RequiresFpuRegister()); |
4094 summary->set_out(0, Location::RequiresRegister()); | 3948 summary->set_out(0, Location::RequiresRegister()); |
4095 return summary; | 3949 return summary; |
4096 } | 3950 } |
4097 | 3951 |
4098 | |
4099 void Simd32x4GetSignMaskInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3952 void Simd32x4GetSignMaskInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4100 XmmRegister value = locs()->in(0).fpu_reg(); | 3953 XmmRegister value = locs()->in(0).fpu_reg(); |
4101 Register out = locs()->out(0).reg(); | 3954 Register out = locs()->out(0).reg(); |
4102 | 3955 |
4103 __ movmskps(out, value); | 3956 __ movmskps(out, value); |
4104 __ SmiTag(out); | 3957 __ SmiTag(out); |
4105 } | 3958 } |
4106 | 3959 |
4107 | |
4108 LocationSummary* Float32x4ConstructorInstr::MakeLocationSummary( | 3960 LocationSummary* Float32x4ConstructorInstr::MakeLocationSummary( |
4109 Zone* zone, | 3961 Zone* zone, |
4110 bool opt) const { | 3962 bool opt) const { |
4111 const intptr_t kNumInputs = 4; | 3963 const intptr_t kNumInputs = 4; |
4112 const intptr_t kNumTemps = 0; | 3964 const intptr_t kNumTemps = 0; |
4113 LocationSummary* summary = new (zone) | 3965 LocationSummary* summary = new (zone) |
4114 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3966 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4115 summary->set_in(0, Location::RequiresFpuRegister()); | 3967 summary->set_in(0, Location::RequiresFpuRegister()); |
4116 summary->set_in(1, Location::RequiresFpuRegister()); | 3968 summary->set_in(1, Location::RequiresFpuRegister()); |
4117 summary->set_in(2, Location::RequiresFpuRegister()); | 3969 summary->set_in(2, Location::RequiresFpuRegister()); |
4118 summary->set_in(3, Location::RequiresFpuRegister()); | 3970 summary->set_in(3, Location::RequiresFpuRegister()); |
4119 summary->set_out(0, Location::SameAsFirstInput()); | 3971 summary->set_out(0, Location::SameAsFirstInput()); |
4120 return summary; | 3972 return summary; |
4121 } | 3973 } |
4122 | 3974 |
4123 | |
4124 void Float32x4ConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3975 void Float32x4ConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4125 XmmRegister v0 = locs()->in(0).fpu_reg(); | 3976 XmmRegister v0 = locs()->in(0).fpu_reg(); |
4126 XmmRegister v1 = locs()->in(1).fpu_reg(); | 3977 XmmRegister v1 = locs()->in(1).fpu_reg(); |
4127 XmmRegister v2 = locs()->in(2).fpu_reg(); | 3978 XmmRegister v2 = locs()->in(2).fpu_reg(); |
4128 XmmRegister v3 = locs()->in(3).fpu_reg(); | 3979 XmmRegister v3 = locs()->in(3).fpu_reg(); |
4129 ASSERT(v0 == locs()->out(0).fpu_reg()); | 3980 ASSERT(v0 == locs()->out(0).fpu_reg()); |
4130 __ subl(ESP, Immediate(16)); | 3981 __ subl(ESP, Immediate(16)); |
4131 __ cvtsd2ss(v0, v0); | 3982 __ cvtsd2ss(v0, v0); |
4132 __ movss(Address(ESP, 0), v0); | 3983 __ movss(Address(ESP, 0), v0); |
4133 __ movsd(v0, v1); | 3984 __ movsd(v0, v1); |
4134 __ cvtsd2ss(v0, v0); | 3985 __ cvtsd2ss(v0, v0); |
4135 __ movss(Address(ESP, 4), v0); | 3986 __ movss(Address(ESP, 4), v0); |
4136 __ movsd(v0, v2); | 3987 __ movsd(v0, v2); |
4137 __ cvtsd2ss(v0, v0); | 3988 __ cvtsd2ss(v0, v0); |
4138 __ movss(Address(ESP, 8), v0); | 3989 __ movss(Address(ESP, 8), v0); |
4139 __ movsd(v0, v3); | 3990 __ movsd(v0, v3); |
4140 __ cvtsd2ss(v0, v0); | 3991 __ cvtsd2ss(v0, v0); |
4141 __ movss(Address(ESP, 12), v0); | 3992 __ movss(Address(ESP, 12), v0); |
4142 __ movups(v0, Address(ESP, 0)); | 3993 __ movups(v0, Address(ESP, 0)); |
4143 __ addl(ESP, Immediate(16)); | 3994 __ addl(ESP, Immediate(16)); |
4144 } | 3995 } |
4145 | 3996 |
4146 | |
4147 LocationSummary* Float32x4ZeroInstr::MakeLocationSummary(Zone* zone, | 3997 LocationSummary* Float32x4ZeroInstr::MakeLocationSummary(Zone* zone, |
4148 bool opt) const { | 3998 bool opt) const { |
4149 const intptr_t kNumInputs = 0; | 3999 const intptr_t kNumInputs = 0; |
4150 const intptr_t kNumTemps = 0; | 4000 const intptr_t kNumTemps = 0; |
4151 LocationSummary* summary = new (zone) | 4001 LocationSummary* summary = new (zone) |
4152 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4002 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4153 summary->set_out(0, Location::RequiresFpuRegister()); | 4003 summary->set_out(0, Location::RequiresFpuRegister()); |
4154 return summary; | 4004 return summary; |
4155 } | 4005 } |
4156 | 4006 |
4157 | |
4158 void Float32x4ZeroInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4007 void Float32x4ZeroInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4159 XmmRegister value = locs()->out(0).fpu_reg(); | 4008 XmmRegister value = locs()->out(0).fpu_reg(); |
4160 __ xorps(value, value); | 4009 __ xorps(value, value); |
4161 } | 4010 } |
4162 | 4011 |
4163 | |
4164 LocationSummary* Float32x4SplatInstr::MakeLocationSummary(Zone* zone, | 4012 LocationSummary* Float32x4SplatInstr::MakeLocationSummary(Zone* zone, |
4165 bool opt) const { | 4013 bool opt) const { |
4166 const intptr_t kNumInputs = 1; | 4014 const intptr_t kNumInputs = 1; |
4167 const intptr_t kNumTemps = 0; | 4015 const intptr_t kNumTemps = 0; |
4168 LocationSummary* summary = new (zone) | 4016 LocationSummary* summary = new (zone) |
4169 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4017 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4170 summary->set_in(0, Location::RequiresFpuRegister()); | 4018 summary->set_in(0, Location::RequiresFpuRegister()); |
4171 summary->set_out(0, Location::SameAsFirstInput()); | 4019 summary->set_out(0, Location::SameAsFirstInput()); |
4172 return summary; | 4020 return summary; |
4173 } | 4021 } |
4174 | 4022 |
4175 | |
4176 void Float32x4SplatInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4023 void Float32x4SplatInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4177 XmmRegister value = locs()->out(0).fpu_reg(); | 4024 XmmRegister value = locs()->out(0).fpu_reg(); |
4178 ASSERT(locs()->in(0).fpu_reg() == locs()->out(0).fpu_reg()); | 4025 ASSERT(locs()->in(0).fpu_reg() == locs()->out(0).fpu_reg()); |
4179 // Convert to Float32. | 4026 // Convert to Float32. |
4180 __ cvtsd2ss(value, value); | 4027 __ cvtsd2ss(value, value); |
4181 // Splat across all lanes. | 4028 // Splat across all lanes. |
4182 __ shufps(value, value, Immediate(0x00)); | 4029 __ shufps(value, value, Immediate(0x00)); |
4183 } | 4030 } |
4184 | 4031 |
4185 | |
4186 LocationSummary* Float32x4ComparisonInstr::MakeLocationSummary(Zone* zone, | 4032 LocationSummary* Float32x4ComparisonInstr::MakeLocationSummary(Zone* zone, |
4187 bool opt) const { | 4033 bool opt) const { |
4188 const intptr_t kNumInputs = 2; | 4034 const intptr_t kNumInputs = 2; |
4189 const intptr_t kNumTemps = 0; | 4035 const intptr_t kNumTemps = 0; |
4190 LocationSummary* summary = new (zone) | 4036 LocationSummary* summary = new (zone) |
4191 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4037 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4192 summary->set_in(0, Location::RequiresFpuRegister()); | 4038 summary->set_in(0, Location::RequiresFpuRegister()); |
4193 summary->set_in(1, Location::RequiresFpuRegister()); | 4039 summary->set_in(1, Location::RequiresFpuRegister()); |
4194 summary->set_out(0, Location::SameAsFirstInput()); | 4040 summary->set_out(0, Location::SameAsFirstInput()); |
4195 return summary; | 4041 return summary; |
4196 } | 4042 } |
4197 | 4043 |
4198 | |
4199 void Float32x4ComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4044 void Float32x4ComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4200 XmmRegister left = locs()->in(0).fpu_reg(); | 4045 XmmRegister left = locs()->in(0).fpu_reg(); |
4201 XmmRegister right = locs()->in(1).fpu_reg(); | 4046 XmmRegister right = locs()->in(1).fpu_reg(); |
4202 | 4047 |
4203 ASSERT(locs()->out(0).fpu_reg() == left); | 4048 ASSERT(locs()->out(0).fpu_reg() == left); |
4204 | 4049 |
4205 switch (op_kind()) { | 4050 switch (op_kind()) { |
4206 case MethodRecognizer::kFloat32x4Equal: | 4051 case MethodRecognizer::kFloat32x4Equal: |
4207 __ cmppseq(left, right); | 4052 __ cmppseq(left, right); |
4208 break; | 4053 break; |
(...skipping 11 matching lines...) Expand all Loading... |
4220 break; | 4065 break; |
4221 case MethodRecognizer::kFloat32x4LessThanOrEqual: | 4066 case MethodRecognizer::kFloat32x4LessThanOrEqual: |
4222 __ cmppsle(left, right); | 4067 __ cmppsle(left, right); |
4223 break; | 4068 break; |
4224 | 4069 |
4225 default: | 4070 default: |
4226 UNREACHABLE(); | 4071 UNREACHABLE(); |
4227 } | 4072 } |
4228 } | 4073 } |
4229 | 4074 |
4230 | |
4231 LocationSummary* Float32x4MinMaxInstr::MakeLocationSummary(Zone* zone, | 4075 LocationSummary* Float32x4MinMaxInstr::MakeLocationSummary(Zone* zone, |
4232 bool opt) const { | 4076 bool opt) const { |
4233 const intptr_t kNumInputs = 2; | 4077 const intptr_t kNumInputs = 2; |
4234 const intptr_t kNumTemps = 0; | 4078 const intptr_t kNumTemps = 0; |
4235 LocationSummary* summary = new (zone) | 4079 LocationSummary* summary = new (zone) |
4236 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4080 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4237 summary->set_in(0, Location::RequiresFpuRegister()); | 4081 summary->set_in(0, Location::RequiresFpuRegister()); |
4238 summary->set_in(1, Location::RequiresFpuRegister()); | 4082 summary->set_in(1, Location::RequiresFpuRegister()); |
4239 summary->set_out(0, Location::SameAsFirstInput()); | 4083 summary->set_out(0, Location::SameAsFirstInput()); |
4240 return summary; | 4084 return summary; |
4241 } | 4085 } |
4242 | 4086 |
4243 | |
4244 void Float32x4MinMaxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4087 void Float32x4MinMaxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4245 XmmRegister left = locs()->in(0).fpu_reg(); | 4088 XmmRegister left = locs()->in(0).fpu_reg(); |
4246 XmmRegister right = locs()->in(1).fpu_reg(); | 4089 XmmRegister right = locs()->in(1).fpu_reg(); |
4247 | 4090 |
4248 ASSERT(locs()->out(0).fpu_reg() == left); | 4091 ASSERT(locs()->out(0).fpu_reg() == left); |
4249 | 4092 |
4250 switch (op_kind()) { | 4093 switch (op_kind()) { |
4251 case MethodRecognizer::kFloat32x4Min: | 4094 case MethodRecognizer::kFloat32x4Min: |
4252 __ minps(left, right); | 4095 __ minps(left, right); |
4253 break; | 4096 break; |
4254 case MethodRecognizer::kFloat32x4Max: | 4097 case MethodRecognizer::kFloat32x4Max: |
4255 __ maxps(left, right); | 4098 __ maxps(left, right); |
4256 break; | 4099 break; |
4257 default: | 4100 default: |
4258 UNREACHABLE(); | 4101 UNREACHABLE(); |
4259 } | 4102 } |
4260 } | 4103 } |
4261 | 4104 |
4262 | |
4263 LocationSummary* Float32x4ScaleInstr::MakeLocationSummary(Zone* zone, | 4105 LocationSummary* Float32x4ScaleInstr::MakeLocationSummary(Zone* zone, |
4264 bool opt) const { | 4106 bool opt) const { |
4265 const intptr_t kNumInputs = 2; | 4107 const intptr_t kNumInputs = 2; |
4266 const intptr_t kNumTemps = 0; | 4108 const intptr_t kNumTemps = 0; |
4267 LocationSummary* summary = new (zone) | 4109 LocationSummary* summary = new (zone) |
4268 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4110 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4269 summary->set_in(0, Location::RequiresFpuRegister()); | 4111 summary->set_in(0, Location::RequiresFpuRegister()); |
4270 summary->set_in(1, Location::RequiresFpuRegister()); | 4112 summary->set_in(1, Location::RequiresFpuRegister()); |
4271 summary->set_out(0, Location::SameAsFirstInput()); | 4113 summary->set_out(0, Location::SameAsFirstInput()); |
4272 return summary; | 4114 return summary; |
4273 } | 4115 } |
4274 | 4116 |
4275 | |
4276 void Float32x4ScaleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4117 void Float32x4ScaleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4277 XmmRegister left = locs()->in(0).fpu_reg(); | 4118 XmmRegister left = locs()->in(0).fpu_reg(); |
4278 XmmRegister right = locs()->in(1).fpu_reg(); | 4119 XmmRegister right = locs()->in(1).fpu_reg(); |
4279 | 4120 |
4280 ASSERT(locs()->out(0).fpu_reg() == left); | 4121 ASSERT(locs()->out(0).fpu_reg() == left); |
4281 | 4122 |
4282 switch (op_kind()) { | 4123 switch (op_kind()) { |
4283 case MethodRecognizer::kFloat32x4Scale: | 4124 case MethodRecognizer::kFloat32x4Scale: |
4284 __ cvtsd2ss(left, left); | 4125 __ cvtsd2ss(left, left); |
4285 __ shufps(left, left, Immediate(0x00)); | 4126 __ shufps(left, left, Immediate(0x00)); |
4286 __ mulps(left, right); | 4127 __ mulps(left, right); |
4287 break; | 4128 break; |
4288 default: | 4129 default: |
4289 UNREACHABLE(); | 4130 UNREACHABLE(); |
4290 } | 4131 } |
4291 } | 4132 } |
4292 | 4133 |
4293 | |
4294 LocationSummary* Float32x4SqrtInstr::MakeLocationSummary(Zone* zone, | 4134 LocationSummary* Float32x4SqrtInstr::MakeLocationSummary(Zone* zone, |
4295 bool opt) const { | 4135 bool opt) const { |
4296 const intptr_t kNumInputs = 1; | 4136 const intptr_t kNumInputs = 1; |
4297 const intptr_t kNumTemps = 0; | 4137 const intptr_t kNumTemps = 0; |
4298 LocationSummary* summary = new (zone) | 4138 LocationSummary* summary = new (zone) |
4299 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4139 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4300 summary->set_in(0, Location::RequiresFpuRegister()); | 4140 summary->set_in(0, Location::RequiresFpuRegister()); |
4301 summary->set_out(0, Location::SameAsFirstInput()); | 4141 summary->set_out(0, Location::SameAsFirstInput()); |
4302 return summary; | 4142 return summary; |
4303 } | 4143 } |
4304 | 4144 |
4305 | |
4306 void Float32x4SqrtInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4145 void Float32x4SqrtInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4307 XmmRegister left = locs()->in(0).fpu_reg(); | 4146 XmmRegister left = locs()->in(0).fpu_reg(); |
4308 | 4147 |
4309 ASSERT(locs()->out(0).fpu_reg() == left); | 4148 ASSERT(locs()->out(0).fpu_reg() == left); |
4310 | 4149 |
4311 switch (op_kind()) { | 4150 switch (op_kind()) { |
4312 case MethodRecognizer::kFloat32x4Sqrt: | 4151 case MethodRecognizer::kFloat32x4Sqrt: |
4313 __ sqrtps(left); | 4152 __ sqrtps(left); |
4314 break; | 4153 break; |
4315 case MethodRecognizer::kFloat32x4Reciprocal: | 4154 case MethodRecognizer::kFloat32x4Reciprocal: |
4316 __ reciprocalps(left); | 4155 __ reciprocalps(left); |
4317 break; | 4156 break; |
4318 case MethodRecognizer::kFloat32x4ReciprocalSqrt: | 4157 case MethodRecognizer::kFloat32x4ReciprocalSqrt: |
4319 __ rsqrtps(left); | 4158 __ rsqrtps(left); |
4320 break; | 4159 break; |
4321 default: | 4160 default: |
4322 UNREACHABLE(); | 4161 UNREACHABLE(); |
4323 } | 4162 } |
4324 } | 4163 } |
4325 | 4164 |
4326 | |
4327 LocationSummary* Float32x4ZeroArgInstr::MakeLocationSummary(Zone* zone, | 4165 LocationSummary* Float32x4ZeroArgInstr::MakeLocationSummary(Zone* zone, |
4328 bool opt) const { | 4166 bool opt) const { |
4329 const intptr_t kNumInputs = 1; | 4167 const intptr_t kNumInputs = 1; |
4330 const intptr_t kNumTemps = 0; | 4168 const intptr_t kNumTemps = 0; |
4331 LocationSummary* summary = new (zone) | 4169 LocationSummary* summary = new (zone) |
4332 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4170 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4333 summary->set_in(0, Location::RequiresFpuRegister()); | 4171 summary->set_in(0, Location::RequiresFpuRegister()); |
4334 summary->set_out(0, Location::SameAsFirstInput()); | 4172 summary->set_out(0, Location::SameAsFirstInput()); |
4335 return summary; | 4173 return summary; |
4336 } | 4174 } |
4337 | 4175 |
4338 | |
4339 void Float32x4ZeroArgInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4176 void Float32x4ZeroArgInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4340 XmmRegister left = locs()->in(0).fpu_reg(); | 4177 XmmRegister left = locs()->in(0).fpu_reg(); |
4341 | 4178 |
4342 ASSERT(locs()->out(0).fpu_reg() == left); | 4179 ASSERT(locs()->out(0).fpu_reg() == left); |
4343 switch (op_kind()) { | 4180 switch (op_kind()) { |
4344 case MethodRecognizer::kFloat32x4Negate: | 4181 case MethodRecognizer::kFloat32x4Negate: |
4345 __ negateps(left); | 4182 __ negateps(left); |
4346 break; | 4183 break; |
4347 case MethodRecognizer::kFloat32x4Absolute: | 4184 case MethodRecognizer::kFloat32x4Absolute: |
4348 __ absps(left); | 4185 __ absps(left); |
4349 break; | 4186 break; |
4350 default: | 4187 default: |
4351 UNREACHABLE(); | 4188 UNREACHABLE(); |
4352 } | 4189 } |
4353 } | 4190 } |
4354 | 4191 |
4355 | |
4356 LocationSummary* Float32x4ClampInstr::MakeLocationSummary(Zone* zone, | 4192 LocationSummary* Float32x4ClampInstr::MakeLocationSummary(Zone* zone, |
4357 bool opt) const { | 4193 bool opt) const { |
4358 const intptr_t kNumInputs = 3; | 4194 const intptr_t kNumInputs = 3; |
4359 const intptr_t kNumTemps = 0; | 4195 const intptr_t kNumTemps = 0; |
4360 LocationSummary* summary = new (zone) | 4196 LocationSummary* summary = new (zone) |
4361 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4197 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4362 summary->set_in(0, Location::RequiresFpuRegister()); | 4198 summary->set_in(0, Location::RequiresFpuRegister()); |
4363 summary->set_in(1, Location::RequiresFpuRegister()); | 4199 summary->set_in(1, Location::RequiresFpuRegister()); |
4364 summary->set_in(2, Location::RequiresFpuRegister()); | 4200 summary->set_in(2, Location::RequiresFpuRegister()); |
4365 summary->set_out(0, Location::SameAsFirstInput()); | 4201 summary->set_out(0, Location::SameAsFirstInput()); |
4366 return summary; | 4202 return summary; |
4367 } | 4203 } |
4368 | 4204 |
4369 | |
4370 void Float32x4ClampInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4205 void Float32x4ClampInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4371 XmmRegister left = locs()->in(0).fpu_reg(); | 4206 XmmRegister left = locs()->in(0).fpu_reg(); |
4372 XmmRegister lower = locs()->in(1).fpu_reg(); | 4207 XmmRegister lower = locs()->in(1).fpu_reg(); |
4373 XmmRegister upper = locs()->in(2).fpu_reg(); | 4208 XmmRegister upper = locs()->in(2).fpu_reg(); |
4374 ASSERT(locs()->out(0).fpu_reg() == left); | 4209 ASSERT(locs()->out(0).fpu_reg() == left); |
4375 __ minps(left, upper); | 4210 __ minps(left, upper); |
4376 __ maxps(left, lower); | 4211 __ maxps(left, lower); |
4377 } | 4212 } |
4378 | 4213 |
4379 | |
4380 LocationSummary* Float32x4WithInstr::MakeLocationSummary(Zone* zone, | 4214 LocationSummary* Float32x4WithInstr::MakeLocationSummary(Zone* zone, |
4381 bool opt) const { | 4215 bool opt) const { |
4382 const intptr_t kNumInputs = 2; | 4216 const intptr_t kNumInputs = 2; |
4383 const intptr_t kNumTemps = 0; | 4217 const intptr_t kNumTemps = 0; |
4384 LocationSummary* summary = new (zone) | 4218 LocationSummary* summary = new (zone) |
4385 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4219 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4386 summary->set_in(0, Location::RequiresFpuRegister()); | 4220 summary->set_in(0, Location::RequiresFpuRegister()); |
4387 summary->set_in(1, Location::RequiresFpuRegister()); | 4221 summary->set_in(1, Location::RequiresFpuRegister()); |
4388 summary->set_out(0, Location::SameAsFirstInput()); | 4222 summary->set_out(0, Location::SameAsFirstInput()); |
4389 return summary; | 4223 return summary; |
4390 } | 4224 } |
4391 | 4225 |
4392 | |
4393 void Float32x4WithInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4226 void Float32x4WithInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4394 XmmRegister replacement = locs()->in(0).fpu_reg(); | 4227 XmmRegister replacement = locs()->in(0).fpu_reg(); |
4395 XmmRegister value = locs()->in(1).fpu_reg(); | 4228 XmmRegister value = locs()->in(1).fpu_reg(); |
4396 | 4229 |
4397 ASSERT(locs()->out(0).fpu_reg() == replacement); | 4230 ASSERT(locs()->out(0).fpu_reg() == replacement); |
4398 | 4231 |
4399 switch (op_kind()) { | 4232 switch (op_kind()) { |
4400 case MethodRecognizer::kFloat32x4WithX: | 4233 case MethodRecognizer::kFloat32x4WithX: |
4401 __ cvtsd2ss(replacement, replacement); | 4234 __ cvtsd2ss(replacement, replacement); |
4402 __ subl(ESP, Immediate(16)); | 4235 __ subl(ESP, Immediate(16)); |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4439 __ movss(Address(ESP, 12), replacement); | 4272 __ movss(Address(ESP, 12), replacement); |
4440 // Move updated value into output register. | 4273 // Move updated value into output register. |
4441 __ movups(replacement, Address(ESP, 0)); | 4274 __ movups(replacement, Address(ESP, 0)); |
4442 __ addl(ESP, Immediate(16)); | 4275 __ addl(ESP, Immediate(16)); |
4443 break; | 4276 break; |
4444 default: | 4277 default: |
4445 UNREACHABLE(); | 4278 UNREACHABLE(); |
4446 } | 4279 } |
4447 } | 4280 } |
4448 | 4281 |
4449 | |
4450 LocationSummary* Float32x4ToInt32x4Instr::MakeLocationSummary(Zone* zone, | 4282 LocationSummary* Float32x4ToInt32x4Instr::MakeLocationSummary(Zone* zone, |
4451 bool opt) const { | 4283 bool opt) const { |
4452 const intptr_t kNumInputs = 1; | 4284 const intptr_t kNumInputs = 1; |
4453 const intptr_t kNumTemps = 0; | 4285 const intptr_t kNumTemps = 0; |
4454 LocationSummary* summary = new (zone) | 4286 LocationSummary* summary = new (zone) |
4455 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4287 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4456 summary->set_in(0, Location::RequiresFpuRegister()); | 4288 summary->set_in(0, Location::RequiresFpuRegister()); |
4457 summary->set_out(0, Location::SameAsFirstInput()); | 4289 summary->set_out(0, Location::SameAsFirstInput()); |
4458 return summary; | 4290 return summary; |
4459 } | 4291 } |
4460 | 4292 |
4461 | |
4462 void Float32x4ToInt32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4293 void Float32x4ToInt32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4463 // NOP. | 4294 // NOP. |
4464 } | 4295 } |
4465 | 4296 |
4466 | |
4467 LocationSummary* Simd64x2ShuffleInstr::MakeLocationSummary(Zone* zone, | 4297 LocationSummary* Simd64x2ShuffleInstr::MakeLocationSummary(Zone* zone, |
4468 bool opt) const { | 4298 bool opt) const { |
4469 const intptr_t kNumInputs = 1; | 4299 const intptr_t kNumInputs = 1; |
4470 const intptr_t kNumTemps = 0; | 4300 const intptr_t kNumTemps = 0; |
4471 LocationSummary* summary = new (zone) | 4301 LocationSummary* summary = new (zone) |
4472 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4302 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4473 summary->set_in(0, Location::RequiresFpuRegister()); | 4303 summary->set_in(0, Location::RequiresFpuRegister()); |
4474 summary->set_out(0, Location::SameAsFirstInput()); | 4304 summary->set_out(0, Location::SameAsFirstInput()); |
4475 return summary; | 4305 return summary; |
4476 } | 4306 } |
4477 | 4307 |
4478 | |
4479 void Simd64x2ShuffleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4308 void Simd64x2ShuffleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4480 XmmRegister value = locs()->in(0).fpu_reg(); | 4309 XmmRegister value = locs()->in(0).fpu_reg(); |
4481 | 4310 |
4482 ASSERT(locs()->out(0).fpu_reg() == value); | 4311 ASSERT(locs()->out(0).fpu_reg() == value); |
4483 | 4312 |
4484 switch (op_kind()) { | 4313 switch (op_kind()) { |
4485 case MethodRecognizer::kFloat64x2GetX: | 4314 case MethodRecognizer::kFloat64x2GetX: |
4486 // nop. | 4315 // nop. |
4487 break; | 4316 break; |
4488 case MethodRecognizer::kFloat64x2GetY: | 4317 case MethodRecognizer::kFloat64x2GetY: |
4489 __ shufpd(value, value, Immediate(0x33)); | 4318 __ shufpd(value, value, Immediate(0x33)); |
4490 break; | 4319 break; |
4491 default: | 4320 default: |
4492 UNREACHABLE(); | 4321 UNREACHABLE(); |
4493 } | 4322 } |
4494 } | 4323 } |
4495 | 4324 |
4496 | |
4497 LocationSummary* Float64x2ZeroInstr::MakeLocationSummary(Zone* zone, | 4325 LocationSummary* Float64x2ZeroInstr::MakeLocationSummary(Zone* zone, |
4498 bool opt) const { | 4326 bool opt) const { |
4499 const intptr_t kNumInputs = 0; | 4327 const intptr_t kNumInputs = 0; |
4500 const intptr_t kNumTemps = 0; | 4328 const intptr_t kNumTemps = 0; |
4501 LocationSummary* summary = new (zone) | 4329 LocationSummary* summary = new (zone) |
4502 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4330 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4503 summary->set_out(0, Location::RequiresFpuRegister()); | 4331 summary->set_out(0, Location::RequiresFpuRegister()); |
4504 return summary; | 4332 return summary; |
4505 } | 4333 } |
4506 | 4334 |
4507 | |
4508 void Float64x2ZeroInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4335 void Float64x2ZeroInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4509 XmmRegister value = locs()->out(0).fpu_reg(); | 4336 XmmRegister value = locs()->out(0).fpu_reg(); |
4510 __ xorpd(value, value); | 4337 __ xorpd(value, value); |
4511 } | 4338 } |
4512 | 4339 |
4513 | |
4514 LocationSummary* Float64x2SplatInstr::MakeLocationSummary(Zone* zone, | 4340 LocationSummary* Float64x2SplatInstr::MakeLocationSummary(Zone* zone, |
4515 bool opt) const { | 4341 bool opt) const { |
4516 const intptr_t kNumInputs = 1; | 4342 const intptr_t kNumInputs = 1; |
4517 const intptr_t kNumTemps = 0; | 4343 const intptr_t kNumTemps = 0; |
4518 LocationSummary* summary = new (zone) | 4344 LocationSummary* summary = new (zone) |
4519 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4345 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4520 summary->set_in(0, Location::RequiresFpuRegister()); | 4346 summary->set_in(0, Location::RequiresFpuRegister()); |
4521 summary->set_out(0, Location::SameAsFirstInput()); | 4347 summary->set_out(0, Location::SameAsFirstInput()); |
4522 return summary; | 4348 return summary; |
4523 } | 4349 } |
4524 | 4350 |
4525 | |
4526 void Float64x2SplatInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4351 void Float64x2SplatInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4527 XmmRegister value = locs()->out(0).fpu_reg(); | 4352 XmmRegister value = locs()->out(0).fpu_reg(); |
4528 __ shufpd(value, value, Immediate(0x0)); | 4353 __ shufpd(value, value, Immediate(0x0)); |
4529 } | 4354 } |
4530 | 4355 |
4531 | |
4532 LocationSummary* Float64x2ConstructorInstr::MakeLocationSummary( | 4356 LocationSummary* Float64x2ConstructorInstr::MakeLocationSummary( |
4533 Zone* zone, | 4357 Zone* zone, |
4534 bool opt) const { | 4358 bool opt) const { |
4535 const intptr_t kNumInputs = 2; | 4359 const intptr_t kNumInputs = 2; |
4536 const intptr_t kNumTemps = 0; | 4360 const intptr_t kNumTemps = 0; |
4537 LocationSummary* summary = new (zone) | 4361 LocationSummary* summary = new (zone) |
4538 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4362 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4539 summary->set_in(0, Location::RequiresFpuRegister()); | 4363 summary->set_in(0, Location::RequiresFpuRegister()); |
4540 summary->set_in(1, Location::RequiresFpuRegister()); | 4364 summary->set_in(1, Location::RequiresFpuRegister()); |
4541 summary->set_out(0, Location::SameAsFirstInput()); | 4365 summary->set_out(0, Location::SameAsFirstInput()); |
4542 return summary; | 4366 return summary; |
4543 } | 4367 } |
4544 | 4368 |
4545 | |
4546 void Float64x2ConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4369 void Float64x2ConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4547 XmmRegister v0 = locs()->in(0).fpu_reg(); | 4370 XmmRegister v0 = locs()->in(0).fpu_reg(); |
4548 XmmRegister v1 = locs()->in(1).fpu_reg(); | 4371 XmmRegister v1 = locs()->in(1).fpu_reg(); |
4549 ASSERT(v0 == locs()->out(0).fpu_reg()); | 4372 ASSERT(v0 == locs()->out(0).fpu_reg()); |
4550 // shufpd mask 0x0 results in: | 4373 // shufpd mask 0x0 results in: |
4551 // Lower 64-bits of v0 = Lower 64-bits of v0. | 4374 // Lower 64-bits of v0 = Lower 64-bits of v0. |
4552 // Upper 64-bits of v0 = Lower 64-bits of v1. | 4375 // Upper 64-bits of v0 = Lower 64-bits of v1. |
4553 __ shufpd(v0, v1, Immediate(0x0)); | 4376 __ shufpd(v0, v1, Immediate(0x0)); |
4554 } | 4377 } |
4555 | 4378 |
4556 | |
4557 LocationSummary* Float64x2ToFloat32x4Instr::MakeLocationSummary( | 4379 LocationSummary* Float64x2ToFloat32x4Instr::MakeLocationSummary( |
4558 Zone* zone, | 4380 Zone* zone, |
4559 bool opt) const { | 4381 bool opt) const { |
4560 const intptr_t kNumInputs = 1; | 4382 const intptr_t kNumInputs = 1; |
4561 const intptr_t kNumTemps = 0; | 4383 const intptr_t kNumTemps = 0; |
4562 LocationSummary* summary = new (zone) | 4384 LocationSummary* summary = new (zone) |
4563 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4385 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4564 summary->set_in(0, Location::RequiresFpuRegister()); | 4386 summary->set_in(0, Location::RequiresFpuRegister()); |
4565 summary->set_out(0, Location::SameAsFirstInput()); | 4387 summary->set_out(0, Location::SameAsFirstInput()); |
4566 return summary; | 4388 return summary; |
4567 } | 4389 } |
4568 | 4390 |
4569 | |
4570 void Float64x2ToFloat32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4391 void Float64x2ToFloat32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4571 XmmRegister value = locs()->out(0).fpu_reg(); | 4392 XmmRegister value = locs()->out(0).fpu_reg(); |
4572 __ cvtpd2ps(value, value); | 4393 __ cvtpd2ps(value, value); |
4573 } | 4394 } |
4574 | 4395 |
4575 | |
4576 LocationSummary* Float32x4ToFloat64x2Instr::MakeLocationSummary( | 4396 LocationSummary* Float32x4ToFloat64x2Instr::MakeLocationSummary( |
4577 Zone* zone, | 4397 Zone* zone, |
4578 bool opt) const { | 4398 bool opt) const { |
4579 const intptr_t kNumInputs = 1; | 4399 const intptr_t kNumInputs = 1; |
4580 const intptr_t kNumTemps = 0; | 4400 const intptr_t kNumTemps = 0; |
4581 LocationSummary* summary = new (zone) | 4401 LocationSummary* summary = new (zone) |
4582 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4402 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4583 summary->set_in(0, Location::RequiresFpuRegister()); | 4403 summary->set_in(0, Location::RequiresFpuRegister()); |
4584 summary->set_out(0, Location::SameAsFirstInput()); | 4404 summary->set_out(0, Location::SameAsFirstInput()); |
4585 return summary; | 4405 return summary; |
4586 } | 4406 } |
4587 | 4407 |
4588 | |
4589 void Float32x4ToFloat64x2Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4408 void Float32x4ToFloat64x2Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4590 XmmRegister value = locs()->out(0).fpu_reg(); | 4409 XmmRegister value = locs()->out(0).fpu_reg(); |
4591 __ cvtps2pd(value, value); | 4410 __ cvtps2pd(value, value); |
4592 } | 4411 } |
4593 | 4412 |
4594 | |
4595 LocationSummary* Float64x2ZeroArgInstr::MakeLocationSummary(Zone* zone, | 4413 LocationSummary* Float64x2ZeroArgInstr::MakeLocationSummary(Zone* zone, |
4596 bool opt) const { | 4414 bool opt) const { |
4597 const intptr_t kNumInputs = 1; | 4415 const intptr_t kNumInputs = 1; |
4598 const intptr_t kNumTemps = 0; | 4416 const intptr_t kNumTemps = 0; |
4599 LocationSummary* summary = new (zone) | 4417 LocationSummary* summary = new (zone) |
4600 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4418 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4601 summary->set_in(0, Location::RequiresFpuRegister()); | 4419 summary->set_in(0, Location::RequiresFpuRegister()); |
4602 if (representation() == kTagged) { | 4420 if (representation() == kTagged) { |
4603 ASSERT(op_kind() == MethodRecognizer::kFloat64x2GetSignMask); | 4421 ASSERT(op_kind() == MethodRecognizer::kFloat64x2GetSignMask); |
4604 summary->set_out(0, Location::RequiresRegister()); | 4422 summary->set_out(0, Location::RequiresRegister()); |
4605 } else { | 4423 } else { |
4606 ASSERT(representation() == kUnboxedFloat64x2); | 4424 ASSERT(representation() == kUnboxedFloat64x2); |
4607 summary->set_out(0, Location::SameAsFirstInput()); | 4425 summary->set_out(0, Location::SameAsFirstInput()); |
4608 } | 4426 } |
4609 return summary; | 4427 return summary; |
4610 } | 4428 } |
4611 | 4429 |
4612 | |
4613 void Float64x2ZeroArgInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4430 void Float64x2ZeroArgInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4614 XmmRegister left = locs()->in(0).fpu_reg(); | 4431 XmmRegister left = locs()->in(0).fpu_reg(); |
4615 | 4432 |
4616 ASSERT((op_kind() == MethodRecognizer::kFloat64x2GetSignMask) || | 4433 ASSERT((op_kind() == MethodRecognizer::kFloat64x2GetSignMask) || |
4617 (locs()->out(0).fpu_reg() == left)); | 4434 (locs()->out(0).fpu_reg() == left)); |
4618 | 4435 |
4619 switch (op_kind()) { | 4436 switch (op_kind()) { |
4620 case MethodRecognizer::kFloat64x2Negate: | 4437 case MethodRecognizer::kFloat64x2Negate: |
4621 __ negatepd(left); | 4438 __ negatepd(left); |
4622 break; | 4439 break; |
4623 case MethodRecognizer::kFloat64x2Abs: | 4440 case MethodRecognizer::kFloat64x2Abs: |
4624 __ abspd(left); | 4441 __ abspd(left); |
4625 break; | 4442 break; |
4626 case MethodRecognizer::kFloat64x2Sqrt: | 4443 case MethodRecognizer::kFloat64x2Sqrt: |
4627 __ sqrtpd(left); | 4444 __ sqrtpd(left); |
4628 break; | 4445 break; |
4629 case MethodRecognizer::kFloat64x2GetSignMask: | 4446 case MethodRecognizer::kFloat64x2GetSignMask: |
4630 __ movmskpd(locs()->out(0).reg(), left); | 4447 __ movmskpd(locs()->out(0).reg(), left); |
4631 __ SmiTag(locs()->out(0).reg()); | 4448 __ SmiTag(locs()->out(0).reg()); |
4632 break; | 4449 break; |
4633 default: | 4450 default: |
4634 UNREACHABLE(); | 4451 UNREACHABLE(); |
4635 } | 4452 } |
4636 } | 4453 } |
4637 | 4454 |
4638 | |
4639 LocationSummary* Float64x2OneArgInstr::MakeLocationSummary(Zone* zone, | 4455 LocationSummary* Float64x2OneArgInstr::MakeLocationSummary(Zone* zone, |
4640 bool opt) const { | 4456 bool opt) const { |
4641 const intptr_t kNumInputs = 2; | 4457 const intptr_t kNumInputs = 2; |
4642 const intptr_t kNumTemps = 0; | 4458 const intptr_t kNumTemps = 0; |
4643 LocationSummary* summary = new (zone) | 4459 LocationSummary* summary = new (zone) |
4644 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4460 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4645 summary->set_in(0, Location::RequiresFpuRegister()); | 4461 summary->set_in(0, Location::RequiresFpuRegister()); |
4646 summary->set_in(1, Location::RequiresFpuRegister()); | 4462 summary->set_in(1, Location::RequiresFpuRegister()); |
4647 summary->set_out(0, Location::SameAsFirstInput()); | 4463 summary->set_out(0, Location::SameAsFirstInput()); |
4648 return summary; | 4464 return summary; |
4649 } | 4465 } |
4650 | 4466 |
4651 | |
4652 void Float64x2OneArgInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4467 void Float64x2OneArgInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4653 XmmRegister left = locs()->in(0).fpu_reg(); | 4468 XmmRegister left = locs()->in(0).fpu_reg(); |
4654 XmmRegister right = locs()->in(1).fpu_reg(); | 4469 XmmRegister right = locs()->in(1).fpu_reg(); |
4655 ASSERT((locs()->out(0).fpu_reg() == left)); | 4470 ASSERT((locs()->out(0).fpu_reg() == left)); |
4656 | 4471 |
4657 switch (op_kind()) { | 4472 switch (op_kind()) { |
4658 case MethodRecognizer::kFloat64x2Scale: | 4473 case MethodRecognizer::kFloat64x2Scale: |
4659 __ shufpd(right, right, Immediate(0x00)); | 4474 __ shufpd(right, right, Immediate(0x00)); |
4660 __ mulpd(left, right); | 4475 __ mulpd(left, right); |
4661 break; | 4476 break; |
(...skipping 21 matching lines...) Expand all Loading... |
4683 __ minpd(left, right); | 4498 __ minpd(left, right); |
4684 break; | 4499 break; |
4685 case MethodRecognizer::kFloat64x2Max: | 4500 case MethodRecognizer::kFloat64x2Max: |
4686 __ maxpd(left, right); | 4501 __ maxpd(left, right); |
4687 break; | 4502 break; |
4688 default: | 4503 default: |
4689 UNREACHABLE(); | 4504 UNREACHABLE(); |
4690 } | 4505 } |
4691 } | 4506 } |
4692 | 4507 |
4693 | |
4694 LocationSummary* Int32x4ConstructorInstr::MakeLocationSummary(Zone* zone, | 4508 LocationSummary* Int32x4ConstructorInstr::MakeLocationSummary(Zone* zone, |
4695 bool opt) const { | 4509 bool opt) const { |
4696 const intptr_t kNumInputs = 4; | 4510 const intptr_t kNumInputs = 4; |
4697 const intptr_t kNumTemps = 0; | 4511 const intptr_t kNumTemps = 0; |
4698 LocationSummary* summary = new (zone) | 4512 LocationSummary* summary = new (zone) |
4699 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4513 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4700 summary->set_in(0, Location::RequiresRegister()); | 4514 summary->set_in(0, Location::RequiresRegister()); |
4701 summary->set_in(1, Location::RequiresRegister()); | 4515 summary->set_in(1, Location::RequiresRegister()); |
4702 summary->set_in(2, Location::RequiresRegister()); | 4516 summary->set_in(2, Location::RequiresRegister()); |
4703 summary->set_in(3, Location::RequiresRegister()); | 4517 summary->set_in(3, Location::RequiresRegister()); |
4704 summary->set_out(0, Location::RequiresFpuRegister()); | 4518 summary->set_out(0, Location::RequiresFpuRegister()); |
4705 return summary; | 4519 return summary; |
4706 } | 4520 } |
4707 | 4521 |
4708 | |
4709 void Int32x4ConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4522 void Int32x4ConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4710 Register v0 = locs()->in(0).reg(); | 4523 Register v0 = locs()->in(0).reg(); |
4711 Register v1 = locs()->in(1).reg(); | 4524 Register v1 = locs()->in(1).reg(); |
4712 Register v2 = locs()->in(2).reg(); | 4525 Register v2 = locs()->in(2).reg(); |
4713 Register v3 = locs()->in(3).reg(); | 4526 Register v3 = locs()->in(3).reg(); |
4714 XmmRegister result = locs()->out(0).fpu_reg(); | 4527 XmmRegister result = locs()->out(0).fpu_reg(); |
4715 __ subl(ESP, Immediate(4 * kInt32Size)); | 4528 __ subl(ESP, Immediate(4 * kInt32Size)); |
4716 __ movl(Address(ESP, 0 * kInt32Size), v0); | 4529 __ movl(Address(ESP, 0 * kInt32Size), v0); |
4717 __ movl(Address(ESP, 1 * kInt32Size), v1); | 4530 __ movl(Address(ESP, 1 * kInt32Size), v1); |
4718 __ movl(Address(ESP, 2 * kInt32Size), v2); | 4531 __ movl(Address(ESP, 2 * kInt32Size), v2); |
4719 __ movl(Address(ESP, 3 * kInt32Size), v3); | 4532 __ movl(Address(ESP, 3 * kInt32Size), v3); |
4720 __ movups(result, Address(ESP, 0)); | 4533 __ movups(result, Address(ESP, 0)); |
4721 __ addl(ESP, Immediate(4 * kInt32Size)); | 4534 __ addl(ESP, Immediate(4 * kInt32Size)); |
4722 } | 4535 } |
4723 | 4536 |
4724 | |
4725 LocationSummary* Int32x4BoolConstructorInstr::MakeLocationSummary( | 4537 LocationSummary* Int32x4BoolConstructorInstr::MakeLocationSummary( |
4726 Zone* zone, | 4538 Zone* zone, |
4727 bool opt) const { | 4539 bool opt) const { |
4728 const intptr_t kNumInputs = 4; | 4540 const intptr_t kNumInputs = 4; |
4729 const intptr_t kNumTemps = 0; | 4541 const intptr_t kNumTemps = 0; |
4730 LocationSummary* summary = new (zone) | 4542 LocationSummary* summary = new (zone) |
4731 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4543 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4732 summary->set_in(0, Location::RequiresRegister()); | 4544 summary->set_in(0, Location::RequiresRegister()); |
4733 summary->set_in(1, Location::RequiresRegister()); | 4545 summary->set_in(1, Location::RequiresRegister()); |
4734 summary->set_in(2, Location::RequiresRegister()); | 4546 summary->set_in(2, Location::RequiresRegister()); |
4735 summary->set_in(3, Location::RequiresRegister()); | 4547 summary->set_in(3, Location::RequiresRegister()); |
4736 summary->set_out(0, Location::RequiresFpuRegister()); | 4548 summary->set_out(0, Location::RequiresFpuRegister()); |
4737 return summary; | 4549 return summary; |
4738 } | 4550 } |
4739 | 4551 |
4740 | |
4741 void Int32x4BoolConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4552 void Int32x4BoolConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4742 Register v0 = locs()->in(0).reg(); | 4553 Register v0 = locs()->in(0).reg(); |
4743 Register v1 = locs()->in(1).reg(); | 4554 Register v1 = locs()->in(1).reg(); |
4744 Register v2 = locs()->in(2).reg(); | 4555 Register v2 = locs()->in(2).reg(); |
4745 Register v3 = locs()->in(3).reg(); | 4556 Register v3 = locs()->in(3).reg(); |
4746 XmmRegister result = locs()->out(0).fpu_reg(); | 4557 XmmRegister result = locs()->out(0).fpu_reg(); |
4747 Label x_false, x_done; | 4558 Label x_false, x_done; |
4748 Label y_false, y_done; | 4559 Label y_false, y_done; |
4749 Label z_false, z_done; | 4560 Label z_false, z_done; |
4750 Label w_false, w_done; | 4561 Label w_false, w_done; |
(...skipping 27 matching lines...) Expand all Loading... |
4778 __ movl(Address(ESP, 12), Immediate(0xFFFFFFFF)); | 4589 __ movl(Address(ESP, 12), Immediate(0xFFFFFFFF)); |
4779 __ jmp(&w_done); | 4590 __ jmp(&w_done); |
4780 __ Bind(&w_false); | 4591 __ Bind(&w_false); |
4781 __ movl(Address(ESP, 12), Immediate(0x0)); | 4592 __ movl(Address(ESP, 12), Immediate(0x0)); |
4782 __ Bind(&w_done); | 4593 __ Bind(&w_done); |
4783 | 4594 |
4784 __ movups(result, Address(ESP, 0)); | 4595 __ movups(result, Address(ESP, 0)); |
4785 __ addl(ESP, Immediate(16)); | 4596 __ addl(ESP, Immediate(16)); |
4786 } | 4597 } |
4787 | 4598 |
4788 | |
4789 LocationSummary* Int32x4GetFlagInstr::MakeLocationSummary(Zone* zone, | 4599 LocationSummary* Int32x4GetFlagInstr::MakeLocationSummary(Zone* zone, |
4790 bool opt) const { | 4600 bool opt) const { |
4791 const intptr_t kNumInputs = 1; | 4601 const intptr_t kNumInputs = 1; |
4792 const intptr_t kNumTemps = 0; | 4602 const intptr_t kNumTemps = 0; |
4793 LocationSummary* summary = new (zone) | 4603 LocationSummary* summary = new (zone) |
4794 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4604 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4795 summary->set_in(0, Location::RequiresFpuRegister()); | 4605 summary->set_in(0, Location::RequiresFpuRegister()); |
4796 summary->set_out(0, Location::RequiresRegister()); | 4606 summary->set_out(0, Location::RequiresRegister()); |
4797 return summary; | 4607 return summary; |
4798 } | 4608 } |
4799 | 4609 |
4800 | |
4801 void Int32x4GetFlagInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4610 void Int32x4GetFlagInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4802 XmmRegister value = locs()->in(0).fpu_reg(); | 4611 XmmRegister value = locs()->in(0).fpu_reg(); |
4803 Register result = locs()->out(0).reg(); | 4612 Register result = locs()->out(0).reg(); |
4804 Label done; | 4613 Label done; |
4805 Label non_zero; | 4614 Label non_zero; |
4806 __ subl(ESP, Immediate(16)); | 4615 __ subl(ESP, Immediate(16)); |
4807 // Move value to stack. | 4616 // Move value to stack. |
4808 __ movups(Address(ESP, 0), value); | 4617 __ movups(Address(ESP, 0), value); |
4809 switch (op_kind()) { | 4618 switch (op_kind()) { |
4810 case MethodRecognizer::kInt32x4GetFlagX: | 4619 case MethodRecognizer::kInt32x4GetFlagX: |
(...skipping 14 matching lines...) Expand all Loading... |
4825 __ addl(ESP, Immediate(16)); | 4634 __ addl(ESP, Immediate(16)); |
4826 __ testl(result, result); | 4635 __ testl(result, result); |
4827 __ j(NOT_ZERO, &non_zero, Assembler::kNearJump); | 4636 __ j(NOT_ZERO, &non_zero, Assembler::kNearJump); |
4828 __ LoadObject(result, Bool::False()); | 4637 __ LoadObject(result, Bool::False()); |
4829 __ jmp(&done); | 4638 __ jmp(&done); |
4830 __ Bind(&non_zero); | 4639 __ Bind(&non_zero); |
4831 __ LoadObject(result, Bool::True()); | 4640 __ LoadObject(result, Bool::True()); |
4832 __ Bind(&done); | 4641 __ Bind(&done); |
4833 } | 4642 } |
4834 | 4643 |
4835 | |
4836 LocationSummary* Int32x4SelectInstr::MakeLocationSummary(Zone* zone, | 4644 LocationSummary* Int32x4SelectInstr::MakeLocationSummary(Zone* zone, |
4837 bool opt) const { | 4645 bool opt) const { |
4838 const intptr_t kNumInputs = 3; | 4646 const intptr_t kNumInputs = 3; |
4839 const intptr_t kNumTemps = 1; | 4647 const intptr_t kNumTemps = 1; |
4840 LocationSummary* summary = new (zone) | 4648 LocationSummary* summary = new (zone) |
4841 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4649 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4842 summary->set_in(0, Location::RequiresFpuRegister()); | 4650 summary->set_in(0, Location::RequiresFpuRegister()); |
4843 summary->set_in(1, Location::RequiresFpuRegister()); | 4651 summary->set_in(1, Location::RequiresFpuRegister()); |
4844 summary->set_in(2, Location::RequiresFpuRegister()); | 4652 summary->set_in(2, Location::RequiresFpuRegister()); |
4845 summary->set_temp(0, Location::RequiresFpuRegister()); | 4653 summary->set_temp(0, Location::RequiresFpuRegister()); |
4846 summary->set_out(0, Location::SameAsFirstInput()); | 4654 summary->set_out(0, Location::SameAsFirstInput()); |
4847 return summary; | 4655 return summary; |
4848 } | 4656 } |
4849 | 4657 |
4850 | |
4851 void Int32x4SelectInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4658 void Int32x4SelectInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4852 XmmRegister mask = locs()->in(0).fpu_reg(); | 4659 XmmRegister mask = locs()->in(0).fpu_reg(); |
4853 XmmRegister trueValue = locs()->in(1).fpu_reg(); | 4660 XmmRegister trueValue = locs()->in(1).fpu_reg(); |
4854 XmmRegister falseValue = locs()->in(2).fpu_reg(); | 4661 XmmRegister falseValue = locs()->in(2).fpu_reg(); |
4855 XmmRegister out = locs()->out(0).fpu_reg(); | 4662 XmmRegister out = locs()->out(0).fpu_reg(); |
4856 XmmRegister temp = locs()->temp(0).fpu_reg(); | 4663 XmmRegister temp = locs()->temp(0).fpu_reg(); |
4857 ASSERT(out == mask); | 4664 ASSERT(out == mask); |
4858 // Copy mask. | 4665 // Copy mask. |
4859 __ movaps(temp, mask); | 4666 __ movaps(temp, mask); |
4860 // Invert it. | 4667 // Invert it. |
4861 __ notps(temp); | 4668 __ notps(temp); |
4862 // mask = mask & trueValue. | 4669 // mask = mask & trueValue. |
4863 __ andps(mask, trueValue); | 4670 __ andps(mask, trueValue); |
4864 // temp = temp & falseValue. | 4671 // temp = temp & falseValue. |
4865 __ andps(temp, falseValue); | 4672 __ andps(temp, falseValue); |
4866 // out = mask | temp. | 4673 // out = mask | temp. |
4867 __ orps(mask, temp); | 4674 __ orps(mask, temp); |
4868 } | 4675 } |
4869 | 4676 |
4870 | |
4871 LocationSummary* Int32x4SetFlagInstr::MakeLocationSummary(Zone* zone, | 4677 LocationSummary* Int32x4SetFlagInstr::MakeLocationSummary(Zone* zone, |
4872 bool opt) const { | 4678 bool opt) const { |
4873 const intptr_t kNumInputs = 2; | 4679 const intptr_t kNumInputs = 2; |
4874 const intptr_t kNumTemps = 0; | 4680 const intptr_t kNumTemps = 0; |
4875 LocationSummary* summary = new (zone) | 4681 LocationSummary* summary = new (zone) |
4876 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4682 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4877 summary->set_in(0, Location::RequiresFpuRegister()); | 4683 summary->set_in(0, Location::RequiresFpuRegister()); |
4878 summary->set_in(1, Location::RequiresRegister()); | 4684 summary->set_in(1, Location::RequiresRegister()); |
4879 summary->set_out(0, Location::SameAsFirstInput()); | 4685 summary->set_out(0, Location::SameAsFirstInput()); |
4880 return summary; | 4686 return summary; |
4881 } | 4687 } |
4882 | 4688 |
4883 | |
4884 void Int32x4SetFlagInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4689 void Int32x4SetFlagInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4885 XmmRegister mask = locs()->in(0).fpu_reg(); | 4690 XmmRegister mask = locs()->in(0).fpu_reg(); |
4886 Register flag = locs()->in(1).reg(); | 4691 Register flag = locs()->in(1).reg(); |
4887 ASSERT(mask == locs()->out(0).fpu_reg()); | 4692 ASSERT(mask == locs()->out(0).fpu_reg()); |
4888 __ subl(ESP, Immediate(16)); | 4693 __ subl(ESP, Immediate(16)); |
4889 // Copy mask to stack. | 4694 // Copy mask to stack. |
4890 __ movups(Address(ESP, 0), mask); | 4695 __ movups(Address(ESP, 0), mask); |
4891 Label falsePath, exitPath; | 4696 Label falsePath, exitPath; |
4892 __ CompareObject(flag, Bool::True()); | 4697 __ CompareObject(flag, Bool::True()); |
4893 __ j(NOT_EQUAL, &falsePath); | 4698 __ j(NOT_EQUAL, &falsePath); |
(...skipping 24 matching lines...) Expand all Loading... |
4918 break; | 4723 break; |
4919 default: | 4724 default: |
4920 UNREACHABLE(); | 4725 UNREACHABLE(); |
4921 } | 4726 } |
4922 __ Bind(&exitPath); | 4727 __ Bind(&exitPath); |
4923 // Copy mask back to register. | 4728 // Copy mask back to register. |
4924 __ movups(mask, Address(ESP, 0)); | 4729 __ movups(mask, Address(ESP, 0)); |
4925 __ addl(ESP, Immediate(16)); | 4730 __ addl(ESP, Immediate(16)); |
4926 } | 4731 } |
4927 | 4732 |
4928 | |
4929 LocationSummary* Int32x4ToFloat32x4Instr::MakeLocationSummary(Zone* zone, | 4733 LocationSummary* Int32x4ToFloat32x4Instr::MakeLocationSummary(Zone* zone, |
4930 bool opt) const { | 4734 bool opt) const { |
4931 const intptr_t kNumInputs = 1; | 4735 const intptr_t kNumInputs = 1; |
4932 const intptr_t kNumTemps = 0; | 4736 const intptr_t kNumTemps = 0; |
4933 LocationSummary* summary = new (zone) | 4737 LocationSummary* summary = new (zone) |
4934 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4738 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4935 summary->set_in(0, Location::RequiresFpuRegister()); | 4739 summary->set_in(0, Location::RequiresFpuRegister()); |
4936 summary->set_out(0, Location::SameAsFirstInput()); | 4740 summary->set_out(0, Location::SameAsFirstInput()); |
4937 return summary; | 4741 return summary; |
4938 } | 4742 } |
4939 | 4743 |
4940 | |
4941 void Int32x4ToFloat32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4744 void Int32x4ToFloat32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4942 // NOP. | 4745 // NOP. |
4943 } | 4746 } |
4944 | 4747 |
4945 | |
4946 LocationSummary* BinaryInt32x4OpInstr::MakeLocationSummary(Zone* zone, | 4748 LocationSummary* BinaryInt32x4OpInstr::MakeLocationSummary(Zone* zone, |
4947 bool opt) const { | 4749 bool opt) const { |
4948 const intptr_t kNumInputs = 2; | 4750 const intptr_t kNumInputs = 2; |
4949 const intptr_t kNumTemps = 0; | 4751 const intptr_t kNumTemps = 0; |
4950 LocationSummary* summary = new (zone) | 4752 LocationSummary* summary = new (zone) |
4951 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4753 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4952 summary->set_in(0, Location::RequiresFpuRegister()); | 4754 summary->set_in(0, Location::RequiresFpuRegister()); |
4953 summary->set_in(1, Location::RequiresFpuRegister()); | 4755 summary->set_in(1, Location::RequiresFpuRegister()); |
4954 summary->set_out(0, Location::SameAsFirstInput()); | 4756 summary->set_out(0, Location::SameAsFirstInput()); |
4955 return summary; | 4757 return summary; |
4956 } | 4758 } |
4957 | 4759 |
4958 | |
4959 void BinaryInt32x4OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4760 void BinaryInt32x4OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4960 XmmRegister left = locs()->in(0).fpu_reg(); | 4761 XmmRegister left = locs()->in(0).fpu_reg(); |
4961 XmmRegister right = locs()->in(1).fpu_reg(); | 4762 XmmRegister right = locs()->in(1).fpu_reg(); |
4962 ASSERT(left == locs()->out(0).fpu_reg()); | 4763 ASSERT(left == locs()->out(0).fpu_reg()); |
4963 switch (op_kind()) { | 4764 switch (op_kind()) { |
4964 case Token::kBIT_AND: { | 4765 case Token::kBIT_AND: { |
4965 __ andps(left, right); | 4766 __ andps(left, right); |
4966 break; | 4767 break; |
4967 } | 4768 } |
4968 case Token::kBIT_OR: { | 4769 case Token::kBIT_OR: { |
4969 __ orps(left, right); | 4770 __ orps(left, right); |
4970 break; | 4771 break; |
4971 } | 4772 } |
4972 case Token::kBIT_XOR: { | 4773 case Token::kBIT_XOR: { |
4973 __ xorps(left, right); | 4774 __ xorps(left, right); |
4974 break; | 4775 break; |
4975 } | 4776 } |
4976 case Token::kADD: | 4777 case Token::kADD: |
4977 __ addpl(left, right); | 4778 __ addpl(left, right); |
4978 break; | 4779 break; |
4979 case Token::kSUB: | 4780 case Token::kSUB: |
4980 __ subpl(left, right); | 4781 __ subpl(left, right); |
4981 break; | 4782 break; |
4982 default: | 4783 default: |
4983 UNREACHABLE(); | 4784 UNREACHABLE(); |
4984 } | 4785 } |
4985 } | 4786 } |
4986 | 4787 |
4987 | |
4988 LocationSummary* MathUnaryInstr::MakeLocationSummary(Zone* zone, | 4788 LocationSummary* MathUnaryInstr::MakeLocationSummary(Zone* zone, |
4989 bool opt) const { | 4789 bool opt) const { |
4990 ASSERT((kind() == MathUnaryInstr::kSqrt) || | 4790 ASSERT((kind() == MathUnaryInstr::kSqrt) || |
4991 (kind() == MathUnaryInstr::kDoubleSquare)); | 4791 (kind() == MathUnaryInstr::kDoubleSquare)); |
4992 const intptr_t kNumInputs = 1; | 4792 const intptr_t kNumInputs = 1; |
4993 const intptr_t kNumTemps = 0; | 4793 const intptr_t kNumTemps = 0; |
4994 LocationSummary* summary = new (zone) | 4794 LocationSummary* summary = new (zone) |
4995 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4795 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4996 summary->set_in(0, Location::RequiresFpuRegister()); | 4796 summary->set_in(0, Location::RequiresFpuRegister()); |
4997 if (kind() == MathUnaryInstr::kDoubleSquare) { | 4797 if (kind() == MathUnaryInstr::kDoubleSquare) { |
4998 summary->set_out(0, Location::SameAsFirstInput()); | 4798 summary->set_out(0, Location::SameAsFirstInput()); |
4999 } else { | 4799 } else { |
5000 summary->set_out(0, Location::RequiresFpuRegister()); | 4800 summary->set_out(0, Location::RequiresFpuRegister()); |
5001 } | 4801 } |
5002 return summary; | 4802 return summary; |
5003 } | 4803 } |
5004 | 4804 |
5005 | |
5006 void MathUnaryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4805 void MathUnaryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5007 if (kind() == MathUnaryInstr::kSqrt) { | 4806 if (kind() == MathUnaryInstr::kSqrt) { |
5008 __ sqrtsd(locs()->out(0).fpu_reg(), locs()->in(0).fpu_reg()); | 4807 __ sqrtsd(locs()->out(0).fpu_reg(), locs()->in(0).fpu_reg()); |
5009 } else if (kind() == MathUnaryInstr::kDoubleSquare) { | 4808 } else if (kind() == MathUnaryInstr::kDoubleSquare) { |
5010 XmmRegister value_reg = locs()->in(0).fpu_reg(); | 4809 XmmRegister value_reg = locs()->in(0).fpu_reg(); |
5011 __ mulsd(value_reg, value_reg); | 4810 __ mulsd(value_reg, value_reg); |
5012 ASSERT(value_reg == locs()->out(0).fpu_reg()); | 4811 ASSERT(value_reg == locs()->out(0).fpu_reg()); |
5013 } else { | 4812 } else { |
5014 UNREACHABLE(); | 4813 UNREACHABLE(); |
5015 } | 4814 } |
5016 } | 4815 } |
5017 | 4816 |
5018 | |
5019 LocationSummary* CaseInsensitiveCompareUC16Instr::MakeLocationSummary( | 4817 LocationSummary* CaseInsensitiveCompareUC16Instr::MakeLocationSummary( |
5020 Zone* zone, | 4818 Zone* zone, |
5021 bool opt) const { | 4819 bool opt) const { |
5022 const intptr_t kNumTemps = 0; | 4820 const intptr_t kNumTemps = 0; |
5023 LocationSummary* summary = new (zone) | 4821 LocationSummary* summary = new (zone) |
5024 LocationSummary(zone, InputCount(), kNumTemps, LocationSummary::kCall); | 4822 LocationSummary(zone, InputCount(), kNumTemps, LocationSummary::kCall); |
5025 summary->set_in(0, Location::RegisterLocation(EAX)); | 4823 summary->set_in(0, Location::RegisterLocation(EAX)); |
5026 summary->set_in(1, Location::RegisterLocation(ECX)); | 4824 summary->set_in(1, Location::RegisterLocation(ECX)); |
5027 summary->set_in(2, Location::RegisterLocation(EDX)); | 4825 summary->set_in(2, Location::RegisterLocation(EDX)); |
5028 summary->set_in(3, Location::RegisterLocation(EBX)); | 4826 summary->set_in(3, Location::RegisterLocation(EBX)); |
5029 summary->set_out(0, Location::RegisterLocation(EAX)); | 4827 summary->set_out(0, Location::RegisterLocation(EAX)); |
5030 return summary; | 4828 return summary; |
5031 } | 4829 } |
5032 | 4830 |
5033 | |
5034 void CaseInsensitiveCompareUC16Instr::EmitNativeCode( | 4831 void CaseInsensitiveCompareUC16Instr::EmitNativeCode( |
5035 FlowGraphCompiler* compiler) { | 4832 FlowGraphCompiler* compiler) { |
5036 // Save ESP. EDI is chosen because it is callee saved so we do not need to | 4833 // Save ESP. EDI is chosen because it is callee saved so we do not need to |
5037 // back it up before calling into the runtime. | 4834 // back it up before calling into the runtime. |
5038 static const Register kSavedSPReg = EDI; | 4835 static const Register kSavedSPReg = EDI; |
5039 __ movl(kSavedSPReg, ESP); | 4836 __ movl(kSavedSPReg, ESP); |
5040 __ ReserveAlignedFrameSpace(kWordSize * TargetFunction().argument_count()); | 4837 __ ReserveAlignedFrameSpace(kWordSize * TargetFunction().argument_count()); |
5041 | 4838 |
5042 __ movl(Address(ESP, +0 * kWordSize), locs()->in(0).reg()); | 4839 __ movl(Address(ESP, +0 * kWordSize), locs()->in(0).reg()); |
5043 __ movl(Address(ESP, +1 * kWordSize), locs()->in(1).reg()); | 4840 __ movl(Address(ESP, +1 * kWordSize), locs()->in(1).reg()); |
5044 __ movl(Address(ESP, +2 * kWordSize), locs()->in(2).reg()); | 4841 __ movl(Address(ESP, +2 * kWordSize), locs()->in(2).reg()); |
5045 __ movl(Address(ESP, +3 * kWordSize), locs()->in(3).reg()); | 4842 __ movl(Address(ESP, +3 * kWordSize), locs()->in(3).reg()); |
5046 | 4843 |
5047 // Call the function. | 4844 // Call the function. |
5048 __ CallRuntime(TargetFunction(), TargetFunction().argument_count()); | 4845 __ CallRuntime(TargetFunction(), TargetFunction().argument_count()); |
5049 | 4846 |
5050 // Restore ESP. | 4847 // Restore ESP. |
5051 __ movl(ESP, kSavedSPReg); | 4848 __ movl(ESP, kSavedSPReg); |
5052 } | 4849 } |
5053 | 4850 |
5054 | |
5055 LocationSummary* MathMinMaxInstr::MakeLocationSummary(Zone* zone, | 4851 LocationSummary* MathMinMaxInstr::MakeLocationSummary(Zone* zone, |
5056 bool opt) const { | 4852 bool opt) const { |
5057 if (result_cid() == kDoubleCid) { | 4853 if (result_cid() == kDoubleCid) { |
5058 const intptr_t kNumInputs = 2; | 4854 const intptr_t kNumInputs = 2; |
5059 const intptr_t kNumTemps = 1; | 4855 const intptr_t kNumTemps = 1; |
5060 LocationSummary* summary = new (zone) | 4856 LocationSummary* summary = new (zone) |
5061 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4857 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5062 summary->set_in(0, Location::RequiresFpuRegister()); | 4858 summary->set_in(0, Location::RequiresFpuRegister()); |
5063 summary->set_in(1, Location::RequiresFpuRegister()); | 4859 summary->set_in(1, Location::RequiresFpuRegister()); |
5064 // Reuse the left register so that code can be made shorter. | 4860 // Reuse the left register so that code can be made shorter. |
5065 summary->set_out(0, Location::SameAsFirstInput()); | 4861 summary->set_out(0, Location::SameAsFirstInput()); |
5066 summary->set_temp(0, Location::RequiresRegister()); | 4862 summary->set_temp(0, Location::RequiresRegister()); |
5067 return summary; | 4863 return summary; |
5068 } | 4864 } |
5069 | 4865 |
5070 ASSERT(result_cid() == kSmiCid); | 4866 ASSERT(result_cid() == kSmiCid); |
5071 const intptr_t kNumInputs = 2; | 4867 const intptr_t kNumInputs = 2; |
5072 const intptr_t kNumTemps = 0; | 4868 const intptr_t kNumTemps = 0; |
5073 LocationSummary* summary = new (zone) | 4869 LocationSummary* summary = new (zone) |
5074 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4870 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5075 summary->set_in(0, Location::RequiresRegister()); | 4871 summary->set_in(0, Location::RequiresRegister()); |
5076 summary->set_in(1, Location::RequiresRegister()); | 4872 summary->set_in(1, Location::RequiresRegister()); |
5077 // Reuse the left register so that code can be made shorter. | 4873 // Reuse the left register so that code can be made shorter. |
5078 summary->set_out(0, Location::SameAsFirstInput()); | 4874 summary->set_out(0, Location::SameAsFirstInput()); |
5079 return summary; | 4875 return summary; |
5080 } | 4876 } |
5081 | 4877 |
5082 | |
5083 void MathMinMaxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4878 void MathMinMaxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5084 ASSERT((op_kind() == MethodRecognizer::kMathMin) || | 4879 ASSERT((op_kind() == MethodRecognizer::kMathMin) || |
5085 (op_kind() == MethodRecognizer::kMathMax)); | 4880 (op_kind() == MethodRecognizer::kMathMax)); |
5086 const intptr_t is_min = (op_kind() == MethodRecognizer::kMathMin); | 4881 const intptr_t is_min = (op_kind() == MethodRecognizer::kMathMin); |
5087 if (result_cid() == kDoubleCid) { | 4882 if (result_cid() == kDoubleCid) { |
5088 Label done, returns_nan, are_equal; | 4883 Label done, returns_nan, are_equal; |
5089 XmmRegister left = locs()->in(0).fpu_reg(); | 4884 XmmRegister left = locs()->in(0).fpu_reg(); |
5090 XmmRegister right = locs()->in(1).fpu_reg(); | 4885 XmmRegister right = locs()->in(1).fpu_reg(); |
5091 XmmRegister result = locs()->out(0).fpu_reg(); | 4886 XmmRegister result = locs()->out(0).fpu_reg(); |
5092 Register temp = locs()->temp(0).reg(); | 4887 Register temp = locs()->temp(0).reg(); |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5133 Register result = locs()->out(0).reg(); | 4928 Register result = locs()->out(0).reg(); |
5134 __ cmpl(left, right); | 4929 __ cmpl(left, right); |
5135 ASSERT(result == left); | 4930 ASSERT(result == left); |
5136 if (is_min) { | 4931 if (is_min) { |
5137 __ cmovgel(result, right); | 4932 __ cmovgel(result, right); |
5138 } else { | 4933 } else { |
5139 __ cmovlessl(result, right); | 4934 __ cmovlessl(result, right); |
5140 } | 4935 } |
5141 } | 4936 } |
5142 | 4937 |
5143 | |
5144 LocationSummary* UnarySmiOpInstr::MakeLocationSummary(Zone* zone, | 4938 LocationSummary* UnarySmiOpInstr::MakeLocationSummary(Zone* zone, |
5145 bool opt) const { | 4939 bool opt) const { |
5146 const intptr_t kNumInputs = 1; | 4940 const intptr_t kNumInputs = 1; |
5147 return LocationSummary::Make(zone, kNumInputs, Location::SameAsFirstInput(), | 4941 return LocationSummary::Make(zone, kNumInputs, Location::SameAsFirstInput(), |
5148 LocationSummary::kNoCall); | 4942 LocationSummary::kNoCall); |
5149 } | 4943 } |
5150 | 4944 |
5151 | |
5152 void UnarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4945 void UnarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5153 Register value = locs()->in(0).reg(); | 4946 Register value = locs()->in(0).reg(); |
5154 ASSERT(value == locs()->out(0).reg()); | 4947 ASSERT(value == locs()->out(0).reg()); |
5155 switch (op_kind()) { | 4948 switch (op_kind()) { |
5156 case Token::kNEGATE: { | 4949 case Token::kNEGATE: { |
5157 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnaryOp); | 4950 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnaryOp); |
5158 __ negl(value); | 4951 __ negl(value); |
5159 __ j(OVERFLOW, deopt); | 4952 __ j(OVERFLOW, deopt); |
5160 break; | 4953 break; |
5161 } | 4954 } |
5162 case Token::kBIT_NOT: | 4955 case Token::kBIT_NOT: |
5163 __ notl(value); | 4956 __ notl(value); |
5164 __ andl(value, Immediate(~kSmiTagMask)); // Remove inverted smi-tag. | 4957 __ andl(value, Immediate(~kSmiTagMask)); // Remove inverted smi-tag. |
5165 break; | 4958 break; |
5166 default: | 4959 default: |
5167 UNREACHABLE(); | 4960 UNREACHABLE(); |
5168 } | 4961 } |
5169 } | 4962 } |
5170 | 4963 |
5171 | |
5172 LocationSummary* UnaryDoubleOpInstr::MakeLocationSummary(Zone* zone, | 4964 LocationSummary* UnaryDoubleOpInstr::MakeLocationSummary(Zone* zone, |
5173 bool opt) const { | 4965 bool opt) const { |
5174 const intptr_t kNumInputs = 1; | 4966 const intptr_t kNumInputs = 1; |
5175 const intptr_t kNumTemps = 0; | 4967 const intptr_t kNumTemps = 0; |
5176 LocationSummary* summary = new (zone) | 4968 LocationSummary* summary = new (zone) |
5177 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4969 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5178 summary->set_in(0, Location::RequiresFpuRegister()); | 4970 summary->set_in(0, Location::RequiresFpuRegister()); |
5179 summary->set_out(0, Location::SameAsFirstInput()); | 4971 summary->set_out(0, Location::SameAsFirstInput()); |
5180 return summary; | 4972 return summary; |
5181 } | 4973 } |
5182 | 4974 |
5183 | |
5184 void UnaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4975 void UnaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5185 XmmRegister value = locs()->in(0).fpu_reg(); | 4976 XmmRegister value = locs()->in(0).fpu_reg(); |
5186 ASSERT(locs()->out(0).fpu_reg() == value); | 4977 ASSERT(locs()->out(0).fpu_reg() == value); |
5187 __ DoubleNegate(value); | 4978 __ DoubleNegate(value); |
5188 } | 4979 } |
5189 | 4980 |
5190 | |
5191 LocationSummary* Int32ToDoubleInstr::MakeLocationSummary(Zone* zone, | 4981 LocationSummary* Int32ToDoubleInstr::MakeLocationSummary(Zone* zone, |
5192 bool opt) const { | 4982 bool opt) const { |
5193 const intptr_t kNumInputs = 1; | 4983 const intptr_t kNumInputs = 1; |
5194 const intptr_t kNumTemps = 0; | 4984 const intptr_t kNumTemps = 0; |
5195 LocationSummary* result = new (zone) | 4985 LocationSummary* result = new (zone) |
5196 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4986 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5197 result->set_in(0, Location::RequiresRegister()); | 4987 result->set_in(0, Location::RequiresRegister()); |
5198 result->set_out(0, Location::RequiresFpuRegister()); | 4988 result->set_out(0, Location::RequiresFpuRegister()); |
5199 return result; | 4989 return result; |
5200 } | 4990 } |
5201 | 4991 |
5202 | |
5203 void Int32ToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4992 void Int32ToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5204 Register value = locs()->in(0).reg(); | 4993 Register value = locs()->in(0).reg(); |
5205 FpuRegister result = locs()->out(0).fpu_reg(); | 4994 FpuRegister result = locs()->out(0).fpu_reg(); |
5206 __ cvtsi2sd(result, value); | 4995 __ cvtsi2sd(result, value); |
5207 } | 4996 } |
5208 | 4997 |
5209 | |
5210 LocationSummary* SmiToDoubleInstr::MakeLocationSummary(Zone* zone, | 4998 LocationSummary* SmiToDoubleInstr::MakeLocationSummary(Zone* zone, |
5211 bool opt) const { | 4999 bool opt) const { |
5212 const intptr_t kNumInputs = 1; | 5000 const intptr_t kNumInputs = 1; |
5213 const intptr_t kNumTemps = 0; | 5001 const intptr_t kNumTemps = 0; |
5214 LocationSummary* result = new (zone) | 5002 LocationSummary* result = new (zone) |
5215 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5003 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5216 result->set_in(0, Location::WritableRegister()); | 5004 result->set_in(0, Location::WritableRegister()); |
5217 result->set_out(0, Location::RequiresFpuRegister()); | 5005 result->set_out(0, Location::RequiresFpuRegister()); |
5218 return result; | 5006 return result; |
5219 } | 5007 } |
5220 | 5008 |
5221 | |
5222 void SmiToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5009 void SmiToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5223 Register value = locs()->in(0).reg(); | 5010 Register value = locs()->in(0).reg(); |
5224 FpuRegister result = locs()->out(0).fpu_reg(); | 5011 FpuRegister result = locs()->out(0).fpu_reg(); |
5225 __ SmiUntag(value); | 5012 __ SmiUntag(value); |
5226 __ cvtsi2sd(result, value); | 5013 __ cvtsi2sd(result, value); |
5227 } | 5014 } |
5228 | 5015 |
5229 | |
5230 LocationSummary* MintToDoubleInstr::MakeLocationSummary(Zone* zone, | 5016 LocationSummary* MintToDoubleInstr::MakeLocationSummary(Zone* zone, |
5231 bool opt) const { | 5017 bool opt) const { |
5232 const intptr_t kNumInputs = 1; | 5018 const intptr_t kNumInputs = 1; |
5233 const intptr_t kNumTemps = 0; | 5019 const intptr_t kNumTemps = 0; |
5234 LocationSummary* result = new (zone) | 5020 LocationSummary* result = new (zone) |
5235 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5021 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5236 result->set_in(0, Location::Pair(Location::RequiresRegister(), | 5022 result->set_in(0, Location::Pair(Location::RequiresRegister(), |
5237 Location::RequiresRegister())); | 5023 Location::RequiresRegister())); |
5238 result->set_out(0, Location::RequiresFpuRegister()); | 5024 result->set_out(0, Location::RequiresFpuRegister()); |
5239 return result; | 5025 return result; |
5240 } | 5026 } |
5241 | 5027 |
5242 | |
5243 void MintToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5028 void MintToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5244 PairLocation* pair = locs()->in(0).AsPairLocation(); | 5029 PairLocation* pair = locs()->in(0).AsPairLocation(); |
5245 Register in_lo = pair->At(0).reg(); | 5030 Register in_lo = pair->At(0).reg(); |
5246 Register in_hi = pair->At(1).reg(); | 5031 Register in_hi = pair->At(1).reg(); |
5247 | 5032 |
5248 FpuRegister result = locs()->out(0).fpu_reg(); | 5033 FpuRegister result = locs()->out(0).fpu_reg(); |
5249 | 5034 |
5250 // Push hi. | 5035 // Push hi. |
5251 __ pushl(in_hi); | 5036 __ pushl(in_hi); |
5252 // Push lo. | 5037 // Push lo. |
5253 __ pushl(in_lo); | 5038 __ pushl(in_lo); |
5254 // Perform conversion from Mint to double. | 5039 // Perform conversion from Mint to double. |
5255 __ fildl(Address(ESP, 0)); | 5040 __ fildl(Address(ESP, 0)); |
5256 // Pop FPU stack onto regular stack. | 5041 // Pop FPU stack onto regular stack. |
5257 __ fstpl(Address(ESP, 0)); | 5042 __ fstpl(Address(ESP, 0)); |
5258 // Copy into result. | 5043 // Copy into result. |
5259 __ movsd(result, Address(ESP, 0)); | 5044 __ movsd(result, Address(ESP, 0)); |
5260 // Pop args. | 5045 // Pop args. |
5261 __ addl(ESP, Immediate(2 * kWordSize)); | 5046 __ addl(ESP, Immediate(2 * kWordSize)); |
5262 } | 5047 } |
5263 | 5048 |
5264 | |
5265 LocationSummary* DoubleToIntegerInstr::MakeLocationSummary(Zone* zone, | 5049 LocationSummary* DoubleToIntegerInstr::MakeLocationSummary(Zone* zone, |
5266 bool opt) const { | 5050 bool opt) const { |
5267 const intptr_t kNumInputs = 1; | 5051 const intptr_t kNumInputs = 1; |
5268 const intptr_t kNumTemps = 0; | 5052 const intptr_t kNumTemps = 0; |
5269 LocationSummary* result = new (zone) | 5053 LocationSummary* result = new (zone) |
5270 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 5054 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
5271 result->set_in(0, Location::RegisterLocation(ECX)); | 5055 result->set_in(0, Location::RegisterLocation(ECX)); |
5272 result->set_out(0, Location::RegisterLocation(EAX)); | 5056 result->set_out(0, Location::RegisterLocation(EAX)); |
5273 return result; | 5057 return result; |
5274 } | 5058 } |
5275 | 5059 |
5276 | |
5277 void DoubleToIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5060 void DoubleToIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5278 Register result = locs()->out(0).reg(); | 5061 Register result = locs()->out(0).reg(); |
5279 Register value_obj = locs()->in(0).reg(); | 5062 Register value_obj = locs()->in(0).reg(); |
5280 XmmRegister value_double = XMM0; | 5063 XmmRegister value_double = XMM0; |
5281 ASSERT(result == EAX); | 5064 ASSERT(result == EAX); |
5282 ASSERT(result != value_obj); | 5065 ASSERT(result != value_obj); |
5283 __ movsd(value_double, FieldAddress(value_obj, Double::value_offset())); | 5066 __ movsd(value_double, FieldAddress(value_obj, Double::value_offset())); |
5284 __ cvttsd2si(result, value_double); | 5067 __ cvttsd2si(result, value_double); |
5285 // Overflow is signalled with minint. | 5068 // Overflow is signalled with minint. |
5286 Label do_call, done; | 5069 Label do_call, done; |
(...skipping 10 matching lines...) Expand all Loading... |
5297 const Function& target = Function::ZoneHandle(ic_data.GetTargetAt(0)); | 5080 const Function& target = Function::ZoneHandle(ic_data.GetTargetAt(0)); |
5298 const int kTypeArgsLen = 0; | 5081 const int kTypeArgsLen = 0; |
5299 const int kNumberOfArguments = 1; | 5082 const int kNumberOfArguments = 1; |
5300 const Array& kNoArgumentNames = Object::null_array(); | 5083 const Array& kNoArgumentNames = Object::null_array(); |
5301 ArgumentsInfo args_info(kTypeArgsLen, kNumberOfArguments, kNoArgumentNames); | 5084 ArgumentsInfo args_info(kTypeArgsLen, kNumberOfArguments, kNoArgumentNames); |
5302 compiler->GenerateStaticCall(deopt_id(), instance_call()->token_pos(), target, | 5085 compiler->GenerateStaticCall(deopt_id(), instance_call()->token_pos(), target, |
5303 args_info, locs(), ICData::Handle()); | 5086 args_info, locs(), ICData::Handle()); |
5304 __ Bind(&done); | 5087 __ Bind(&done); |
5305 } | 5088 } |
5306 | 5089 |
5307 | |
5308 LocationSummary* DoubleToSmiInstr::MakeLocationSummary(Zone* zone, | 5090 LocationSummary* DoubleToSmiInstr::MakeLocationSummary(Zone* zone, |
5309 bool opt) const { | 5091 bool opt) const { |
5310 const intptr_t kNumInputs = 1; | 5092 const intptr_t kNumInputs = 1; |
5311 const intptr_t kNumTemps = 0; | 5093 const intptr_t kNumTemps = 0; |
5312 LocationSummary* result = new (zone) | 5094 LocationSummary* result = new (zone) |
5313 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5095 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5314 result->set_in(0, Location::RequiresFpuRegister()); | 5096 result->set_in(0, Location::RequiresFpuRegister()); |
5315 result->set_out(0, Location::RequiresRegister()); | 5097 result->set_out(0, Location::RequiresRegister()); |
5316 return result; | 5098 return result; |
5317 } | 5099 } |
5318 | 5100 |
5319 | |
5320 void DoubleToSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5101 void DoubleToSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5321 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptDoubleToSmi); | 5102 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptDoubleToSmi); |
5322 Register result = locs()->out(0).reg(); | 5103 Register result = locs()->out(0).reg(); |
5323 XmmRegister value = locs()->in(0).fpu_reg(); | 5104 XmmRegister value = locs()->in(0).fpu_reg(); |
5324 __ cvttsd2si(result, value); | 5105 __ cvttsd2si(result, value); |
5325 // Check for overflow and that it fits into Smi. | 5106 // Check for overflow and that it fits into Smi. |
5326 __ cmpl(result, Immediate(0xC0000000)); | 5107 __ cmpl(result, Immediate(0xC0000000)); |
5327 __ j(NEGATIVE, deopt); | 5108 __ j(NEGATIVE, deopt); |
5328 __ SmiTag(result); | 5109 __ SmiTag(result); |
5329 } | 5110 } |
5330 | 5111 |
5331 | |
5332 LocationSummary* DoubleToDoubleInstr::MakeLocationSummary(Zone* zone, | 5112 LocationSummary* DoubleToDoubleInstr::MakeLocationSummary(Zone* zone, |
5333 bool opt) const { | 5113 bool opt) const { |
5334 const intptr_t kNumInputs = 1; | 5114 const intptr_t kNumInputs = 1; |
5335 const intptr_t kNumTemps = 0; | 5115 const intptr_t kNumTemps = 0; |
5336 LocationSummary* result = new (zone) | 5116 LocationSummary* result = new (zone) |
5337 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5117 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5338 result->set_in(0, Location::RequiresFpuRegister()); | 5118 result->set_in(0, Location::RequiresFpuRegister()); |
5339 result->set_out(0, Location::RequiresFpuRegister()); | 5119 result->set_out(0, Location::RequiresFpuRegister()); |
5340 return result; | 5120 return result; |
5341 } | 5121 } |
5342 | 5122 |
5343 | |
5344 void DoubleToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5123 void DoubleToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5345 XmmRegister value = locs()->in(0).fpu_reg(); | 5124 XmmRegister value = locs()->in(0).fpu_reg(); |
5346 XmmRegister result = locs()->out(0).fpu_reg(); | 5125 XmmRegister result = locs()->out(0).fpu_reg(); |
5347 switch (recognized_kind()) { | 5126 switch (recognized_kind()) { |
5348 case MethodRecognizer::kDoubleTruncate: | 5127 case MethodRecognizer::kDoubleTruncate: |
5349 __ roundsd(result, value, Assembler::kRoundToZero); | 5128 __ roundsd(result, value, Assembler::kRoundToZero); |
5350 break; | 5129 break; |
5351 case MethodRecognizer::kDoubleFloor: | 5130 case MethodRecognizer::kDoubleFloor: |
5352 __ roundsd(result, value, Assembler::kRoundDown); | 5131 __ roundsd(result, value, Assembler::kRoundDown); |
5353 break; | 5132 break; |
5354 case MethodRecognizer::kDoubleCeil: | 5133 case MethodRecognizer::kDoubleCeil: |
5355 __ roundsd(result, value, Assembler::kRoundUp); | 5134 __ roundsd(result, value, Assembler::kRoundUp); |
5356 break; | 5135 break; |
5357 default: | 5136 default: |
5358 UNREACHABLE(); | 5137 UNREACHABLE(); |
5359 } | 5138 } |
5360 } | 5139 } |
5361 | 5140 |
5362 | |
5363 LocationSummary* DoubleToFloatInstr::MakeLocationSummary(Zone* zone, | 5141 LocationSummary* DoubleToFloatInstr::MakeLocationSummary(Zone* zone, |
5364 bool opt) const { | 5142 bool opt) const { |
5365 const intptr_t kNumInputs = 1; | 5143 const intptr_t kNumInputs = 1; |
5366 const intptr_t kNumTemps = 0; | 5144 const intptr_t kNumTemps = 0; |
5367 LocationSummary* result = new (zone) | 5145 LocationSummary* result = new (zone) |
5368 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5146 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5369 result->set_in(0, Location::RequiresFpuRegister()); | 5147 result->set_in(0, Location::RequiresFpuRegister()); |
5370 result->set_out(0, Location::SameAsFirstInput()); | 5148 result->set_out(0, Location::SameAsFirstInput()); |
5371 return result; | 5149 return result; |
5372 } | 5150 } |
5373 | 5151 |
5374 | |
5375 void DoubleToFloatInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5152 void DoubleToFloatInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5376 __ cvtsd2ss(locs()->out(0).fpu_reg(), locs()->in(0).fpu_reg()); | 5153 __ cvtsd2ss(locs()->out(0).fpu_reg(), locs()->in(0).fpu_reg()); |
5377 } | 5154 } |
5378 | 5155 |
5379 | |
5380 LocationSummary* FloatToDoubleInstr::MakeLocationSummary(Zone* zone, | 5156 LocationSummary* FloatToDoubleInstr::MakeLocationSummary(Zone* zone, |
5381 bool opt) const { | 5157 bool opt) const { |
5382 const intptr_t kNumInputs = 1; | 5158 const intptr_t kNumInputs = 1; |
5383 const intptr_t kNumTemps = 0; | 5159 const intptr_t kNumTemps = 0; |
5384 LocationSummary* result = new (zone) | 5160 LocationSummary* result = new (zone) |
5385 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5161 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5386 result->set_in(0, Location::RequiresFpuRegister()); | 5162 result->set_in(0, Location::RequiresFpuRegister()); |
5387 result->set_out(0, Location::SameAsFirstInput()); | 5163 result->set_out(0, Location::SameAsFirstInput()); |
5388 return result; | 5164 return result; |
5389 } | 5165 } |
5390 | 5166 |
5391 | |
5392 void FloatToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5167 void FloatToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5393 __ cvtss2sd(locs()->out(0).fpu_reg(), locs()->in(0).fpu_reg()); | 5168 __ cvtss2sd(locs()->out(0).fpu_reg(), locs()->in(0).fpu_reg()); |
5394 } | 5169 } |
5395 | 5170 |
5396 | |
5397 LocationSummary* InvokeMathCFunctionInstr::MakeLocationSummary(Zone* zone, | 5171 LocationSummary* InvokeMathCFunctionInstr::MakeLocationSummary(Zone* zone, |
5398 bool opt) const { | 5172 bool opt) const { |
5399 ASSERT((InputCount() == 1) || (InputCount() == 2)); | 5173 ASSERT((InputCount() == 1) || (InputCount() == 2)); |
5400 const intptr_t kNumTemps = | 5174 const intptr_t kNumTemps = |
5401 (recognized_kind() == MethodRecognizer::kMathDoublePow) ? 3 : 1; | 5175 (recognized_kind() == MethodRecognizer::kMathDoublePow) ? 3 : 1; |
5402 LocationSummary* result = new (zone) | 5176 LocationSummary* result = new (zone) |
5403 LocationSummary(zone, InputCount(), kNumTemps, LocationSummary::kCall); | 5177 LocationSummary(zone, InputCount(), kNumTemps, LocationSummary::kCall); |
5404 // EDI is chosen because it is callee saved so we do not need to back it | 5178 // EDI is chosen because it is callee saved so we do not need to back it |
5405 // up before calling into the runtime. | 5179 // up before calling into the runtime. |
5406 result->set_temp(0, Location::RegisterLocation(EDI)); | 5180 result->set_temp(0, Location::RegisterLocation(EDI)); |
5407 result->set_in(0, Location::FpuRegisterLocation(XMM1)); | 5181 result->set_in(0, Location::FpuRegisterLocation(XMM1)); |
5408 if (InputCount() == 2) { | 5182 if (InputCount() == 2) { |
5409 result->set_in(1, Location::FpuRegisterLocation(XMM2)); | 5183 result->set_in(1, Location::FpuRegisterLocation(XMM2)); |
5410 } | 5184 } |
5411 if (recognized_kind() == MethodRecognizer::kMathDoublePow) { | 5185 if (recognized_kind() == MethodRecognizer::kMathDoublePow) { |
5412 // Temp index 1. | 5186 // Temp index 1. |
5413 result->set_temp(1, Location::RegisterLocation(EAX)); | 5187 result->set_temp(1, Location::RegisterLocation(EAX)); |
5414 // Temp index 2. | 5188 // Temp index 2. |
5415 result->set_temp(2, Location::FpuRegisterLocation(XMM4)); | 5189 result->set_temp(2, Location::FpuRegisterLocation(XMM4)); |
5416 } | 5190 } |
5417 result->set_out(0, Location::FpuRegisterLocation(XMM3)); | 5191 result->set_out(0, Location::FpuRegisterLocation(XMM3)); |
5418 return result; | 5192 return result; |
5419 } | 5193 } |
5420 | 5194 |
5421 | |
5422 // Pseudo code: | 5195 // Pseudo code: |
5423 // if (exponent == 0.0) return 1.0; | 5196 // if (exponent == 0.0) return 1.0; |
5424 // // Speed up simple cases. | 5197 // // Speed up simple cases. |
5425 // if (exponent == 1.0) return base; | 5198 // if (exponent == 1.0) return base; |
5426 // if (exponent == 2.0) return base * base; | 5199 // if (exponent == 2.0) return base * base; |
5427 // if (exponent == 3.0) return base * base * base; | 5200 // if (exponent == 3.0) return base * base * base; |
5428 // if (base == 1.0) return 1.0; | 5201 // if (base == 1.0) return 1.0; |
5429 // if (base.isNaN || exponent.isNaN) { | 5202 // if (base.isNaN || exponent.isNaN) { |
5430 // return double.NAN; | 5203 // return double.NAN; |
5431 // } | 5204 // } |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5544 __ movsd(Address(ESP, kDoubleSize * i), locs->in(i).fpu_reg()); | 5317 __ movsd(Address(ESP, kDoubleSize * i), locs->in(i).fpu_reg()); |
5545 } | 5318 } |
5546 __ CallRuntime(instr->TargetFunction(), kInputCount); | 5319 __ CallRuntime(instr->TargetFunction(), kInputCount); |
5547 __ fstpl(Address(ESP, 0)); | 5320 __ fstpl(Address(ESP, 0)); |
5548 __ movsd(locs->out(0).fpu_reg(), Address(ESP, 0)); | 5321 __ movsd(locs->out(0).fpu_reg(), Address(ESP, 0)); |
5549 // Restore ESP. | 5322 // Restore ESP. |
5550 __ movl(ESP, locs->temp(InvokeMathCFunctionInstr::kSavedSpTempIndex).reg()); | 5323 __ movl(ESP, locs->temp(InvokeMathCFunctionInstr::kSavedSpTempIndex).reg()); |
5551 __ Bind(&skip_call); | 5324 __ Bind(&skip_call); |
5552 } | 5325 } |
5553 | 5326 |
5554 | |
5555 void InvokeMathCFunctionInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5327 void InvokeMathCFunctionInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5556 if (recognized_kind() == MethodRecognizer::kMathDoublePow) { | 5328 if (recognized_kind() == MethodRecognizer::kMathDoublePow) { |
5557 InvokeDoublePow(compiler, this); | 5329 InvokeDoublePow(compiler, this); |
5558 return; | 5330 return; |
5559 } | 5331 } |
5560 // Save ESP. | 5332 // Save ESP. |
5561 __ movl(locs()->temp(kSavedSpTempIndex).reg(), ESP); | 5333 __ movl(locs()->temp(kSavedSpTempIndex).reg(), ESP); |
5562 __ ReserveAlignedFrameSpace(kDoubleSize * InputCount()); | 5334 __ ReserveAlignedFrameSpace(kDoubleSize * InputCount()); |
5563 for (intptr_t i = 0; i < InputCount(); i++) { | 5335 for (intptr_t i = 0; i < InputCount(); i++) { |
5564 __ movsd(Address(ESP, kDoubleSize * i), locs()->in(i).fpu_reg()); | 5336 __ movsd(Address(ESP, kDoubleSize * i), locs()->in(i).fpu_reg()); |
5565 } | 5337 } |
5566 | 5338 |
5567 __ CallRuntime(TargetFunction(), InputCount()); | 5339 __ CallRuntime(TargetFunction(), InputCount()); |
5568 __ fstpl(Address(ESP, 0)); | 5340 __ fstpl(Address(ESP, 0)); |
5569 __ movsd(locs()->out(0).fpu_reg(), Address(ESP, 0)); | 5341 __ movsd(locs()->out(0).fpu_reg(), Address(ESP, 0)); |
5570 // Restore ESP. | 5342 // Restore ESP. |
5571 __ movl(ESP, locs()->temp(kSavedSpTempIndex).reg()); | 5343 __ movl(ESP, locs()->temp(kSavedSpTempIndex).reg()); |
5572 } | 5344 } |
5573 | 5345 |
5574 | |
5575 LocationSummary* ExtractNthOutputInstr::MakeLocationSummary(Zone* zone, | 5346 LocationSummary* ExtractNthOutputInstr::MakeLocationSummary(Zone* zone, |
5576 bool opt) const { | 5347 bool opt) const { |
5577 // Only use this instruction in optimized code. | 5348 // Only use this instruction in optimized code. |
5578 ASSERT(opt); | 5349 ASSERT(opt); |
5579 const intptr_t kNumInputs = 1; | 5350 const intptr_t kNumInputs = 1; |
5580 LocationSummary* summary = | 5351 LocationSummary* summary = |
5581 new (zone) LocationSummary(zone, kNumInputs, 0, LocationSummary::kNoCall); | 5352 new (zone) LocationSummary(zone, kNumInputs, 0, LocationSummary::kNoCall); |
5582 if (representation() == kUnboxedDouble) { | 5353 if (representation() == kUnboxedDouble) { |
5583 if (index() == 0) { | 5354 if (index() == 0) { |
5584 summary->set_in( | 5355 summary->set_in( |
(...skipping 12 matching lines...) Expand all Loading... |
5597 } else { | 5368 } else { |
5598 ASSERT(index() == 1); | 5369 ASSERT(index() == 1); |
5599 summary->set_in( | 5370 summary->set_in( |
5600 0, Location::Pair(Location::Any(), Location::RequiresRegister())); | 5371 0, Location::Pair(Location::Any(), Location::RequiresRegister())); |
5601 } | 5372 } |
5602 summary->set_out(0, Location::RequiresRegister()); | 5373 summary->set_out(0, Location::RequiresRegister()); |
5603 } | 5374 } |
5604 return summary; | 5375 return summary; |
5605 } | 5376 } |
5606 | 5377 |
5607 | |
5608 void ExtractNthOutputInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5378 void ExtractNthOutputInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5609 ASSERT(locs()->in(0).IsPairLocation()); | 5379 ASSERT(locs()->in(0).IsPairLocation()); |
5610 PairLocation* pair = locs()->in(0).AsPairLocation(); | 5380 PairLocation* pair = locs()->in(0).AsPairLocation(); |
5611 Location in_loc = pair->At(index()); | 5381 Location in_loc = pair->At(index()); |
5612 if (representation() == kUnboxedDouble) { | 5382 if (representation() == kUnboxedDouble) { |
5613 XmmRegister out = locs()->out(0).fpu_reg(); | 5383 XmmRegister out = locs()->out(0).fpu_reg(); |
5614 XmmRegister in = in_loc.fpu_reg(); | 5384 XmmRegister in = in_loc.fpu_reg(); |
5615 __ movaps(out, in); | 5385 __ movaps(out, in); |
5616 } else { | 5386 } else { |
5617 ASSERT(representation() == kTagged); | 5387 ASSERT(representation() == kTagged); |
5618 Register out = locs()->out(0).reg(); | 5388 Register out = locs()->out(0).reg(); |
5619 Register in = in_loc.reg(); | 5389 Register in = in_loc.reg(); |
5620 __ movl(out, in); | 5390 __ movl(out, in); |
5621 } | 5391 } |
5622 } | 5392 } |
5623 | 5393 |
5624 | |
5625 LocationSummary* TruncDivModInstr::MakeLocationSummary(Zone* zone, | 5394 LocationSummary* TruncDivModInstr::MakeLocationSummary(Zone* zone, |
5626 bool opt) const { | 5395 bool opt) const { |
5627 const intptr_t kNumInputs = 2; | 5396 const intptr_t kNumInputs = 2; |
5628 const intptr_t kNumTemps = 0; | 5397 const intptr_t kNumTemps = 0; |
5629 LocationSummary* summary = new (zone) | 5398 LocationSummary* summary = new (zone) |
5630 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5399 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5631 // Both inputs must be writable because they will be untagged. | 5400 // Both inputs must be writable because they will be untagged. |
5632 summary->set_in(0, Location::RegisterLocation(EAX)); | 5401 summary->set_in(0, Location::RegisterLocation(EAX)); |
5633 summary->set_in(1, Location::WritableRegister()); | 5402 summary->set_in(1, Location::WritableRegister()); |
5634 // Output is a pair of registers. | 5403 // Output is a pair of registers. |
5635 summary->set_out(0, Location::Pair(Location::RegisterLocation(EAX), | 5404 summary->set_out(0, Location::Pair(Location::RegisterLocation(EAX), |
5636 Location::RegisterLocation(EDX))); | 5405 Location::RegisterLocation(EDX))); |
5637 return summary; | 5406 return summary; |
5638 } | 5407 } |
5639 | 5408 |
5640 | |
5641 void TruncDivModInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5409 void TruncDivModInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5642 ASSERT(CanDeoptimize()); | 5410 ASSERT(CanDeoptimize()); |
5643 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinarySmiOp); | 5411 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinarySmiOp); |
5644 Register left = locs()->in(0).reg(); | 5412 Register left = locs()->in(0).reg(); |
5645 Register right = locs()->in(1).reg(); | 5413 Register right = locs()->in(1).reg(); |
5646 ASSERT(locs()->out(0).IsPairLocation()); | 5414 ASSERT(locs()->out(0).IsPairLocation()); |
5647 PairLocation* pair = locs()->out(0).AsPairLocation(); | 5415 PairLocation* pair = locs()->out(0).AsPairLocation(); |
5648 Register result1 = pair->At(0).reg(); | 5416 Register result1 = pair->At(0).reg(); |
5649 Register result2 = pair->At(1).reg(); | 5417 Register result2 = pair->At(1).reg(); |
5650 if (RangeUtils::CanBeZero(divisor_range())) { | 5418 if (RangeUtils::CanBeZero(divisor_range())) { |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5694 } else { | 5462 } else { |
5695 // Right is negative. | 5463 // Right is negative. |
5696 __ subl(EDX, right); | 5464 __ subl(EDX, right); |
5697 } | 5465 } |
5698 __ Bind(&done); | 5466 __ Bind(&done); |
5699 | 5467 |
5700 __ SmiTag(EAX); | 5468 __ SmiTag(EAX); |
5701 __ SmiTag(EDX); | 5469 __ SmiTag(EDX); |
5702 } | 5470 } |
5703 | 5471 |
5704 | |
5705 LocationSummary* PolymorphicInstanceCallInstr::MakeLocationSummary( | 5472 LocationSummary* PolymorphicInstanceCallInstr::MakeLocationSummary( |
5706 Zone* zone, | 5473 Zone* zone, |
5707 bool opt) const { | 5474 bool opt) const { |
5708 return MakeCallSummary(zone); | 5475 return MakeCallSummary(zone); |
5709 } | 5476 } |
5710 | 5477 |
5711 | |
5712 LocationSummary* BranchInstr::MakeLocationSummary(Zone* zone, bool opt) const { | 5478 LocationSummary* BranchInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
5713 comparison()->InitializeLocationSummary(zone, opt); | 5479 comparison()->InitializeLocationSummary(zone, opt); |
5714 // Branches don't produce a result. | 5480 // Branches don't produce a result. |
5715 comparison()->locs()->set_out(0, Location::NoLocation()); | 5481 comparison()->locs()->set_out(0, Location::NoLocation()); |
5716 return comparison()->locs(); | 5482 return comparison()->locs(); |
5717 } | 5483 } |
5718 | 5484 |
5719 | |
5720 void BranchInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5485 void BranchInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5721 comparison()->EmitBranchCode(compiler, this); | 5486 comparison()->EmitBranchCode(compiler, this); |
5722 } | 5487 } |
5723 | 5488 |
5724 | |
5725 LocationSummary* CheckClassInstr::MakeLocationSummary(Zone* zone, | 5489 LocationSummary* CheckClassInstr::MakeLocationSummary(Zone* zone, |
5726 bool opt) const { | 5490 bool opt) const { |
5727 const intptr_t kNumInputs = 1; | 5491 const intptr_t kNumInputs = 1; |
5728 const bool need_mask_temp = IsBitTest(); | 5492 const bool need_mask_temp = IsBitTest(); |
5729 const intptr_t kNumTemps = !IsNullCheck() ? (need_mask_temp ? 2 : 1) : 0; | 5493 const intptr_t kNumTemps = !IsNullCheck() ? (need_mask_temp ? 2 : 1) : 0; |
5730 LocationSummary* summary = new (zone) | 5494 LocationSummary* summary = new (zone) |
5731 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5495 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5732 summary->set_in(0, Location::RequiresRegister()); | 5496 summary->set_in(0, Location::RequiresRegister()); |
5733 if (!IsNullCheck()) { | 5497 if (!IsNullCheck()) { |
5734 summary->set_temp(0, Location::RequiresRegister()); | 5498 summary->set_temp(0, Location::RequiresRegister()); |
5735 if (need_mask_temp) { | 5499 if (need_mask_temp) { |
5736 summary->set_temp(1, Location::RequiresRegister()); | 5500 summary->set_temp(1, Location::RequiresRegister()); |
5737 } | 5501 } |
5738 } | 5502 } |
5739 return summary; | 5503 return summary; |
5740 } | 5504 } |
5741 | 5505 |
5742 | |
5743 void CheckClassInstr::EmitNullCheck(FlowGraphCompiler* compiler, Label* deopt) { | 5506 void CheckClassInstr::EmitNullCheck(FlowGraphCompiler* compiler, Label* deopt) { |
5744 const Immediate& raw_null = | 5507 const Immediate& raw_null = |
5745 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 5508 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
5746 __ cmpl(locs()->in(0).reg(), raw_null); | 5509 __ cmpl(locs()->in(0).reg(), raw_null); |
5747 ASSERT(IsDeoptIfNull() || IsDeoptIfNotNull()); | 5510 ASSERT(IsDeoptIfNull() || IsDeoptIfNotNull()); |
5748 Condition cond = IsDeoptIfNull() ? EQUAL : NOT_EQUAL; | 5511 Condition cond = IsDeoptIfNull() ? EQUAL : NOT_EQUAL; |
5749 __ j(cond, deopt); | 5512 __ j(cond, deopt); |
5750 } | 5513 } |
5751 | 5514 |
5752 | |
5753 void CheckClassInstr::EmitBitTest(FlowGraphCompiler* compiler, | 5515 void CheckClassInstr::EmitBitTest(FlowGraphCompiler* compiler, |
5754 intptr_t min, | 5516 intptr_t min, |
5755 intptr_t max, | 5517 intptr_t max, |
5756 intptr_t mask, | 5518 intptr_t mask, |
5757 Label* deopt) { | 5519 Label* deopt) { |
5758 Register biased_cid = locs()->temp(0).reg(); | 5520 Register biased_cid = locs()->temp(0).reg(); |
5759 __ subl(biased_cid, Immediate(min)); | 5521 __ subl(biased_cid, Immediate(min)); |
5760 __ cmpl(biased_cid, Immediate(max - min)); | 5522 __ cmpl(biased_cid, Immediate(max - min)); |
5761 __ j(ABOVE, deopt); | 5523 __ j(ABOVE, deopt); |
5762 | 5524 |
5763 Register mask_reg = locs()->temp(1).reg(); | 5525 Register mask_reg = locs()->temp(1).reg(); |
5764 __ movl(mask_reg, Immediate(mask)); | 5526 __ movl(mask_reg, Immediate(mask)); |
5765 __ bt(mask_reg, biased_cid); | 5527 __ bt(mask_reg, biased_cid); |
5766 __ j(NOT_CARRY, deopt); | 5528 __ j(NOT_CARRY, deopt); |
5767 } | 5529 } |
5768 | 5530 |
5769 | |
5770 int CheckClassInstr::EmitCheckCid(FlowGraphCompiler* compiler, | 5531 int CheckClassInstr::EmitCheckCid(FlowGraphCompiler* compiler, |
5771 int bias, | 5532 int bias, |
5772 intptr_t cid_start, | 5533 intptr_t cid_start, |
5773 intptr_t cid_end, | 5534 intptr_t cid_end, |
5774 bool is_last, | 5535 bool is_last, |
5775 Label* is_ok, | 5536 Label* is_ok, |
5776 Label* deopt, | 5537 Label* deopt, |
5777 bool use_near_jump) { | 5538 bool use_near_jump) { |
5778 Register biased_cid = locs()->temp(0).reg(); | 5539 Register biased_cid = locs()->temp(0).reg(); |
5779 Condition no_match, match; | 5540 Condition no_match, match; |
(...skipping 16 matching lines...) Expand all Loading... |
5796 } else { | 5557 } else { |
5797 if (use_near_jump) { | 5558 if (use_near_jump) { |
5798 __ j(match, is_ok, Assembler::kNearJump); | 5559 __ j(match, is_ok, Assembler::kNearJump); |
5799 } else { | 5560 } else { |
5800 __ j(match, is_ok); | 5561 __ j(match, is_ok); |
5801 } | 5562 } |
5802 } | 5563 } |
5803 return bias; | 5564 return bias; |
5804 } | 5565 } |
5805 | 5566 |
5806 | |
5807 LocationSummary* CheckSmiInstr::MakeLocationSummary(Zone* zone, | 5567 LocationSummary* CheckSmiInstr::MakeLocationSummary(Zone* zone, |
5808 bool opt) const { | 5568 bool opt) const { |
5809 const intptr_t kNumInputs = 1; | 5569 const intptr_t kNumInputs = 1; |
5810 const intptr_t kNumTemps = 0; | 5570 const intptr_t kNumTemps = 0; |
5811 LocationSummary* summary = new (zone) | 5571 LocationSummary* summary = new (zone) |
5812 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5572 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5813 summary->set_in(0, Location::RequiresRegister()); | 5573 summary->set_in(0, Location::RequiresRegister()); |
5814 return summary; | 5574 return summary; |
5815 } | 5575 } |
5816 | 5576 |
5817 | |
5818 void CheckSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5577 void CheckSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5819 Register value = locs()->in(0).reg(); | 5578 Register value = locs()->in(0).reg(); |
5820 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptCheckSmi, | 5579 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptCheckSmi, |
5821 licm_hoisted_ ? ICData::kHoisted : 0); | 5580 licm_hoisted_ ? ICData::kHoisted : 0); |
5822 __ BranchIfNotSmi(value, deopt); | 5581 __ BranchIfNotSmi(value, deopt); |
5823 } | 5582 } |
5824 | 5583 |
5825 | |
5826 LocationSummary* CheckClassIdInstr::MakeLocationSummary(Zone* zone, | 5584 LocationSummary* CheckClassIdInstr::MakeLocationSummary(Zone* zone, |
5827 bool opt) const { | 5585 bool opt) const { |
5828 const intptr_t kNumInputs = 1; | 5586 const intptr_t kNumInputs = 1; |
5829 const intptr_t kNumTemps = 0; | 5587 const intptr_t kNumTemps = 0; |
5830 LocationSummary* summary = new (zone) | 5588 LocationSummary* summary = new (zone) |
5831 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5589 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5832 summary->set_in(0, cids_.IsSingleCid() ? Location::RequiresRegister() | 5590 summary->set_in(0, cids_.IsSingleCid() ? Location::RequiresRegister() |
5833 : Location::WritableRegister()); | 5591 : Location::WritableRegister()); |
5834 return summary; | 5592 return summary; |
5835 } | 5593 } |
5836 | 5594 |
5837 | |
5838 void CheckClassIdInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5595 void CheckClassIdInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5839 Register value = locs()->in(0).reg(); | 5596 Register value = locs()->in(0).reg(); |
5840 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptCheckClass); | 5597 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptCheckClass); |
5841 if (cids_.IsSingleCid()) { | 5598 if (cids_.IsSingleCid()) { |
5842 __ cmpl(value, Immediate(Smi::RawValue(cids_.cid_start))); | 5599 __ cmpl(value, Immediate(Smi::RawValue(cids_.cid_start))); |
5843 __ j(NOT_ZERO, deopt); | 5600 __ j(NOT_ZERO, deopt); |
5844 } else { | 5601 } else { |
5845 __ AddImmediate(value, Immediate(-Smi::RawValue(cids_.cid_start))); | 5602 __ AddImmediate(value, Immediate(-Smi::RawValue(cids_.cid_start))); |
5846 __ cmpl(value, Immediate(Smi::RawValue(cids_.Extent()))); | 5603 __ cmpl(value, Immediate(Smi::RawValue(cids_.Extent()))); |
5847 __ j(ABOVE, deopt); | 5604 __ j(ABOVE, deopt); |
5848 } | 5605 } |
5849 } | 5606 } |
5850 | 5607 |
5851 | |
5852 LocationSummary* GenericCheckBoundInstr::MakeLocationSummary(Zone* zone, | 5608 LocationSummary* GenericCheckBoundInstr::MakeLocationSummary(Zone* zone, |
5853 bool opt) const { | 5609 bool opt) const { |
5854 // Only needed for AOT. | 5610 // Only needed for AOT. |
5855 UNIMPLEMENTED(); | 5611 UNIMPLEMENTED(); |
5856 return NULL; | 5612 return NULL; |
5857 } | 5613 } |
5858 | 5614 |
5859 | |
5860 void GenericCheckBoundInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5615 void GenericCheckBoundInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5861 // Only needed for AOT. | 5616 // Only needed for AOT. |
5862 UNIMPLEMENTED(); | 5617 UNIMPLEMENTED(); |
5863 } | 5618 } |
5864 | 5619 |
5865 | |
5866 // Length: register or constant. | 5620 // Length: register or constant. |
5867 // Index: register, constant or stack slot. | 5621 // Index: register, constant or stack slot. |
5868 LocationSummary* CheckArrayBoundInstr::MakeLocationSummary(Zone* zone, | 5622 LocationSummary* CheckArrayBoundInstr::MakeLocationSummary(Zone* zone, |
5869 bool opt) const { | 5623 bool opt) const { |
5870 const intptr_t kNumInputs = 2; | 5624 const intptr_t kNumInputs = 2; |
5871 const intptr_t kNumTemps = 0; | 5625 const intptr_t kNumTemps = 0; |
5872 LocationSummary* locs = new (zone) | 5626 LocationSummary* locs = new (zone) |
5873 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5627 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5874 if (length()->definition()->IsConstant()) { | 5628 if (length()->definition()->IsConstant()) { |
5875 locs->set_in(kLengthPos, Location::RegisterOrSmiConstant(length())); | 5629 locs->set_in(kLengthPos, Location::RegisterOrSmiConstant(length())); |
5876 } else { | 5630 } else { |
5877 locs->set_in(kLengthPos, Location::PrefersRegister()); | 5631 locs->set_in(kLengthPos, Location::PrefersRegister()); |
5878 } | 5632 } |
5879 locs->set_in(kIndexPos, Location::RegisterOrSmiConstant(index())); | 5633 locs->set_in(kIndexPos, Location::RegisterOrSmiConstant(index())); |
5880 return locs; | 5634 return locs; |
5881 } | 5635 } |
5882 | 5636 |
5883 | |
5884 void CheckArrayBoundInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5637 void CheckArrayBoundInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5885 uint32_t flags = generalized_ ? ICData::kGeneralized : 0; | 5638 uint32_t flags = generalized_ ? ICData::kGeneralized : 0; |
5886 flags |= licm_hoisted_ ? ICData::kHoisted : 0; | 5639 flags |= licm_hoisted_ ? ICData::kHoisted : 0; |
5887 Label* deopt = | 5640 Label* deopt = |
5888 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptCheckArrayBound, flags); | 5641 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptCheckArrayBound, flags); |
5889 | 5642 |
5890 Location length_loc = locs()->in(kLengthPos); | 5643 Location length_loc = locs()->in(kLengthPos); |
5891 Location index_loc = locs()->in(kIndexPos); | 5644 Location index_loc = locs()->in(kIndexPos); |
5892 | 5645 |
5893 if (length_loc.IsConstant() && index_loc.IsConstant()) { | 5646 if (length_loc.IsConstant() && index_loc.IsConstant()) { |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5936 Register index = index_loc.reg(); | 5689 Register index = index_loc.reg(); |
5937 Register length = length_loc.reg(); | 5690 Register length = length_loc.reg(); |
5938 if (index_cid != kSmiCid) { | 5691 if (index_cid != kSmiCid) { |
5939 __ BranchIfNotSmi(index, deopt); | 5692 __ BranchIfNotSmi(index, deopt); |
5940 } | 5693 } |
5941 __ cmpl(length, index); | 5694 __ cmpl(length, index); |
5942 __ j(BELOW_EQUAL, deopt); | 5695 __ j(BELOW_EQUAL, deopt); |
5943 } | 5696 } |
5944 } | 5697 } |
5945 | 5698 |
5946 | |
5947 LocationSummary* BinaryMintOpInstr::MakeLocationSummary(Zone* zone, | 5699 LocationSummary* BinaryMintOpInstr::MakeLocationSummary(Zone* zone, |
5948 bool opt) const { | 5700 bool opt) const { |
5949 const intptr_t kNumInputs = 2; | 5701 const intptr_t kNumInputs = 2; |
5950 switch (op_kind()) { | 5702 switch (op_kind()) { |
5951 case Token::kBIT_AND: | 5703 case Token::kBIT_AND: |
5952 case Token::kBIT_OR: | 5704 case Token::kBIT_OR: |
5953 case Token::kBIT_XOR: | 5705 case Token::kBIT_XOR: |
5954 case Token::kADD: | 5706 case Token::kADD: |
5955 case Token::kSUB: | 5707 case Token::kSUB: |
5956 case Token::kMUL: { | 5708 case Token::kMUL: { |
(...skipping 12 matching lines...) Expand all Loading... |
5969 summary->set_temp(0, Location::RequiresRegister()); | 5721 summary->set_temp(0, Location::RequiresRegister()); |
5970 } | 5722 } |
5971 return summary; | 5723 return summary; |
5972 } | 5724 } |
5973 default: | 5725 default: |
5974 UNREACHABLE(); | 5726 UNREACHABLE(); |
5975 return NULL; | 5727 return NULL; |
5976 } | 5728 } |
5977 } | 5729 } |
5978 | 5730 |
5979 | |
5980 void BinaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5731 void BinaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5981 PairLocation* left_pair = locs()->in(0).AsPairLocation(); | 5732 PairLocation* left_pair = locs()->in(0).AsPairLocation(); |
5982 Register left_lo = left_pair->At(0).reg(); | 5733 Register left_lo = left_pair->At(0).reg(); |
5983 Register left_hi = left_pair->At(1).reg(); | 5734 Register left_hi = left_pair->At(1).reg(); |
5984 PairLocation* right_pair = locs()->in(1).AsPairLocation(); | 5735 PairLocation* right_pair = locs()->in(1).AsPairLocation(); |
5985 Register right_lo = right_pair->At(0).reg(); | 5736 Register right_lo = right_pair->At(0).reg(); |
5986 Register right_hi = right_pair->At(1).reg(); | 5737 Register right_hi = right_pair->At(1).reg(); |
5987 PairLocation* out_pair = locs()->out(0).AsPairLocation(); | 5738 PairLocation* out_pair = locs()->out(0).AsPairLocation(); |
5988 Register out_lo = out_pair->At(0).reg(); | 5739 Register out_lo = out_pair->At(0).reg(); |
5989 Register out_hi = out_pair->At(1).reg(); | 5740 Register out_hi = out_pair->At(1).reg(); |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6039 __ imull(right_lo); // Result in EDX:EAX. | 5790 __ imull(right_lo); // Result in EDX:EAX. |
6040 ASSERT(out_lo == EAX); | 5791 ASSERT(out_lo == EAX); |
6041 ASSERT(out_hi == EDX); | 5792 ASSERT(out_hi == EDX); |
6042 break; | 5793 break; |
6043 } | 5794 } |
6044 default: | 5795 default: |
6045 UNREACHABLE(); | 5796 UNREACHABLE(); |
6046 } | 5797 } |
6047 } | 5798 } |
6048 | 5799 |
6049 | |
6050 LocationSummary* ShiftMintOpInstr::MakeLocationSummary(Zone* zone, | 5800 LocationSummary* ShiftMintOpInstr::MakeLocationSummary(Zone* zone, |
6051 bool opt) const { | 5801 bool opt) const { |
6052 const intptr_t kNumInputs = 2; | 5802 const intptr_t kNumInputs = 2; |
6053 const intptr_t kNumTemps = | 5803 const intptr_t kNumTemps = |
6054 (op_kind() == Token::kSHL) && CanDeoptimize() ? 2 : 0; | 5804 (op_kind() == Token::kSHL) && CanDeoptimize() ? 2 : 0; |
6055 LocationSummary* summary = new (zone) | 5805 LocationSummary* summary = new (zone) |
6056 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5806 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
6057 summary->set_in(0, Location::Pair(Location::RequiresRegister(), | 5807 summary->set_in(0, Location::Pair(Location::RequiresRegister(), |
6058 Location::RequiresRegister())); | 5808 Location::RequiresRegister())); |
6059 summary->set_in(1, Location::FixedRegisterOrSmiConstant(right(), ECX)); | 5809 summary->set_in(1, Location::FixedRegisterOrSmiConstant(right(), ECX)); |
6060 if ((op_kind() == Token::kSHL) && CanDeoptimize()) { | 5810 if ((op_kind() == Token::kSHL) && CanDeoptimize()) { |
6061 summary->set_temp(0, Location::RequiresRegister()); | 5811 summary->set_temp(0, Location::RequiresRegister()); |
6062 summary->set_temp(1, Location::RequiresRegister()); | 5812 summary->set_temp(1, Location::RequiresRegister()); |
6063 } | 5813 } |
6064 summary->set_out(0, Location::SameAsFirstInput()); | 5814 summary->set_out(0, Location::SameAsFirstInput()); |
6065 return summary; | 5815 return summary; |
6066 } | 5816 } |
6067 | 5817 |
6068 | |
6069 void ShiftMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5818 void ShiftMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
6070 PairLocation* left_pair = locs()->in(0).AsPairLocation(); | 5819 PairLocation* left_pair = locs()->in(0).AsPairLocation(); |
6071 Register left_lo = left_pair->At(0).reg(); | 5820 Register left_lo = left_pair->At(0).reg(); |
6072 Register left_hi = left_pair->At(1).reg(); | 5821 Register left_hi = left_pair->At(1).reg(); |
6073 PairLocation* out_pair = locs()->out(0).AsPairLocation(); | 5822 PairLocation* out_pair = locs()->out(0).AsPairLocation(); |
6074 Register out_lo = out_pair->At(0).reg(); | 5823 Register out_lo = out_pair->At(0).reg(); |
6075 Register out_hi = out_pair->At(1).reg(); | 5824 Register out_hi = out_pair->At(1).reg(); |
6076 ASSERT(out_lo == left_lo); | 5825 ASSERT(out_lo == left_lo); |
6077 ASSERT(out_hi == left_hi); | 5826 ASSERT(out_hi == left_hi); |
6078 | 5827 |
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6231 } | 5980 } |
6232 break; | 5981 break; |
6233 } | 5982 } |
6234 default: | 5983 default: |
6235 UNREACHABLE(); | 5984 UNREACHABLE(); |
6236 } | 5985 } |
6237 __ Bind(&done); | 5986 __ Bind(&done); |
6238 } | 5987 } |
6239 } | 5988 } |
6240 | 5989 |
6241 | |
6242 LocationSummary* UnaryMintOpInstr::MakeLocationSummary(Zone* zone, | 5990 LocationSummary* UnaryMintOpInstr::MakeLocationSummary(Zone* zone, |
6243 bool opt) const { | 5991 bool opt) const { |
6244 const intptr_t kNumInputs = 1; | 5992 const intptr_t kNumInputs = 1; |
6245 const intptr_t kNumTemps = 0; | 5993 const intptr_t kNumTemps = 0; |
6246 LocationSummary* summary = new (zone) | 5994 LocationSummary* summary = new (zone) |
6247 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5995 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
6248 summary->set_in(0, Location::Pair(Location::RequiresRegister(), | 5996 summary->set_in(0, Location::Pair(Location::RequiresRegister(), |
6249 Location::RequiresRegister())); | 5997 Location::RequiresRegister())); |
6250 summary->set_out(0, Location::SameAsFirstInput()); | 5998 summary->set_out(0, Location::SameAsFirstInput()); |
6251 return summary; | 5999 return summary; |
6252 } | 6000 } |
6253 | 6001 |
6254 | |
6255 void UnaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6002 void UnaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
6256 ASSERT(op_kind() == Token::kBIT_NOT); | 6003 ASSERT(op_kind() == Token::kBIT_NOT); |
6257 PairLocation* left_pair = locs()->in(0).AsPairLocation(); | 6004 PairLocation* left_pair = locs()->in(0).AsPairLocation(); |
6258 Register left_lo = left_pair->At(0).reg(); | 6005 Register left_lo = left_pair->At(0).reg(); |
6259 Register left_hi = left_pair->At(1).reg(); | 6006 Register left_hi = left_pair->At(1).reg(); |
6260 PairLocation* out_pair = locs()->out(0).AsPairLocation(); | 6007 PairLocation* out_pair = locs()->out(0).AsPairLocation(); |
6261 Register out_lo = out_pair->At(0).reg(); | 6008 Register out_lo = out_pair->At(0).reg(); |
6262 Register out_hi = out_pair->At(1).reg(); | 6009 Register out_hi = out_pair->At(1).reg(); |
6263 ASSERT(out_lo == left_lo); | 6010 ASSERT(out_lo == left_lo); |
6264 ASSERT(out_hi == left_hi); | 6011 ASSERT(out_hi == left_hi); |
6265 __ notl(left_lo); | 6012 __ notl(left_lo); |
6266 __ notl(left_hi); | 6013 __ notl(left_hi); |
6267 } | 6014 } |
6268 | 6015 |
6269 | |
6270 CompileType BinaryUint32OpInstr::ComputeType() const { | 6016 CompileType BinaryUint32OpInstr::ComputeType() const { |
6271 return CompileType::Int(); | 6017 return CompileType::Int(); |
6272 } | 6018 } |
6273 | 6019 |
6274 | |
6275 CompileType ShiftUint32OpInstr::ComputeType() const { | 6020 CompileType ShiftUint32OpInstr::ComputeType() const { |
6276 return CompileType::Int(); | 6021 return CompileType::Int(); |
6277 } | 6022 } |
6278 | 6023 |
6279 | |
6280 CompileType UnaryUint32OpInstr::ComputeType() const { | 6024 CompileType UnaryUint32OpInstr::ComputeType() const { |
6281 return CompileType::Int(); | 6025 return CompileType::Int(); |
6282 } | 6026 } |
6283 | 6027 |
6284 | |
6285 LocationSummary* ShiftUint32OpInstr::MakeLocationSummary(Zone* zone, | 6028 LocationSummary* ShiftUint32OpInstr::MakeLocationSummary(Zone* zone, |
6286 bool opt) const { | 6029 bool opt) const { |
6287 const intptr_t kNumInputs = 2; | 6030 const intptr_t kNumInputs = 2; |
6288 const intptr_t kNumTemps = 0; | 6031 const intptr_t kNumTemps = 0; |
6289 LocationSummary* summary = new (zone) | 6032 LocationSummary* summary = new (zone) |
6290 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 6033 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
6291 summary->set_in(0, Location::RequiresRegister()); | 6034 summary->set_in(0, Location::RequiresRegister()); |
6292 summary->set_in(1, Location::FixedRegisterOrSmiConstant(right(), ECX)); | 6035 summary->set_in(1, Location::FixedRegisterOrSmiConstant(right(), ECX)); |
6293 summary->set_out(0, Location::SameAsFirstInput()); | 6036 summary->set_out(0, Location::SameAsFirstInput()); |
6294 return summary; | 6037 return summary; |
6295 } | 6038 } |
6296 | 6039 |
6297 | |
6298 void ShiftUint32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6040 void ShiftUint32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
6299 const intptr_t kShifterLimit = 31; | 6041 const intptr_t kShifterLimit = 31; |
6300 | 6042 |
6301 Register left = locs()->in(0).reg(); | 6043 Register left = locs()->in(0).reg(); |
6302 Register out = locs()->out(0).reg(); | 6044 Register out = locs()->out(0).reg(); |
6303 ASSERT(left == out); | 6045 ASSERT(left == out); |
6304 | 6046 |
6305 | |
6306 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryMintOp); | 6047 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryMintOp); |
6307 | 6048 |
6308 if (locs()->in(1).IsConstant()) { | 6049 if (locs()->in(1).IsConstant()) { |
6309 // Shifter is constant. | 6050 // Shifter is constant. |
6310 | 6051 |
6311 const Object& constant = locs()->in(1).constant(); | 6052 const Object& constant = locs()->in(1).constant(); |
6312 ASSERT(constant.IsSmi()); | 6053 ASSERT(constant.IsSmi()); |
6313 const intptr_t shift_value = Smi::Cast(constant).Value(); | 6054 const intptr_t shift_value = Smi::Cast(constant).Value(); |
6314 | 6055 |
6315 | |
6316 // Do the shift: (shift_value > 0) && (shift_value <= kShifterLimit). | 6056 // Do the shift: (shift_value > 0) && (shift_value <= kShifterLimit). |
6317 switch (op_kind()) { | 6057 switch (op_kind()) { |
6318 case Token::kSHR: | 6058 case Token::kSHR: |
6319 __ shrl(left, Immediate(shift_value)); | 6059 __ shrl(left, Immediate(shift_value)); |
6320 break; | 6060 break; |
6321 case Token::kSHL: | 6061 case Token::kSHL: |
6322 __ shll(left, Immediate(shift_value)); | 6062 __ shll(left, Immediate(shift_value)); |
6323 break; | 6063 break; |
6324 default: | 6064 default: |
6325 UNREACHABLE(); | 6065 UNREACHABLE(); |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6359 } | 6099 } |
6360 | 6100 |
6361 __ Bind(&zero); | 6101 __ Bind(&zero); |
6362 // Shift was greater than 31 bits, just return zero. | 6102 // Shift was greater than 31 bits, just return zero. |
6363 __ xorl(left, left); | 6103 __ xorl(left, left); |
6364 | 6104 |
6365 // Exit path. | 6105 // Exit path. |
6366 __ Bind(&done); | 6106 __ Bind(&done); |
6367 } | 6107 } |
6368 | 6108 |
6369 | |
6370 LocationSummary* UnaryUint32OpInstr::MakeLocationSummary(Zone* zone, | 6109 LocationSummary* UnaryUint32OpInstr::MakeLocationSummary(Zone* zone, |
6371 bool opt) const { | 6110 bool opt) const { |
6372 const intptr_t kNumInputs = 1; | 6111 const intptr_t kNumInputs = 1; |
6373 const intptr_t kNumTemps = 0; | 6112 const intptr_t kNumTemps = 0; |
6374 LocationSummary* summary = new (zone) | 6113 LocationSummary* summary = new (zone) |
6375 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 6114 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
6376 summary->set_in(0, Location::RequiresRegister()); | 6115 summary->set_in(0, Location::RequiresRegister()); |
6377 summary->set_out(0, Location::SameAsFirstInput()); | 6116 summary->set_out(0, Location::SameAsFirstInput()); |
6378 return summary; | 6117 return summary; |
6379 } | 6118 } |
6380 | 6119 |
6381 | |
6382 void UnaryUint32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6120 void UnaryUint32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
6383 Register out = locs()->out(0).reg(); | 6121 Register out = locs()->out(0).reg(); |
6384 ASSERT(locs()->in(0).reg() == out); | 6122 ASSERT(locs()->in(0).reg() == out); |
6385 | 6123 |
6386 ASSERT(op_kind() == Token::kBIT_NOT); | 6124 ASSERT(op_kind() == Token::kBIT_NOT); |
6387 | 6125 |
6388 __ notl(out); | 6126 __ notl(out); |
6389 } | 6127 } |
6390 | 6128 |
6391 | |
6392 LocationSummary* UnboxedIntConverterInstr::MakeLocationSummary(Zone* zone, | 6129 LocationSummary* UnboxedIntConverterInstr::MakeLocationSummary(Zone* zone, |
6393 bool opt) const { | 6130 bool opt) const { |
6394 const intptr_t kNumInputs = 1; | 6131 const intptr_t kNumInputs = 1; |
6395 const intptr_t kNumTemps = 0; | 6132 const intptr_t kNumTemps = 0; |
6396 LocationSummary* summary = new (zone) | 6133 LocationSummary* summary = new (zone) |
6397 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 6134 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
6398 if ((from() == kUnboxedInt32 || from() == kUnboxedUint32) && | 6135 if ((from() == kUnboxedInt32 || from() == kUnboxedUint32) && |
6399 (to() == kUnboxedInt32 || to() == kUnboxedUint32)) { | 6136 (to() == kUnboxedInt32 || to() == kUnboxedUint32)) { |
6400 summary->set_in(0, Location::RequiresRegister()); | 6137 summary->set_in(0, Location::RequiresRegister()); |
6401 summary->set_out(0, Location::SameAsFirstInput()); | 6138 summary->set_out(0, Location::SameAsFirstInput()); |
6402 } else if (from() == kUnboxedMint) { | 6139 } else if (from() == kUnboxedMint) { |
6403 summary->set_in( | 6140 summary->set_in( |
6404 0, Location::Pair(CanDeoptimize() ? Location::WritableRegister() | 6141 0, Location::Pair(CanDeoptimize() ? Location::WritableRegister() |
6405 : Location::RequiresRegister(), | 6142 : Location::RequiresRegister(), |
6406 Location::RequiresRegister())); | 6143 Location::RequiresRegister())); |
6407 summary->set_out(0, Location::RequiresRegister()); | 6144 summary->set_out(0, Location::RequiresRegister()); |
6408 } else if (from() == kUnboxedUint32) { | 6145 } else if (from() == kUnboxedUint32) { |
6409 summary->set_in(0, Location::RequiresRegister()); | 6146 summary->set_in(0, Location::RequiresRegister()); |
6410 summary->set_out(0, Location::Pair(Location::RequiresRegister(), | 6147 summary->set_out(0, Location::Pair(Location::RequiresRegister(), |
6411 Location::RequiresRegister())); | 6148 Location::RequiresRegister())); |
6412 } else if (from() == kUnboxedInt32) { | 6149 } else if (from() == kUnboxedInt32) { |
6413 summary->set_in(0, Location::RegisterLocation(EAX)); | 6150 summary->set_in(0, Location::RegisterLocation(EAX)); |
6414 summary->set_out(0, Location::Pair(Location::RegisterLocation(EAX), | 6151 summary->set_out(0, Location::Pair(Location::RegisterLocation(EAX), |
6415 Location::RegisterLocation(EDX))); | 6152 Location::RegisterLocation(EDX))); |
6416 } | 6153 } |
6417 return summary; | 6154 return summary; |
6418 } | 6155 } |
6419 | 6156 |
6420 | |
6421 void UnboxedIntConverterInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6157 void UnboxedIntConverterInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
6422 if (from() == kUnboxedInt32 && to() == kUnboxedUint32) { | 6158 if (from() == kUnboxedInt32 && to() == kUnboxedUint32) { |
6423 // Representations are bitwise equivalent. | 6159 // Representations are bitwise equivalent. |
6424 ASSERT(locs()->out(0).reg() == locs()->in(0).reg()); | 6160 ASSERT(locs()->out(0).reg() == locs()->in(0).reg()); |
6425 } else if (from() == kUnboxedUint32 && to() == kUnboxedInt32) { | 6161 } else if (from() == kUnboxedUint32 && to() == kUnboxedInt32) { |
6426 // Representations are bitwise equivalent. | 6162 // Representations are bitwise equivalent. |
6427 ASSERT(locs()->out(0).reg() == locs()->in(0).reg()); | 6163 ASSERT(locs()->out(0).reg() == locs()->in(0).reg()); |
6428 if (CanDeoptimize()) { | 6164 if (CanDeoptimize()) { |
6429 Label* deopt = | 6165 Label* deopt = |
6430 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnboxInteger); | 6166 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnboxInteger); |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6466 Register out_lo = out_pair->At(0).reg(); | 6202 Register out_lo = out_pair->At(0).reg(); |
6467 Register out_hi = out_pair->At(1).reg(); | 6203 Register out_hi = out_pair->At(1).reg(); |
6468 ASSERT(locs()->in(0).reg() == EAX); | 6204 ASSERT(locs()->in(0).reg() == EAX); |
6469 ASSERT(out_lo == EAX && out_hi == EDX); | 6205 ASSERT(out_lo == EAX && out_hi == EDX); |
6470 __ cdq(); | 6206 __ cdq(); |
6471 } else { | 6207 } else { |
6472 UNREACHABLE(); | 6208 UNREACHABLE(); |
6473 } | 6209 } |
6474 } | 6210 } |
6475 | 6211 |
6476 | |
6477 LocationSummary* ThrowInstr::MakeLocationSummary(Zone* zone, bool opt) const { | 6212 LocationSummary* ThrowInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
6478 return new (zone) LocationSummary(zone, 0, 0, LocationSummary::kCall); | 6213 return new (zone) LocationSummary(zone, 0, 0, LocationSummary::kCall); |
6479 } | 6214 } |
6480 | 6215 |
6481 | |
6482 void ThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6216 void ThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
6483 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), kThrowRuntimeEntry, 1, | 6217 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), kThrowRuntimeEntry, 1, |
6484 locs()); | 6218 locs()); |
6485 __ int3(); | 6219 __ int3(); |
6486 } | 6220 } |
6487 | 6221 |
6488 | |
6489 LocationSummary* ReThrowInstr::MakeLocationSummary(Zone* zone, bool opt) const { | 6222 LocationSummary* ReThrowInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
6490 return new (zone) LocationSummary(zone, 0, 0, LocationSummary::kCall); | 6223 return new (zone) LocationSummary(zone, 0, 0, LocationSummary::kCall); |
6491 } | 6224 } |
6492 | 6225 |
6493 | |
6494 void ReThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6226 void ReThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
6495 compiler->SetNeedsStackTrace(catch_try_index()); | 6227 compiler->SetNeedsStackTrace(catch_try_index()); |
6496 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), kReThrowRuntimeEntry, | 6228 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), kReThrowRuntimeEntry, |
6497 2, locs()); | 6229 2, locs()); |
6498 __ int3(); | 6230 __ int3(); |
6499 } | 6231 } |
6500 | 6232 |
6501 | |
6502 LocationSummary* StopInstr::MakeLocationSummary(Zone* zone, bool opt) const { | 6233 LocationSummary* StopInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
6503 return new (zone) LocationSummary(zone, 0, 0, LocationSummary::kNoCall); | 6234 return new (zone) LocationSummary(zone, 0, 0, LocationSummary::kNoCall); |
6504 } | 6235 } |
6505 | 6236 |
6506 | |
6507 void StopInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6237 void StopInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
6508 __ Stop(message()); | 6238 __ Stop(message()); |
6509 } | 6239 } |
6510 | 6240 |
6511 | |
6512 void GraphEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6241 void GraphEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
6513 if (!compiler->CanFallThroughTo(normal_entry())) { | 6242 if (!compiler->CanFallThroughTo(normal_entry())) { |
6514 __ jmp(compiler->GetJumpLabel(normal_entry())); | 6243 __ jmp(compiler->GetJumpLabel(normal_entry())); |
6515 } | 6244 } |
6516 } | 6245 } |
6517 | 6246 |
6518 | |
6519 LocationSummary* GotoInstr::MakeLocationSummary(Zone* zone, bool opt) const { | 6247 LocationSummary* GotoInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
6520 return new (zone) LocationSummary(zone, 0, 0, LocationSummary::kNoCall); | 6248 return new (zone) LocationSummary(zone, 0, 0, LocationSummary::kNoCall); |
6521 } | 6249 } |
6522 | 6250 |
6523 | |
6524 void GotoInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6251 void GotoInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
6525 if (!compiler->is_optimizing()) { | 6252 if (!compiler->is_optimizing()) { |
6526 if (FLAG_reorder_basic_blocks) { | 6253 if (FLAG_reorder_basic_blocks) { |
6527 compiler->EmitEdgeCounter(block()->preorder_number()); | 6254 compiler->EmitEdgeCounter(block()->preorder_number()); |
6528 } | 6255 } |
6529 // Add a deoptimization descriptor for deoptimizing instructions that | 6256 // Add a deoptimization descriptor for deoptimizing instructions that |
6530 // may be inserted before this instruction. | 6257 // may be inserted before this instruction. |
6531 compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt, GetDeoptId(), | 6258 compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt, GetDeoptId(), |
6532 TokenPosition::kNoSource); | 6259 TokenPosition::kNoSource); |
6533 } | 6260 } |
6534 if (HasParallelMove()) { | 6261 if (HasParallelMove()) { |
6535 compiler->parallel_move_resolver()->EmitNativeCode(parallel_move()); | 6262 compiler->parallel_move_resolver()->EmitNativeCode(parallel_move()); |
6536 } | 6263 } |
6537 | 6264 |
6538 // We can fall through if the successor is the next block in the list. | 6265 // We can fall through if the successor is the next block in the list. |
6539 // Otherwise, we need a jump. | 6266 // Otherwise, we need a jump. |
6540 if (!compiler->CanFallThroughTo(successor())) { | 6267 if (!compiler->CanFallThroughTo(successor())) { |
6541 __ jmp(compiler->GetJumpLabel(successor())); | 6268 __ jmp(compiler->GetJumpLabel(successor())); |
6542 } | 6269 } |
6543 } | 6270 } |
6544 | 6271 |
6545 | |
6546 LocationSummary* IndirectGotoInstr::MakeLocationSummary(Zone* zone, | 6272 LocationSummary* IndirectGotoInstr::MakeLocationSummary(Zone* zone, |
6547 bool opt) const { | 6273 bool opt) const { |
6548 const intptr_t kNumInputs = 1; | 6274 const intptr_t kNumInputs = 1; |
6549 const intptr_t kNumTemps = 1; | 6275 const intptr_t kNumTemps = 1; |
6550 | 6276 |
6551 LocationSummary* summary = new (zone) | 6277 LocationSummary* summary = new (zone) |
6552 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 6278 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
6553 | 6279 |
6554 summary->set_in(0, Location::RequiresRegister()); | 6280 summary->set_in(0, Location::RequiresRegister()); |
6555 summary->set_temp(0, Location::RequiresRegister()); | 6281 summary->set_temp(0, Location::RequiresRegister()); |
6556 | 6282 |
6557 return summary; | 6283 return summary; |
6558 } | 6284 } |
6559 | 6285 |
6560 | |
6561 void IndirectGotoInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6286 void IndirectGotoInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
6562 Register target_reg = locs()->temp_slot(0)->reg(); | 6287 Register target_reg = locs()->temp_slot(0)->reg(); |
6563 | 6288 |
6564 // Load code object from frame. | 6289 // Load code object from frame. |
6565 __ movl(target_reg, Address(EBP, kPcMarkerSlotFromFp * kWordSize)); | 6290 __ movl(target_reg, Address(EBP, kPcMarkerSlotFromFp * kWordSize)); |
6566 // Load instructions object (active_instructions and Code::entry_point() may | 6291 // Load instructions object (active_instructions and Code::entry_point() may |
6567 // not point to this instruction object any more; see Code::DisableDartCode). | 6292 // not point to this instruction object any more; see Code::DisableDartCode). |
6568 __ movl(target_reg, | 6293 __ movl(target_reg, |
6569 FieldAddress(target_reg, Code::saved_instructions_offset())); | 6294 FieldAddress(target_reg, Code::saved_instructions_offset())); |
6570 __ addl(target_reg, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); | 6295 __ addl(target_reg, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); |
6571 | 6296 |
6572 // Add the offset. | 6297 // Add the offset. |
6573 Register offset_reg = locs()->in(0).reg(); | 6298 Register offset_reg = locs()->in(0).reg(); |
6574 if (offset()->definition()->representation() == kTagged) { | 6299 if (offset()->definition()->representation() == kTagged) { |
6575 __ SmiUntag(offset_reg); | 6300 __ SmiUntag(offset_reg); |
6576 } | 6301 } |
6577 __ addl(target_reg, offset_reg); | 6302 __ addl(target_reg, offset_reg); |
6578 | 6303 |
6579 // Jump to the absolute address. | 6304 // Jump to the absolute address. |
6580 __ jmp(target_reg); | 6305 __ jmp(target_reg); |
6581 } | 6306 } |
6582 | 6307 |
6583 | |
6584 LocationSummary* StrictCompareInstr::MakeLocationSummary(Zone* zone, | 6308 LocationSummary* StrictCompareInstr::MakeLocationSummary(Zone* zone, |
6585 bool opt) const { | 6309 bool opt) const { |
6586 const intptr_t kNumInputs = 2; | 6310 const intptr_t kNumInputs = 2; |
6587 const intptr_t kNumTemps = 0; | 6311 const intptr_t kNumTemps = 0; |
6588 if (needs_number_check()) { | 6312 if (needs_number_check()) { |
6589 LocationSummary* locs = new (zone) | 6313 LocationSummary* locs = new (zone) |
6590 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 6314 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
6591 locs->set_in(0, Location::RegisterLocation(EAX)); | 6315 locs->set_in(0, Location::RegisterLocation(EAX)); |
6592 locs->set_in(1, Location::RegisterLocation(ECX)); | 6316 locs->set_in(1, Location::RegisterLocation(ECX)); |
6593 locs->set_out(0, Location::RegisterLocation(EAX)); | 6317 locs->set_out(0, Location::RegisterLocation(EAX)); |
6594 return locs; | 6318 return locs; |
6595 } | 6319 } |
6596 LocationSummary* locs = new (zone) | 6320 LocationSummary* locs = new (zone) |
6597 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 6321 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
6598 locs->set_in(0, Location::RegisterOrConstant(left())); | 6322 locs->set_in(0, Location::RegisterOrConstant(left())); |
6599 // Only one of the inputs can be a constant. Choose register if the first one | 6323 // Only one of the inputs can be a constant. Choose register if the first one |
6600 // is a constant. | 6324 // is a constant. |
6601 locs->set_in(1, locs->in(0).IsConstant() | 6325 locs->set_in(1, locs->in(0).IsConstant() |
6602 ? Location::RequiresRegister() | 6326 ? Location::RequiresRegister() |
6603 : Location::RegisterOrConstant(right())); | 6327 : Location::RegisterOrConstant(right())); |
6604 locs->set_out(0, Location::RequiresRegister()); | 6328 locs->set_out(0, Location::RequiresRegister()); |
6605 return locs; | 6329 return locs; |
6606 } | 6330 } |
6607 | 6331 |
6608 | |
6609 Condition StrictCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler, | 6332 Condition StrictCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
6610 BranchLabels labels) { | 6333 BranchLabels labels) { |
6611 Location left = locs()->in(0); | 6334 Location left = locs()->in(0); |
6612 Location right = locs()->in(1); | 6335 Location right = locs()->in(1); |
6613 ASSERT(!left.IsConstant() || !right.IsConstant()); | 6336 ASSERT(!left.IsConstant() || !right.IsConstant()); |
6614 Condition true_condition; | 6337 Condition true_condition; |
6615 if (left.IsConstant()) { | 6338 if (left.IsConstant()) { |
6616 true_condition = compiler->EmitEqualityRegConstCompare( | 6339 true_condition = compiler->EmitEqualityRegConstCompare( |
6617 right.reg(), left.constant(), needs_number_check(), token_pos(), | 6340 right.reg(), left.constant(), needs_number_check(), token_pos(), |
6618 deopt_id_); | 6341 deopt_id_); |
6619 } else if (right.IsConstant()) { | 6342 } else if (right.IsConstant()) { |
6620 true_condition = compiler->EmitEqualityRegConstCompare( | 6343 true_condition = compiler->EmitEqualityRegConstCompare( |
6621 left.reg(), right.constant(), needs_number_check(), token_pos(), | 6344 left.reg(), right.constant(), needs_number_check(), token_pos(), |
6622 deopt_id_); | 6345 deopt_id_); |
6623 } else { | 6346 } else { |
6624 true_condition = compiler->EmitEqualityRegRegCompare( | 6347 true_condition = compiler->EmitEqualityRegRegCompare( |
6625 left.reg(), right.reg(), needs_number_check(), token_pos(), deopt_id_); | 6348 left.reg(), right.reg(), needs_number_check(), token_pos(), deopt_id_); |
6626 } | 6349 } |
6627 if (kind() != Token::kEQ_STRICT) { | 6350 if (kind() != Token::kEQ_STRICT) { |
6628 ASSERT(kind() == Token::kNE_STRICT); | 6351 ASSERT(kind() == Token::kNE_STRICT); |
6629 true_condition = NegateCondition(true_condition); | 6352 true_condition = NegateCondition(true_condition); |
6630 } | 6353 } |
6631 return true_condition; | 6354 return true_condition; |
6632 } | 6355 } |
6633 | 6356 |
6634 | |
6635 // Detect pattern when one value is zero and another is a power of 2. | 6357 // Detect pattern when one value is zero and another is a power of 2. |
6636 static bool IsPowerOfTwoKind(intptr_t v1, intptr_t v2) { | 6358 static bool IsPowerOfTwoKind(intptr_t v1, intptr_t v2) { |
6637 return (Utils::IsPowerOfTwo(v1) && (v2 == 0)) || | 6359 return (Utils::IsPowerOfTwo(v1) && (v2 == 0)) || |
6638 (Utils::IsPowerOfTwo(v2) && (v1 == 0)); | 6360 (Utils::IsPowerOfTwo(v2) && (v1 == 0)); |
6639 } | 6361 } |
6640 | 6362 |
6641 | |
6642 LocationSummary* IfThenElseInstr::MakeLocationSummary(Zone* zone, | 6363 LocationSummary* IfThenElseInstr::MakeLocationSummary(Zone* zone, |
6643 bool opt) const { | 6364 bool opt) const { |
6644 comparison()->InitializeLocationSummary(zone, opt); | 6365 comparison()->InitializeLocationSummary(zone, opt); |
6645 // TODO(vegorov): support byte register constraints in the register allocator. | 6366 // TODO(vegorov): support byte register constraints in the register allocator. |
6646 comparison()->locs()->set_out(0, Location::RegisterLocation(EDX)); | 6367 comparison()->locs()->set_out(0, Location::RegisterLocation(EDX)); |
6647 return comparison()->locs(); | 6368 return comparison()->locs(); |
6648 } | 6369 } |
6649 | 6370 |
6650 | |
6651 void IfThenElseInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6371 void IfThenElseInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
6652 ASSERT(locs()->out(0).reg() == EDX); | 6372 ASSERT(locs()->out(0).reg() == EDX); |
6653 | 6373 |
6654 // Clear upper part of the out register. We are going to use setcc on it | 6374 // Clear upper part of the out register. We are going to use setcc on it |
6655 // which is a byte move. | 6375 // which is a byte move. |
6656 __ xorl(EDX, EDX); | 6376 __ xorl(EDX, EDX); |
6657 | 6377 |
6658 // Emit comparison code. This must not overwrite the result register. | 6378 // Emit comparison code. This must not overwrite the result register. |
6659 // IfThenElseInstr::Supports() should prevent EmitComparisonCode from using | 6379 // IfThenElseInstr::Supports() should prevent EmitComparisonCode from using |
6660 // the labels or returning an invalid condition. | 6380 // the labels or returning an invalid condition. |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6692 } else { | 6412 } else { |
6693 __ decl(EDX); | 6413 __ decl(EDX); |
6694 __ andl(EDX, | 6414 __ andl(EDX, |
6695 Immediate(Smi::RawValue(true_value) - Smi::RawValue(false_value))); | 6415 Immediate(Smi::RawValue(true_value) - Smi::RawValue(false_value))); |
6696 if (false_value != 0) { | 6416 if (false_value != 0) { |
6697 __ addl(EDX, Immediate(Smi::RawValue(false_value))); | 6417 __ addl(EDX, Immediate(Smi::RawValue(false_value))); |
6698 } | 6418 } |
6699 } | 6419 } |
6700 } | 6420 } |
6701 | 6421 |
6702 | |
6703 LocationSummary* ClosureCallInstr::MakeLocationSummary(Zone* zone, | 6422 LocationSummary* ClosureCallInstr::MakeLocationSummary(Zone* zone, |
6704 bool opt) const { | 6423 bool opt) const { |
6705 const intptr_t kNumInputs = 1; | 6424 const intptr_t kNumInputs = 1; |
6706 const intptr_t kNumTemps = 0; | 6425 const intptr_t kNumTemps = 0; |
6707 LocationSummary* summary = new (zone) | 6426 LocationSummary* summary = new (zone) |
6708 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 6427 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
6709 summary->set_in(0, Location::RegisterLocation(EAX)); // Function. | 6428 summary->set_in(0, Location::RegisterLocation(EAX)); // Function. |
6710 summary->set_out(0, Location::RegisterLocation(EAX)); | 6429 summary->set_out(0, Location::RegisterLocation(EAX)); |
6711 return summary; | 6430 return summary; |
6712 } | 6431 } |
6713 | 6432 |
6714 | |
6715 void ClosureCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6433 void ClosureCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
6716 // Load arguments descriptor. | 6434 // Load arguments descriptor. |
6717 const intptr_t argument_count = ArgumentCount(); // Includes type args. | 6435 const intptr_t argument_count = ArgumentCount(); // Includes type args. |
6718 const Array& arguments_descriptor = | 6436 const Array& arguments_descriptor = |
6719 Array::ZoneHandle(Z, GetArgumentsDescriptor()); | 6437 Array::ZoneHandle(Z, GetArgumentsDescriptor()); |
6720 __ LoadObject(EDX, arguments_descriptor); | 6438 __ LoadObject(EDX, arguments_descriptor); |
6721 | 6439 |
6722 // EBX: Code (compiled code or lazy compile stub). | 6440 // EBX: Code (compiled code or lazy compile stub). |
6723 ASSERT(locs()->in(0).reg() == EAX); | 6441 ASSERT(locs()->in(0).reg() == EAX); |
6724 __ movl(EBX, FieldAddress(EAX, Function::entry_point_offset())); | 6442 __ movl(EBX, FieldAddress(EAX, Function::entry_point_offset())); |
(...skipping 11 matching lines...) Expand all Loading... |
6736 compiler->AddDeoptIndexAtCall(deopt_id_after); | 6454 compiler->AddDeoptIndexAtCall(deopt_id_after); |
6737 } | 6455 } |
6738 // Add deoptimization continuation point after the call and before the | 6456 // Add deoptimization continuation point after the call and before the |
6739 // arguments are removed. | 6457 // arguments are removed. |
6740 // In optimized code this descriptor is needed for exception handling. | 6458 // In optimized code this descriptor is needed for exception handling. |
6741 compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt, deopt_id_after, | 6459 compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt, deopt_id_after, |
6742 token_pos()); | 6460 token_pos()); |
6743 __ Drop(argument_count); | 6461 __ Drop(argument_count); |
6744 } | 6462 } |
6745 | 6463 |
6746 | |
6747 LocationSummary* BooleanNegateInstr::MakeLocationSummary(Zone* zone, | 6464 LocationSummary* BooleanNegateInstr::MakeLocationSummary(Zone* zone, |
6748 bool opt) const { | 6465 bool opt) const { |
6749 return LocationSummary::Make(zone, 1, Location::RequiresRegister(), | 6466 return LocationSummary::Make(zone, 1, Location::RequiresRegister(), |
6750 LocationSummary::kNoCall); | 6467 LocationSummary::kNoCall); |
6751 } | 6468 } |
6752 | 6469 |
6753 | |
6754 void BooleanNegateInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6470 void BooleanNegateInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
6755 Register value = locs()->in(0).reg(); | 6471 Register value = locs()->in(0).reg(); |
6756 Register result = locs()->out(0).reg(); | 6472 Register result = locs()->out(0).reg(); |
6757 | 6473 |
6758 Label done; | 6474 Label done; |
6759 __ LoadObject(result, Bool::True()); | 6475 __ LoadObject(result, Bool::True()); |
6760 __ CompareRegisters(result, value); | 6476 __ CompareRegisters(result, value); |
6761 __ j(NOT_EQUAL, &done, Assembler::kNearJump); | 6477 __ j(NOT_EQUAL, &done, Assembler::kNearJump); |
6762 __ LoadObject(result, Bool::False()); | 6478 __ LoadObject(result, Bool::False()); |
6763 __ Bind(&done); | 6479 __ Bind(&done); |
6764 } | 6480 } |
6765 | 6481 |
6766 | |
6767 LocationSummary* AllocateObjectInstr::MakeLocationSummary(Zone* zone, | 6482 LocationSummary* AllocateObjectInstr::MakeLocationSummary(Zone* zone, |
6768 bool opt) const { | 6483 bool opt) const { |
6769 return MakeCallSummary(zone); | 6484 return MakeCallSummary(zone); |
6770 } | 6485 } |
6771 | 6486 |
6772 | |
6773 void AllocateObjectInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6487 void AllocateObjectInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
6774 const Code& stub = Code::ZoneHandle( | 6488 const Code& stub = Code::ZoneHandle( |
6775 compiler->zone(), StubCode::GetAllocationStubForClass(cls())); | 6489 compiler->zone(), StubCode::GetAllocationStubForClass(cls())); |
6776 const StubEntry stub_entry(stub); | 6490 const StubEntry stub_entry(stub); |
6777 compiler->GenerateCall(token_pos(), stub_entry, RawPcDescriptors::kOther, | 6491 compiler->GenerateCall(token_pos(), stub_entry, RawPcDescriptors::kOther, |
6778 locs()); | 6492 locs()); |
6779 compiler->AddStubCallTarget(stub); | 6493 compiler->AddStubCallTarget(stub); |
6780 __ Drop(ArgumentCount()); // Discard arguments. | 6494 __ Drop(ArgumentCount()); // Discard arguments. |
6781 } | 6495 } |
6782 | 6496 |
6783 | |
6784 void DebugStepCheckInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6497 void DebugStepCheckInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
6785 ASSERT(!compiler->is_optimizing()); | 6498 ASSERT(!compiler->is_optimizing()); |
6786 __ Call(*StubCode::DebugStepCheck_entry()); | 6499 __ Call(*StubCode::DebugStepCheck_entry()); |
6787 compiler->EmitCallsiteMetaData(token_pos(), deopt_id_, stub_kind_, locs()); | 6500 compiler->EmitCallsiteMetaData(token_pos(), deopt_id_, stub_kind_, locs()); |
6788 } | 6501 } |
6789 | 6502 |
6790 | |
6791 } // namespace dart | 6503 } // namespace dart |
6792 | 6504 |
6793 #undef __ | 6505 #undef __ |
6794 | 6506 |
6795 #endif // defined TARGET_ARCH_IA32 | 6507 #endif // defined TARGET_ARCH_IA32 |
OLD | NEW |