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/dart_entry.h" | 10 #include "vm/dart_entry.h" |
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
168 if (kNumTemps == 1) { | 168 if (kNumTemps == 1) { |
169 locs->set_temp(0, Location::RequiresRegister()); | 169 locs->set_temp(0, Location::RequiresRegister()); |
170 } | 170 } |
171 return locs; | 171 return locs; |
172 } | 172 } |
173 | 173 |
174 | 174 |
175 void UnboxedConstantInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 175 void UnboxedConstantInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
176 // The register allocator drops constant definitions that have no uses. | 176 // The register allocator drops constant definitions that have no uses. |
177 if (!locs()->out(0).IsInvalid()) { | 177 if (!locs()->out(0).IsInvalid()) { |
178 XmmRegister result = locs()->out(0).fpu_reg(); | 178 switch (representation()) { |
179 if (constant_address() == 0) { | 179 case kUnboxedDouble: { |
180 Register boxed = locs()->temp(0).reg(); | 180 XmmRegister result = locs()->out(0).fpu_reg(); |
181 __ LoadObjectSafely(boxed, value()); | 181 if (constant_address() == 0) { |
182 __ movsd(result, FieldAddress(boxed, Double::value_offset())); | 182 Register boxed = locs()->temp(0).reg(); |
183 } else if (Utils::DoublesBitEqual(Double::Cast(value()).value(), 0.0)) { | 183 __ LoadObjectSafely(boxed, value()); |
184 __ xorps(result, result); | 184 __ movsd(result, FieldAddress(boxed, Double::value_offset())); |
185 } else { | 185 } else if (Utils::DoublesBitEqual(Double::Cast(value()).value(), 0.0)) { |
186 __ movsd(result, Address::Absolute(constant_address())); | 186 __ xorps(result, result); |
187 } else { | |
188 __ movsd(result, Address::Absolute(constant_address())); | |
189 } | |
190 break; | |
191 } | |
192 case kUnboxedInt32: | |
193 __ movl(locs()->out(0).reg(), Immediate(Smi::Cast(value()).Value())); | |
194 break; | |
195 default: | |
196 UNREACHABLE(); | |
187 } | 197 } |
188 } | 198 } |
189 } | 199 } |
190 | 200 |
191 | 201 |
192 LocationSummary* AssertAssignableInstr::MakeLocationSummary(Isolate* isolate, | 202 LocationSummary* AssertAssignableInstr::MakeLocationSummary(Isolate* isolate, |
193 bool opt) const { | 203 bool opt) const { |
194 const intptr_t kNumInputs = 3; | 204 const intptr_t kNumInputs = 3; |
195 const intptr_t kNumTemps = 0; | 205 const intptr_t kNumTemps = 0; |
196 LocationSummary* summary = new(isolate) LocationSummary( | 206 LocationSummary* summary = new(isolate) LocationSummary( |
(...skipping 838 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1035 | 1045 |
1036 LocationSummary* LoadIndexedInstr::MakeLocationSummary(Isolate* isolate, | 1046 LocationSummary* LoadIndexedInstr::MakeLocationSummary(Isolate* isolate, |
1037 bool opt) const { | 1047 bool opt) const { |
1038 const intptr_t kNumInputs = 2; | 1048 const intptr_t kNumInputs = 2; |
1039 const intptr_t kNumTemps = 0; | 1049 const intptr_t kNumTemps = 0; |
1040 LocationSummary* locs = new(isolate) LocationSummary( | 1050 LocationSummary* locs = new(isolate) LocationSummary( |
1041 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1051 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
1042 locs->set_in(0, Location::RequiresRegister()); | 1052 locs->set_in(0, Location::RequiresRegister()); |
1043 if (CanBeImmediateIndex(index(), class_id())) { | 1053 if (CanBeImmediateIndex(index(), class_id())) { |
1044 // CanBeImmediateIndex must return false for unsafe smis. | 1054 // CanBeImmediateIndex must return false for unsafe smis. |
1045 locs->set_in(1, Location::Constant(index()->BoundConstant())); | 1055 locs->set_in(1, Location::Constant(index()->definition()->AsConstant())); |
1046 } else { | 1056 } else { |
1047 // The index is either untagged (element size == 1) or a smi (for all | 1057 // The index is either untagged (element size == 1) or a smi (for all |
1048 // element sizes > 1). | 1058 // element sizes > 1). |
1049 locs->set_in(1, (index_scale() == 1) | 1059 locs->set_in(1, (index_scale() == 1) |
1050 ? Location::WritableRegister() | 1060 ? Location::WritableRegister() |
1051 : Location::RequiresRegister()); | 1061 : Location::RequiresRegister()); |
1052 } | 1062 } |
1053 if ((representation() == kUnboxedDouble) || | 1063 if ((representation() == kUnboxedDouble) || |
1054 (representation() == kUnboxedFloat32x4) || | 1064 (representation() == kUnboxedFloat32x4) || |
1055 (representation() == kUnboxedInt32x4) || | 1065 (representation() == kUnboxedInt32x4) || |
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1231 | 1241 |
1232 LocationSummary* StoreIndexedInstr::MakeLocationSummary(Isolate* isolate, | 1242 LocationSummary* StoreIndexedInstr::MakeLocationSummary(Isolate* isolate, |
1233 bool opt) const { | 1243 bool opt) const { |
1234 const intptr_t kNumInputs = 3; | 1244 const intptr_t kNumInputs = 3; |
1235 const intptr_t kNumTemps = 0; | 1245 const intptr_t kNumTemps = 0; |
1236 LocationSummary* locs = new(isolate) LocationSummary( | 1246 LocationSummary* locs = new(isolate) LocationSummary( |
1237 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1247 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
1238 locs->set_in(0, Location::RequiresRegister()); | 1248 locs->set_in(0, Location::RequiresRegister()); |
1239 if (CanBeImmediateIndex(index(), class_id())) { | 1249 if (CanBeImmediateIndex(index(), class_id())) { |
1240 // CanBeImmediateIndex must return false for unsafe smis. | 1250 // CanBeImmediateIndex must return false for unsafe smis. |
1241 locs->set_in(1, Location::Constant(index()->BoundConstant())); | 1251 locs->set_in(1, Location::Constant(index()->definition()->AsConstant())); |
1242 } else { | 1252 } else { |
1243 // The index is either untagged (element size == 1) or a smi (for all | 1253 // The index is either untagged (element size == 1) or a smi (for all |
1244 // element sizes > 1). | 1254 // element sizes > 1). |
1245 locs->set_in(1, (index_scale() == 1) | 1255 locs->set_in(1, (index_scale() == 1) |
1246 ? Location::WritableRegister() | 1256 ? Location::WritableRegister() |
1247 : Location::RequiresRegister()); | 1257 : Location::RequiresRegister()); |
1248 } | 1258 } |
1249 switch (class_id()) { | 1259 switch (class_id()) { |
1250 case kArrayCid: | 1260 case kArrayCid: |
1251 locs->set_in(2, ShouldEmitStoreBarrier() | 1261 locs->set_in(2, ShouldEmitStoreBarrier() |
(...skipping 1516 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2768 bool opt) const { | 2778 bool opt) const { |
2769 const intptr_t kNumInputs = 2; | 2779 const intptr_t kNumInputs = 2; |
2770 if (op_kind() == Token::kTRUNCDIV) { | 2780 if (op_kind() == Token::kTRUNCDIV) { |
2771 const intptr_t kNumTemps = 1; | 2781 const intptr_t kNumTemps = 1; |
2772 LocationSummary* summary = new(isolate) LocationSummary( | 2782 LocationSummary* summary = new(isolate) LocationSummary( |
2773 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 2783 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
2774 if (RightIsPowerOfTwoConstant()) { | 2784 if (RightIsPowerOfTwoConstant()) { |
2775 summary->set_in(0, Location::RequiresRegister()); | 2785 summary->set_in(0, Location::RequiresRegister()); |
2776 ConstantInstr* right_constant = right()->definition()->AsConstant(); | 2786 ConstantInstr* right_constant = right()->definition()->AsConstant(); |
2777 // The programmer only controls one bit, so the constant is safe. | 2787 // The programmer only controls one bit, so the constant is safe. |
2778 summary->set_in(1, Location::Constant(right_constant->value())); | 2788 summary->set_in(1, Location::Constant(right_constant)); |
2779 summary->set_temp(0, Location::RequiresRegister()); | 2789 summary->set_temp(0, Location::RequiresRegister()); |
2780 summary->set_out(0, Location::SameAsFirstInput()); | 2790 summary->set_out(0, Location::SameAsFirstInput()); |
2781 } else { | 2791 } else { |
2782 // Both inputs must be writable because they will be untagged. | 2792 // Both inputs must be writable because they will be untagged. |
2783 summary->set_in(0, Location::RegisterLocation(EAX)); | 2793 summary->set_in(0, Location::RegisterLocation(EAX)); |
2784 summary->set_in(1, Location::WritableRegister()); | 2794 summary->set_in(1, Location::WritableRegister()); |
2785 summary->set_out(0, Location::SameAsFirstInput()); | 2795 summary->set_out(0, Location::SameAsFirstInput()); |
2786 // Will be used for sign extension and division. | 2796 // Will be used for sign extension and division. |
2787 summary->set_temp(0, Location::RegisterLocation(EDX)); | 2797 summary->set_temp(0, Location::RegisterLocation(EDX)); |
2788 } | 2798 } |
(...skipping 343 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3132 UNREACHABLE(); | 3142 UNREACHABLE(); |
3133 break; | 3143 break; |
3134 } | 3144 } |
3135 default: | 3145 default: |
3136 UNREACHABLE(); | 3146 UNREACHABLE(); |
3137 break; | 3147 break; |
3138 } | 3148 } |
3139 } | 3149 } |
3140 | 3150 |
3141 | 3151 |
3152 LocationSummary* BinaryInt32OpInstr::MakeLocationSummary(Isolate* isolate, | |
3153 bool opt) const { | |
3154 const intptr_t kNumInputs = 2; | |
3155 if (op_kind() == Token::kTRUNCDIV) { | |
3156 UNREACHABLE(); | |
3157 return NULL; | |
3158 } else if (op_kind() == Token::kMOD) { | |
3159 UNREACHABLE(); | |
3160 return NULL; | |
3161 } else if (op_kind() == Token::kSHR) { | |
3162 const intptr_t kNumTemps = 0; | |
3163 LocationSummary* summary = new(isolate) LocationSummary( | |
3164 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | |
3165 summary->set_in(0, Location::RequiresRegister()); | |
3166 summary->set_in(1, Location::FixedRegisterOrSmiConstant(right(), ECX)); | |
3167 summary->set_out(0, Location::SameAsFirstInput()); | |
3168 return summary; | |
3169 } else if (op_kind() == Token::kSHL) { | |
3170 const intptr_t kNumTemps = !IsTruncating() ? 1 : 0; | |
3171 LocationSummary* summary = new(isolate) LocationSummary( | |
3172 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | |
3173 summary->set_in(0, Location::RequiresRegister()); | |
3174 summary->set_in(1, Location::FixedRegisterOrSmiConstant(right(), ECX)); | |
3175 if (!IsTruncating()) { | |
3176 summary->set_temp(0, Location::RequiresRegister()); | |
3177 } | |
3178 summary->set_out(0, Location::SameAsFirstInput()); | |
3179 return summary; | |
3180 } else { | |
3181 const intptr_t kNumTemps = 0; | |
3182 LocationSummary* summary = new(isolate) LocationSummary( | |
3183 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | |
3184 summary->set_in(0, Location::RequiresRegister()); | |
3185 ConstantInstr* constant = right()->definition()->AsConstant(); | |
3186 if (constant == NULL) { | |
3187 if (right()->definition()->IsUnboxedConstant()) { | |
3188 asm("int $3"); | |
Florian Schneider
2014/08/27 09:36:51
Remove debugging left-over?
Vyacheslav Egorov (Google)
2014/08/27 11:45:37
Done.
| |
3189 } | |
3190 } | |
3191 if (constant != NULL) { | |
3192 summary->set_in(1, Location::RegisterOrSmiConstant(right())); | |
3193 } else { | |
3194 summary->set_in(1, Location::PrefersRegister()); | |
3195 } | |
3196 summary->set_out(0, Location::SameAsFirstInput()); | |
3197 return summary; | |
3198 } | |
3199 } | |
3200 | |
3201 | |
3202 static void EmitInt32ShiftLeft(FlowGraphCompiler* compiler, | |
3203 BinaryInt32OpInstr* shift_left) { | |
3204 const bool is_truncating = shift_left->IsTruncating(); | |
3205 const LocationSummary& locs = *shift_left->locs(); | |
3206 Register left = locs.in(0).reg(); | |
3207 Register result = locs.out(0).reg(); | |
3208 ASSERT(left == result); | |
3209 Label* deopt = shift_left->CanDeoptimize() ? | |
3210 compiler->AddDeoptStub(shift_left->deopt_id(), ICData::kDeoptBinarySmiOp) | |
3211 : NULL; | |
3212 ASSERT(locs.in(1).IsConstant()); | |
3213 | |
3214 const Object& constant = locs.in(1).constant(); | |
3215 ASSERT(constant.IsSmi()); | |
3216 // shll operation masks the count to 5 bits. | |
3217 const intptr_t kCountLimit = 0x1F; | |
3218 const intptr_t value = Smi::Cast(constant).Value(); | |
3219 if (value == 0) { | |
3220 // No code needed. | |
3221 } else if ((value < 0) || (value >= kCountLimit)) { | |
3222 // This condition may not be known earlier in some cases because | |
3223 // of constant propagation, inlining, etc. | |
3224 if ((value >= kCountLimit) && is_truncating) { | |
3225 __ xorl(result, result); | |
3226 } else { | |
3227 // Result is Mint or exception. | |
3228 __ jmp(deopt); | |
3229 } | |
3230 } else { | |
3231 if (!is_truncating) { | |
3232 // Check for overflow. | |
3233 Register temp = locs.temp(0).reg(); | |
3234 __ movl(temp, left); | |
3235 __ shll(left, Immediate(value)); | |
3236 __ sarl(left, Immediate(value)); | |
3237 __ cmpl(left, temp); | |
3238 __ j(NOT_EQUAL, deopt); // Overflow. | |
3239 } | |
3240 // Shift for result now we know there is no overflow. | |
3241 __ shll(left, Immediate(value)); | |
3242 } | |
3243 } | |
3244 | |
3245 | |
3246 void BinaryInt32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | |
3247 if (op_kind() == Token::kSHL) { | |
3248 EmitInt32ShiftLeft(compiler, this); | |
3249 return; | |
3250 } | |
3251 | |
3252 Register left = locs()->in(0).reg(); | |
3253 Register result = locs()->out(0).reg(); | |
3254 ASSERT(left == result); | |
3255 Label* deopt = NULL; | |
3256 if (CanDeoptimize()) { | |
3257 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinarySmiOp); | |
3258 } | |
3259 | |
3260 if (locs()->in(1).IsConstant()) { | |
3261 const Object& constant = locs()->in(1).constant(); | |
3262 ASSERT(constant.IsSmi()); | |
3263 const intptr_t value = Smi::Cast(constant).Value(); | |
3264 switch (op_kind()) { | |
3265 case Token::kADD: | |
3266 if (value != 0) { | |
3267 // Checking overflow without emitting an instruction would be wrong. | |
3268 __ addl(left, Immediate(value)); | |
3269 if (deopt != NULL) __ j(OVERFLOW, deopt); | |
3270 } | |
3271 break; | |
3272 case Token::kSUB: { | |
3273 if (value != 0) { | |
3274 // Checking overflow without emitting an instruction would be wrong. | |
3275 __ subl(left, Immediate(value)); | |
3276 if (deopt != NULL) __ j(OVERFLOW, deopt); | |
3277 } | |
3278 break; | |
3279 } | |
3280 case Token::kMUL: { | |
3281 if (value == 2) { | |
3282 __ shll(left, Immediate(1)); | |
3283 } else { | |
3284 __ imull(left, Immediate(value)); | |
3285 } | |
3286 if (deopt != NULL) __ j(OVERFLOW, deopt); | |
3287 break; | |
3288 } | |
3289 case Token::kTRUNCDIV: { | |
3290 UNREACHABLE(); | |
Florian Schneider
2014/08/27 09:36:51
UNIMPLEMENTED?
Vyacheslav Egorov (Google)
2014/08/27 11:45:37
UNREACHABLE() is more meaningful because supported
| |
3291 break; | |
3292 } | |
3293 case Token::kBIT_AND: { | |
3294 // No overflow check. | |
3295 __ andl(left, Immediate(value)); | |
3296 break; | |
3297 } | |
3298 case Token::kBIT_OR: { | |
3299 // No overflow check. | |
3300 __ orl(left, Immediate(value)); | |
3301 break; | |
3302 } | |
3303 case Token::kBIT_XOR: { | |
3304 // No overflow check. | |
3305 __ xorl(left, Immediate(value)); | |
3306 break; | |
3307 } | |
3308 case Token::kSHR: { | |
3309 // sarl operation masks the count to 5 bits. | |
3310 const intptr_t kCountLimit = 0x1F; | |
3311 if (value == 0) { | |
3312 // TODO(vegorov): should be handled outside. | |
3313 break; | |
3314 } else if (value < 0) { | |
3315 // TODO(vegorov): should be handled outside. | |
3316 __ jmp(deopt); | |
3317 break; | |
3318 } | |
3319 | |
3320 if (value >= kCountLimit) { | |
3321 __ sarl(left, Immediate(kCountLimit)); | |
3322 } else { | |
3323 __ sarl(left, Immediate(value)); | |
3324 } | |
3325 | |
3326 break; | |
3327 } | |
3328 | |
3329 default: | |
3330 UNREACHABLE(); | |
3331 break; | |
3332 } | |
3333 return; | |
3334 } // if locs()->in(1).IsConstant() | |
3335 | |
3336 if (locs()->in(1).IsStackSlot()) { | |
3337 const Address& right = locs()->in(1).ToStackSlotAddress(); | |
3338 switch (op_kind()) { | |
3339 case Token::kADD: { | |
3340 __ addl(left, right); | |
3341 if (deopt != NULL) __ j(OVERFLOW, deopt); | |
3342 break; | |
3343 } | |
3344 case Token::kSUB: { | |
3345 __ subl(left, right); | |
3346 if (deopt != NULL) __ j(OVERFLOW, deopt); | |
3347 break; | |
3348 } | |
3349 case Token::kMUL: { | |
3350 __ imull(left, right); | |
3351 if (deopt != NULL) __ j(OVERFLOW, deopt); | |
3352 break; | |
3353 } | |
3354 case Token::kBIT_AND: { | |
3355 // No overflow check. | |
3356 __ andl(left, right); | |
3357 break; | |
3358 } | |
3359 case Token::kBIT_OR: { | |
3360 // No overflow check. | |
3361 __ orl(left, right); | |
3362 break; | |
3363 } | |
3364 case Token::kBIT_XOR: { | |
3365 // No overflow check. | |
3366 __ xorl(left, right); | |
3367 break; | |
3368 } | |
3369 default: | |
3370 UNREACHABLE(); | |
3371 } | |
3372 return; | |
3373 } // if locs()->in(1).IsStackSlot. | |
3374 | |
3375 // if locs()->in(1).IsRegister. | |
3376 Register right = locs()->in(1).reg(); | |
3377 switch (op_kind()) { | |
3378 case Token::kADD: { | |
3379 __ addl(left, right); | |
3380 if (deopt != NULL) __ j(OVERFLOW, deopt); | |
3381 break; | |
3382 } | |
3383 case Token::kSUB: { | |
3384 __ subl(left, right); | |
3385 if (deopt != NULL) __ j(OVERFLOW, deopt); | |
3386 break; | |
3387 } | |
3388 case Token::kMUL: { | |
3389 __ imull(left, right); | |
3390 if (deopt != NULL) __ j(OVERFLOW, deopt); | |
3391 break; | |
3392 } | |
3393 case Token::kBIT_AND: { | |
3394 // No overflow check. | |
3395 __ andl(left, right); | |
3396 break; | |
3397 } | |
3398 case Token::kBIT_OR: { | |
3399 // No overflow check. | |
3400 __ orl(left, right); | |
3401 break; | |
3402 } | |
3403 case Token::kBIT_XOR: { | |
3404 // No overflow check. | |
3405 __ xorl(left, right); | |
3406 break; | |
3407 } | |
3408 case Token::kTRUNCDIV: { | |
3409 UNREACHABLE(); | |
Florian Schneider
2014/08/27 09:36:51
UNIMPLEMENTED?
Vyacheslav Egorov (Google)
2014/08/27 11:45:37
Ditto.
| |
3410 break; | |
3411 } | |
3412 case Token::kMOD: { | |
3413 UNREACHABLE(); | |
Florian Schneider
2014/08/27 09:36:51
UNIMPLEMENTED?
Vyacheslav Egorov (Google)
2014/08/27 11:45:37
Ditto
| |
3414 break; | |
3415 } | |
3416 case Token::kSHR: { | |
3417 UNREACHABLE(); | |
Florian Schneider
2014/08/27 09:36:51
UNIMPLEMENTED?
Vyacheslav Egorov (Google)
2014/08/27 11:45:37
Ditto.
| |
3418 break; | |
3419 } | |
3420 case Token::kDIV: { | |
3421 // Dispatches to 'Double./'. | |
3422 // TODO(srdjan): Implement as conversion to double and double division. | |
3423 UNREACHABLE(); | |
3424 break; | |
3425 } | |
3426 case Token::kOR: | |
3427 case Token::kAND: { | |
3428 // Flow graph builder has dissected this operation to guarantee correct | |
3429 // behavior (short-circuit evaluation). | |
3430 UNREACHABLE(); | |
3431 break; | |
3432 } | |
3433 default: | |
3434 UNREACHABLE(); | |
3435 break; | |
3436 } | |
3437 } | |
3438 | |
3439 | |
3142 LocationSummary* CheckEitherNonSmiInstr::MakeLocationSummary(Isolate* isolate, | 3440 LocationSummary* CheckEitherNonSmiInstr::MakeLocationSummary(Isolate* isolate, |
3143 bool opt) const { | 3441 bool opt) const { |
3144 intptr_t left_cid = left()->Type()->ToCid(); | 3442 intptr_t left_cid = left()->Type()->ToCid(); |
3145 intptr_t right_cid = right()->Type()->ToCid(); | 3443 intptr_t right_cid = right()->Type()->ToCid(); |
3146 ASSERT((left_cid != kDoubleCid) && (right_cid != kDoubleCid)); | 3444 ASSERT((left_cid != kDoubleCid) && (right_cid != kDoubleCid)); |
3147 const intptr_t kNumInputs = 2; | 3445 const intptr_t kNumInputs = 2; |
3148 const bool need_temp = (left()->definition() != right()->definition()) | 3446 const bool need_temp = (left()->definition() != right()->definition()) |
3149 && (left_cid != kSmiCid) | 3447 && (left_cid != kSmiCid) |
3150 && (right_cid != kSmiCid); | 3448 && (right_cid != kSmiCid); |
3151 const intptr_t kNumTemps = need_temp ? 1 : 0; | 3449 const intptr_t kNumTemps = need_temp ? 1 : 0; |
(...skipping 1514 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4666 } | 4964 } |
4667 | 4965 |
4668 | 4966 |
4669 void UnaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4967 void UnaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
4670 XmmRegister value = locs()->in(0).fpu_reg(); | 4968 XmmRegister value = locs()->in(0).fpu_reg(); |
4671 ASSERT(locs()->out(0).fpu_reg() == value); | 4969 ASSERT(locs()->out(0).fpu_reg() == value); |
4672 __ DoubleNegate(value); | 4970 __ DoubleNegate(value); |
4673 } | 4971 } |
4674 | 4972 |
4675 | 4973 |
4974 LocationSummary* Int32ToDoubleInstr::MakeLocationSummary(Isolate* isolate, | |
4975 bool opt) const { | |
4976 const intptr_t kNumInputs = 1; | |
4977 const intptr_t kNumTemps = 0; | |
4978 LocationSummary* result = new(isolate) LocationSummary( | |
4979 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | |
4980 result->set_in(0, Location::WritableRegister()); | |
4981 result->set_out(0, Location::RequiresFpuRegister()); | |
4982 return result; | |
4983 } | |
4984 | |
4985 | |
4986 void Int32ToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | |
4987 Register value = locs()->in(0).reg(); | |
4988 FpuRegister result = locs()->out(0).fpu_reg(); | |
4989 __ cvtsi2sd(result, value); | |
4990 } | |
4991 | |
4992 | |
4676 LocationSummary* SmiToDoubleInstr::MakeLocationSummary(Isolate* isolate, | 4993 LocationSummary* SmiToDoubleInstr::MakeLocationSummary(Isolate* isolate, |
4677 bool opt) const { | 4994 bool opt) const { |
4678 const intptr_t kNumInputs = 1; | 4995 const intptr_t kNumInputs = 1; |
4679 const intptr_t kNumTemps = 0; | 4996 const intptr_t kNumTemps = 0; |
4680 LocationSummary* result = new(isolate) LocationSummary( | 4997 LocationSummary* result = new(isolate) LocationSummary( |
4681 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4998 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
4682 result->set_in(0, Location::WritableRegister()); | 4999 result->set_in(0, Location::WritableRegister()); |
4683 result->set_out(0, Location::RequiresFpuRegister()); | 5000 result->set_out(0, Location::RequiresFpuRegister()); |
4684 return result; | 5001 return result; |
4685 } | 5002 } |
(...skipping 1217 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5903 CompileType ShiftUint32OpInstr::ComputeType() const { | 6220 CompileType ShiftUint32OpInstr::ComputeType() const { |
5904 return CompileType::Int(); | 6221 return CompileType::Int(); |
5905 } | 6222 } |
5906 | 6223 |
5907 | 6224 |
5908 CompileType UnaryUint32OpInstr::ComputeType() const { | 6225 CompileType UnaryUint32OpInstr::ComputeType() const { |
5909 return CompileType::Int(); | 6226 return CompileType::Int(); |
5910 } | 6227 } |
5911 | 6228 |
5912 | 6229 |
5913 CompileType BoxUint32Instr::ComputeType() const { | |
5914 return CompileType::Int(); | |
5915 } | |
5916 | |
5917 | |
5918 CompileType UnboxUint32Instr::ComputeType() const { | |
5919 return CompileType::Int(); | |
5920 } | |
5921 | |
5922 | |
5923 LocationSummary* BinaryUint32OpInstr::MakeLocationSummary(Isolate* isolate, | 6230 LocationSummary* BinaryUint32OpInstr::MakeLocationSummary(Isolate* isolate, |
5924 bool opt) const { | 6231 bool opt) const { |
5925 const intptr_t kNumInputs = 2; | 6232 const intptr_t kNumInputs = 2; |
5926 const intptr_t kNumTemps = (op_kind() == Token::kMUL) ? 1 : 0; | 6233 const intptr_t kNumTemps = (op_kind() == Token::kMUL) ? 1 : 0; |
5927 LocationSummary* summary = new(isolate) LocationSummary( | 6234 LocationSummary* summary = new(isolate) LocationSummary( |
5928 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 6235 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5929 if (op_kind() == Token::kMUL) { | 6236 if (op_kind() == Token::kMUL) { |
5930 summary->set_in(0, Location::RegisterLocation(EAX)); | 6237 summary->set_in(0, Location::RegisterLocation(EAX)); |
5931 summary->set_temp(0, Location::RegisterLocation(EDX)); | 6238 summary->set_temp(0, Location::RegisterLocation(EDX)); |
5932 } else { | 6239 } else { |
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
6085 | 6392 |
6086 __ notl(out); | 6393 __ notl(out); |
6087 } | 6394 } |
6088 | 6395 |
6089 | 6396 |
6090 LocationSummary* BoxUint32Instr::MakeLocationSummary(Isolate* isolate, | 6397 LocationSummary* BoxUint32Instr::MakeLocationSummary(Isolate* isolate, |
6091 bool opt) const { | 6398 bool opt) const { |
6092 const intptr_t kNumInputs = 1; | 6399 const intptr_t kNumInputs = 1; |
6093 const intptr_t kNumTemps = 0; | 6400 const intptr_t kNumTemps = 0; |
6094 LocationSummary* summary = new(isolate) LocationSummary( | 6401 LocationSummary* summary = new(isolate) LocationSummary( |
6095 isolate, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); | 6402 isolate, |
6403 kNumInputs, | |
6404 kNumTemps, | |
6405 ValueFitsSmi() ? LocationSummary::kNoCall | |
6406 : LocationSummary::kCallOnSlowPath); | |
6096 summary->set_in(0, Location::RequiresRegister()); | 6407 summary->set_in(0, Location::RequiresRegister()); |
6097 summary->set_out(0, Location::RequiresRegister()); | 6408 summary->set_out(0, ValueFitsSmi() ? Location::SameAsFirstInput() |
6409 : Location::RequiresRegister()); | |
6098 return summary; | 6410 return summary; |
6099 } | 6411 } |
6100 | 6412 |
6101 | 6413 |
6102 void BoxUint32Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6414 void BoxUint32Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
6103 Register value = locs()->in(0).reg(); | 6415 Register value = locs()->in(0).reg(); |
6104 Register out = locs()->out(0).reg(); | 6416 Register out = locs()->out(0).reg(); |
6105 ASSERT(value != out); | |
6106 | 6417 |
6107 Label not_smi, done; | 6418 Label not_smi, done; |
6108 | 6419 |
6109 // TODO(johnmccutchan): Use range information to fast path smi / mint boxing. | 6420 if (ValueFitsSmi()) { |
6110 // Test if this value is <= kSmiMax. | 6421 ASSERT(value == out); |
6111 __ cmpl(value, Immediate(kSmiMax)); | 6422 __ SmiTag(value); |
6112 __ j(ABOVE, ¬_smi); | 6423 } else { |
6113 // Smi. | 6424 ASSERT(value != out); |
6114 __ movl(out, value); | 6425 __ cmpl(value, Immediate(kSmiMax)); |
6115 __ SmiTag(out); | 6426 __ j(ABOVE, ¬_smi); |
6116 __ jmp(&done); | 6427 // Smi. |
6117 __ Bind(¬_smi); | 6428 __ movl(out, value); |
6118 // Allocate a mint. | 6429 __ SmiTag(out); |
6119 BoxAllocationSlowPath::Allocate( | 6430 __ jmp(&done); |
6120 compiler, this, compiler->mint_class(), out, kNoRegister); | 6431 __ Bind(¬_smi); |
6121 // Copy low word into mint. | 6432 // Allocate a mint. |
6122 __ movl(FieldAddress(out, Mint::value_offset()), value); | 6433 BoxAllocationSlowPath::Allocate( |
6123 // Zero high word. | 6434 compiler, this, compiler->mint_class(), out, kNoRegister); |
6124 __ movl(FieldAddress(out, Mint::value_offset() + kWordSize), Immediate(0)); | 6435 // Copy low word into mint. |
6125 __ Bind(&done); | 6436 __ movl(FieldAddress(out, Mint::value_offset()), value); |
6437 // Zero high word. | |
6438 __ movl(FieldAddress(out, Mint::value_offset() + kWordSize), Immediate(0)); | |
6439 __ Bind(&done); | |
6440 } | |
6126 } | 6441 } |
6127 | 6442 |
6128 | 6443 |
6444 LocationSummary* BoxInt32Instr::MakeLocationSummary(Isolate* isolate, | |
6445 bool opt) const { | |
6446 const intptr_t kNumInputs = 1; | |
6447 const intptr_t kNumTemps = 0; | |
6448 LocationSummary* summary = new(isolate) LocationSummary( | |
6449 isolate, kNumInputs, kNumTemps, | |
6450 ValueFitsSmi() ? LocationSummary::kNoCall | |
6451 : LocationSummary::kCallOnSlowPath); | |
6452 summary->set_in(0, ValueFitsSmi() ? Location::RequiresRegister() | |
6453 : Location::WritableRegister()); | |
6454 summary->set_out(0, ValueFitsSmi() ? Location::SameAsFirstInput() | |
6455 : Location::RequiresRegister()); | |
6456 return summary; | |
6457 } | |
6458 | |
6459 | |
6460 void BoxInt32Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | |
6461 Register value = locs()->in(0).reg(); | |
6462 Register out = locs()->out(0).reg(); | |
6463 | |
6464 if (out != value) { | |
6465 __ movl(out, value); | |
6466 } | |
6467 __ shll(out, Immediate(1)); | |
6468 if (!ValueFitsSmi()) { | |
6469 Label done; | |
6470 __ j(NO_OVERFLOW, &done); | |
6471 // Allocate a mint. | |
6472 BoxAllocationSlowPath::Allocate( | |
6473 compiler, this, compiler->mint_class(), out, kNoRegister); | |
6474 __ movl(FieldAddress(out, Mint::value_offset()), value); | |
6475 __ sarl(value, Immediate(31)); // Sign extend. | |
6476 __ movl(FieldAddress(out, Mint::value_offset() + kWordSize), value); | |
6477 __ Bind(&done); | |
6478 } | |
6479 } | |
6480 | |
6481 | |
6129 LocationSummary* UnboxUint32Instr::MakeLocationSummary(Isolate* isolate, | 6482 LocationSummary* UnboxUint32Instr::MakeLocationSummary(Isolate* isolate, |
6130 bool opt) const { | 6483 bool opt) const { |
6131 const intptr_t value_cid = value()->Type()->ToCid(); | 6484 const intptr_t value_cid = value()->Type()->ToCid(); |
6132 const intptr_t kNumInputs = 1; | 6485 const intptr_t kNumInputs = 1; |
6133 const intptr_t kNumTemps = | 6486 const intptr_t kNumTemps = |
6134 ((value_cid == kMintCid) || (value_cid == kSmiCid)) ? 0 : 1; | 6487 ((value_cid == kMintCid) || (value_cid == kSmiCid)) ? 0 : 1; |
6135 LocationSummary* summary = new(isolate) LocationSummary( | 6488 LocationSummary* summary = new(isolate) LocationSummary( |
6136 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 6489 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
6137 summary->set_in(0, Location::RequiresRegister()); | 6490 summary->set_in(0, Location::RequiresRegister()); |
6138 if (kNumTemps > 0) { | 6491 if (kNumTemps > 0) { |
(...skipping 25 matching lines...) Expand all Loading... | |
6164 __ j(NOT_EQUAL, deopt); | 6517 __ j(NOT_EQUAL, deopt); |
6165 __ movl(value, FieldAddress(value, Mint::value_offset())); | 6518 __ movl(value, FieldAddress(value, Mint::value_offset())); |
6166 __ jmp(&done); | 6519 __ jmp(&done); |
6167 __ Bind(&is_smi); | 6520 __ Bind(&is_smi); |
6168 __ SmiUntag(value); | 6521 __ SmiUntag(value); |
6169 __ Bind(&done); | 6522 __ Bind(&done); |
6170 } | 6523 } |
6171 } | 6524 } |
6172 | 6525 |
6173 | 6526 |
6527 LocationSummary* UnboxInt32Instr::MakeLocationSummary(Isolate* isolate, | |
6528 bool opt) const { | |
6529 const intptr_t value_cid = value()->Type()->ToCid(); | |
6530 const intptr_t kNumInputs = 1; | |
6531 const intptr_t kNumTemps = CanDeoptimize() ? 1 : 0; | |
6532 LocationSummary* summary = new(isolate) LocationSummary( | |
6533 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | |
6534 summary->set_in(0, Location::RequiresRegister()); | |
6535 if (kNumTemps > 0) { | |
6536 summary->set_temp(0, Location::RequiresRegister()); | |
6537 } | |
6538 summary->set_out(0, (value_cid == kSmiCid) ? Location::SameAsFirstInput() | |
6539 : Location::RequiresRegister()); | |
6540 return summary; | |
6541 } | |
6542 | |
6543 | |
6544 static void LoadInt32FromMint(FlowGraphCompiler* compiler, | |
6545 Register mint, | |
6546 Register result, | |
6547 Register temp, | |
6548 Label* deopt) { | |
6549 __ movl(result, FieldAddress(mint, Mint::value_offset())); | |
6550 if (deopt != NULL) { | |
6551 __ movl(temp, result); | |
6552 __ sarl(temp, Immediate(31)); | |
6553 __ cmpl(temp, FieldAddress(mint, Mint::value_offset() + kWordSize)); | |
6554 __ j(NOT_EQUAL, deopt); | |
6555 } | |
6556 } | |
6557 | |
6558 | |
6559 void UnboxInt32Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | |
6560 const intptr_t value_cid = value()->Type()->ToCid(); | |
6561 const Register value = locs()->in(0).reg(); | |
6562 const Register result = locs()->out(0).reg(); | |
6563 | |
6564 // TODO(johnmccutchan): Emit better code for constant inputs. | |
6565 if (value_cid == kMintCid) { | |
6566 Register temp = CanDeoptimize() ? locs()->temp(0).reg() : kNoRegister; | |
6567 Label* deopt = CanDeoptimize() ? | |
6568 compiler->AddDeoptStub(deopt_id_, ICData::kDeoptUnboxInteger) : NULL; | |
6569 LoadInt32FromMint(compiler, | |
6570 value, | |
6571 result, | |
6572 temp, | |
6573 deopt); | |
6574 } else if (value_cid == kSmiCid) { | |
6575 ASSERT(value == result); | |
6576 __ SmiUntag(value); | |
6577 } else { | |
6578 Register temp = locs()->temp(0).reg(); | |
6579 Label* deopt = compiler->AddDeoptStub(deopt_id_, | |
6580 ICData::kDeoptUnboxInteger); | |
6581 Label is_smi, done; | |
6582 __ testl(value, Immediate(kSmiTagMask)); | |
6583 __ j(ZERO, &is_smi); | |
6584 __ CompareClassId(value, kMintCid, temp); | |
6585 __ j(NOT_EQUAL, deopt); | |
6586 LoadInt32FromMint(compiler, | |
6587 value, | |
6588 result, | |
6589 temp, | |
6590 deopt); | |
6591 __ movl(value, FieldAddress(value, Mint::value_offset())); | |
6592 __ jmp(&done); | |
6593 __ Bind(&is_smi); | |
6594 __ SmiUntag(value); | |
6595 __ Bind(&done); | |
6596 } | |
6597 } | |
6598 | |
6599 | |
6174 LocationSummary* UnboxedIntConverterInstr::MakeLocationSummary(Isolate* isolate, | 6600 LocationSummary* UnboxedIntConverterInstr::MakeLocationSummary(Isolate* isolate, |
6175 bool opt) const { | 6601 bool opt) const { |
6176 const intptr_t kNumInputs = 1; | 6602 const intptr_t kNumInputs = 1; |
6177 const intptr_t kNumTemps = 0; | 6603 const intptr_t kNumTemps = 0; |
6178 LocationSummary* summary = new(isolate) LocationSummary( | 6604 LocationSummary* summary = new(isolate) LocationSummary( |
6179 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 6605 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
6180 if (from() == kUnboxedMint) { | 6606 if ((from() == kUnboxedInt32 || from() == kUnboxedUint32) && |
6181 summary->set_in(0, Location::Pair(Location::RequiresRegister(), | 6607 (to() == kUnboxedInt32 || to() == kUnboxedUint32)) { |
6182 Location::RequiresRegister())); | 6608 summary->set_in(0, Location::RequiresRegister()); |
6609 summary->set_out(0, Location::SameAsFirstInput()); | |
6610 } else if (from() == kUnboxedMint) { | |
6611 summary->set_in(0, Location::Pair( | |
6612 CanDeoptimize() ? Location::WritableRegister() | |
6613 : Location::RequiresRegister(), | |
6614 Location::RequiresRegister())); | |
6183 summary->set_out(0, Location::RequiresRegister()); | 6615 summary->set_out(0, Location::RequiresRegister()); |
6184 } else { | 6616 } else if (from() == kUnboxedUint32) { |
6185 ASSERT(from() == kUnboxedUint32); | |
6186 summary->set_in(0, Location::RequiresRegister()); | 6617 summary->set_in(0, Location::RequiresRegister()); |
6187 summary->set_out(0, Location::Pair(Location::RequiresRegister(), | 6618 summary->set_out(0, Location::Pair(Location::RequiresRegister(), |
6188 Location::RequiresRegister())); | 6619 Location::RequiresRegister())); |
6620 } else if (from() == kUnboxedInt32) { | |
6621 summary->set_in(0, Location::RegisterLocation(EAX)); | |
6622 summary->set_out(0, Location::Pair(Location::RegisterLocation(EAX), | |
6623 Location::RegisterLocation(EDX))); | |
6189 } | 6624 } |
6190 return summary; | 6625 return summary; |
6191 } | 6626 } |
6192 | 6627 |
6193 | 6628 |
6194 void UnboxedIntConverterInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6629 void UnboxedIntConverterInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
6195 if (from() == kUnboxedMint) { | 6630 if (from() == kUnboxedInt32 && to() == kUnboxedUint32) { |
6631 // Representations are bitwise equivalent. | |
6632 ASSERT(locs()->out(0).reg() == locs()->in(0).reg()); | |
6633 } else if (from() == kUnboxedUint32 && to() == kUnboxedInt32) { | |
6634 // Representations are bitwise equivalent. | |
6635 ASSERT(locs()->out(0).reg() == locs()->in(0).reg()); | |
6636 if (CanDeoptimize()) { | |
6637 Label* deopt = | |
6638 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnboxInteger); | |
6639 __ testl(locs()->out(0).reg(), locs()->out(0).reg()); | |
6640 __ j(NEGATIVE, deopt); | |
6641 } | |
6642 } else if (from() == kUnboxedMint) { | |
6643 // TODO(vegorov) kUnboxedMint -> kInt32 conversion is currently usually | |
6644 // dominated by a CheckSmi(BoxInteger(val)) which is an artifact of ordering | |
6645 // of optimization passes and the way we check smi-ness of values. | |
6646 // Optimize it away. | |
6647 ASSERT(to() == kUnboxedInt32 || to() == kUnboxedUint32); | |
6196 PairLocation* in_pair = locs()->in(0).AsPairLocation(); | 6648 PairLocation* in_pair = locs()->in(0).AsPairLocation(); |
6197 Register in_lo = in_pair->At(0).reg(); | 6649 Register in_lo = in_pair->At(0).reg(); |
6650 Register in_hi = in_pair->At(1).reg(); | |
6198 Register out = locs()->out(0).reg(); | 6651 Register out = locs()->out(0).reg(); |
6199 // Copy low word. | 6652 // Copy low word. |
6200 __ movl(out, in_lo); | 6653 __ movl(out, in_lo); |
6201 } else { | 6654 if (CanDeoptimize()) { |
6202 ASSERT(from() == kUnboxedUint32); | 6655 Label* deopt = |
6656 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnboxInteger); | |
6657 __ sarl(in_lo, Immediate(31)); | |
6658 __ cmpl(in_lo, in_hi); | |
6659 __ j(NOT_EQUAL, deopt); | |
6660 } | |
6661 } else if (from() == kUnboxedUint32) { | |
6662 ASSERT(to() == kUnboxedMint); | |
6203 Register in = locs()->in(0).reg(); | 6663 Register in = locs()->in(0).reg(); |
6204 PairLocation* out_pair = locs()->out(0).AsPairLocation(); | 6664 PairLocation* out_pair = locs()->out(0).AsPairLocation(); |
6205 Register out_lo = out_pair->At(0).reg(); | 6665 Register out_lo = out_pair->At(0).reg(); |
6206 Register out_hi = out_pair->At(1).reg(); | 6666 Register out_hi = out_pair->At(1).reg(); |
6207 // Copy low word. | 6667 // Copy low word. |
6208 __ movl(out_lo, in); | 6668 __ movl(out_lo, in); |
6209 // Zero upper word. | 6669 // Zero upper word. |
6210 __ xorl(out_hi, out_hi); | 6670 __ xorl(out_hi, out_hi); |
6671 } else if (from() == kUnboxedInt32) { | |
6672 ASSERT(to() == kUnboxedMint); | |
6673 PairLocation* out_pair = locs()->out(0).AsPairLocation(); | |
6674 Register out_lo = out_pair->At(0).reg(); | |
6675 Register out_hi = out_pair->At(1).reg(); | |
6676 ASSERT(locs()->in(0).reg() == EAX); | |
6677 ASSERT(out_lo == EAX && out_hi == EDX); | |
6678 __ cdq(); | |
6679 } else { | |
6680 UNREACHABLE(); | |
6211 } | 6681 } |
6212 } | 6682 } |
6213 | 6683 |
6214 | 6684 |
6215 LocationSummary* ThrowInstr::MakeLocationSummary(Isolate* isolate, | 6685 LocationSummary* ThrowInstr::MakeLocationSummary(Isolate* isolate, |
6216 bool opt) const { | 6686 bool opt) const { |
6217 return new(isolate) LocationSummary(isolate, 0, 0, LocationSummary::kCall); | 6687 return new(isolate) LocationSummary(isolate, 0, 0, LocationSummary::kCall); |
6218 } | 6688 } |
6219 | 6689 |
6220 | 6690 |
(...skipping 343 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
6564 __ movl(EDX, Immediate(kInvalidObjectPointer)); | 7034 __ movl(EDX, Immediate(kInvalidObjectPointer)); |
6565 __ movl(EDX, Immediate(kInvalidObjectPointer)); | 7035 __ movl(EDX, Immediate(kInvalidObjectPointer)); |
6566 #endif | 7036 #endif |
6567 } | 7037 } |
6568 | 7038 |
6569 } // namespace dart | 7039 } // namespace dart |
6570 | 7040 |
6571 #undef __ | 7041 #undef __ |
6572 | 7042 |
6573 #endif // defined TARGET_ARCH_IA32 | 7043 #endif // defined TARGET_ARCH_IA32 |
OLD | NEW |