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

Side by Side Diff: runtime/vm/intermediate_language_ia32.cc

Issue 504143003: Support Int32 representation for selected binary operations. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
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
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 summary->set_in(1, Location::RegisterOrSmiConstant(right()));
3188 } else {
3189 summary->set_in(1, Location::PrefersRegister());
3190 }
3191 summary->set_out(0, Location::SameAsFirstInput());
3192 return summary;
3193 }
3194 }
3195
3196
3197 static void EmitInt32ShiftLeft(FlowGraphCompiler* compiler,
3198 BinaryInt32OpInstr* shift_left) {
3199 const bool is_truncating = shift_left->IsTruncating();
3200 const LocationSummary& locs = *shift_left->locs();
3201 Register left = locs.in(0).reg();
3202 Register result = locs.out(0).reg();
3203 ASSERT(left == result);
3204 Label* deopt = shift_left->CanDeoptimize() ?
3205 compiler->AddDeoptStub(shift_left->deopt_id(), ICData::kDeoptBinarySmiOp)
3206 : NULL;
3207 ASSERT(locs.in(1).IsConstant());
3208
3209 const Object& constant = locs.in(1).constant();
3210 ASSERT(constant.IsSmi());
3211 // shll operation masks the count to 5 bits.
3212 const intptr_t kCountLimit = 0x1F;
3213 const intptr_t value = Smi::Cast(constant).Value();
3214 if (value == 0) {
3215 // No code needed.
3216 } else if ((value < 0) || (value >= kCountLimit)) {
3217 // This condition may not be known earlier in some cases because
3218 // of constant propagation, inlining, etc.
3219 if ((value >= kCountLimit) && is_truncating) {
3220 __ xorl(result, result);
3221 } else {
3222 // Result is Mint or exception.
3223 __ jmp(deopt);
3224 }
3225 } else {
3226 if (!is_truncating) {
3227 // Check for overflow.
3228 Register temp = locs.temp(0).reg();
3229 __ movl(temp, left);
3230 __ shll(left, Immediate(value));
3231 __ sarl(left, Immediate(value));
3232 __ cmpl(left, temp);
3233 __ j(NOT_EQUAL, deopt); // Overflow.
3234 }
3235 // Shift for result now we know there is no overflow.
3236 __ shll(left, Immediate(value));
3237 }
3238 }
3239
3240
3241 void BinaryInt32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
3242 if (op_kind() == Token::kSHL) {
3243 EmitInt32ShiftLeft(compiler, this);
3244 return;
3245 }
3246
3247 Register left = locs()->in(0).reg();
3248 Register result = locs()->out(0).reg();
3249 ASSERT(left == result);
3250 Label* deopt = NULL;
3251 if (CanDeoptimize()) {
3252 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinarySmiOp);
3253 }
3254
3255 if (locs()->in(1).IsConstant()) {
3256 const Object& constant = locs()->in(1).constant();
3257 ASSERT(constant.IsSmi());
3258 const intptr_t value = Smi::Cast(constant).Value();
3259 switch (op_kind()) {
3260 case Token::kADD:
3261 if (value != 0) {
3262 // Checking overflow without emitting an instruction would be wrong.
3263 __ addl(left, Immediate(value));
3264 if (deopt != NULL) __ j(OVERFLOW, deopt);
3265 }
3266 break;
3267 case Token::kSUB: {
3268 if (value != 0) {
3269 // Checking overflow without emitting an instruction would be wrong.
3270 __ subl(left, Immediate(value));
3271 if (deopt != NULL) __ j(OVERFLOW, deopt);
3272 }
3273 break;
3274 }
3275 case Token::kMUL: {
3276 if (value == 2) {
3277 __ shll(left, Immediate(1));
3278 } else {
3279 __ imull(left, Immediate(value));
3280 }
3281 if (deopt != NULL) __ j(OVERFLOW, deopt);
3282 break;
3283 }
3284 case Token::kTRUNCDIV: {
3285 UNREACHABLE();
3286 break;
3287 }
3288 case Token::kBIT_AND: {
3289 // No overflow check.
3290 __ andl(left, Immediate(value));
3291 break;
3292 }
3293 case Token::kBIT_OR: {
3294 // No overflow check.
3295 __ orl(left, Immediate(value));
3296 break;
3297 }
3298 case Token::kBIT_XOR: {
3299 // No overflow check.
3300 __ xorl(left, Immediate(value));
3301 break;
3302 }
3303 case Token::kSHR: {
3304 // sarl operation masks the count to 5 bits.
3305 const intptr_t kCountLimit = 0x1F;
3306 if (value == 0) {
3307 // TODO(vegorov): should be handled outside.
3308 break;
3309 } else if (value < 0) {
3310 // TODO(vegorov): should be handled outside.
3311 __ jmp(deopt);
3312 break;
3313 }
3314
3315 if (value >= kCountLimit) {
3316 __ sarl(left, Immediate(kCountLimit));
3317 } else {
3318 __ sarl(left, Immediate(value));
3319 }
3320
3321 break;
3322 }
3323
3324 default:
3325 UNREACHABLE();
3326 break;
3327 }
3328 return;
3329 } // if locs()->in(1).IsConstant()
3330
3331 if (locs()->in(1).IsStackSlot()) {
3332 const Address& right = locs()->in(1).ToStackSlotAddress();
3333 switch (op_kind()) {
3334 case Token::kADD: {
3335 __ addl(left, right);
3336 if (deopt != NULL) __ j(OVERFLOW, deopt);
3337 break;
3338 }
3339 case Token::kSUB: {
3340 __ subl(left, right);
3341 if (deopt != NULL) __ j(OVERFLOW, deopt);
3342 break;
3343 }
3344 case Token::kMUL: {
3345 __ imull(left, right);
3346 if (deopt != NULL) __ j(OVERFLOW, deopt);
3347 break;
3348 }
3349 case Token::kBIT_AND: {
3350 // No overflow check.
3351 __ andl(left, right);
3352 break;
3353 }
3354 case Token::kBIT_OR: {
3355 // No overflow check.
3356 __ orl(left, right);
3357 break;
3358 }
3359 case Token::kBIT_XOR: {
3360 // No overflow check.
3361 __ xorl(left, right);
3362 break;
3363 }
3364 default:
3365 UNREACHABLE();
3366 }
3367 return;
3368 } // if locs()->in(1).IsStackSlot.
3369
3370 // if locs()->in(1).IsRegister.
3371 Register right = locs()->in(1).reg();
3372 switch (op_kind()) {
3373 case Token::kADD: {
3374 __ addl(left, right);
3375 if (deopt != NULL) __ j(OVERFLOW, deopt);
3376 break;
3377 }
3378 case Token::kSUB: {
3379 __ subl(left, right);
3380 if (deopt != NULL) __ j(OVERFLOW, deopt);
3381 break;
3382 }
3383 case Token::kMUL: {
3384 __ imull(left, right);
3385 if (deopt != NULL) __ j(OVERFLOW, deopt);
3386 break;
3387 }
3388 case Token::kBIT_AND: {
3389 // No overflow check.
3390 __ andl(left, right);
3391 break;
3392 }
3393 case Token::kBIT_OR: {
3394 // No overflow check.
3395 __ orl(left, right);
3396 break;
3397 }
3398 case Token::kBIT_XOR: {
3399 // No overflow check.
3400 __ xorl(left, right);
3401 break;
3402 }
3403 case Token::kTRUNCDIV: {
3404 UNREACHABLE();
3405 break;
3406 }
3407 case Token::kMOD: {
3408 UNREACHABLE();
3409 break;
3410 }
3411 case Token::kSHR: {
3412 UNREACHABLE();
3413 break;
3414 }
3415 case Token::kDIV: {
3416 // Dispatches to 'Double./'.
3417 // TODO(srdjan): Implement as conversion to double and double division.
3418 UNREACHABLE();
3419 break;
3420 }
3421 case Token::kOR:
3422 case Token::kAND: {
3423 // Flow graph builder has dissected this operation to guarantee correct
3424 // behavior (short-circuit evaluation).
3425 UNREACHABLE();
3426 break;
3427 }
3428 default:
3429 UNREACHABLE();
3430 break;
3431 }
3432 }
3433
3434
3142 LocationSummary* CheckEitherNonSmiInstr::MakeLocationSummary(Isolate* isolate, 3435 LocationSummary* CheckEitherNonSmiInstr::MakeLocationSummary(Isolate* isolate,
3143 bool opt) const { 3436 bool opt) const {
3144 intptr_t left_cid = left()->Type()->ToCid(); 3437 intptr_t left_cid = left()->Type()->ToCid();
3145 intptr_t right_cid = right()->Type()->ToCid(); 3438 intptr_t right_cid = right()->Type()->ToCid();
3146 ASSERT((left_cid != kDoubleCid) && (right_cid != kDoubleCid)); 3439 ASSERT((left_cid != kDoubleCid) && (right_cid != kDoubleCid));
3147 const intptr_t kNumInputs = 2; 3440 const intptr_t kNumInputs = 2;
3148 const bool need_temp = (left()->definition() != right()->definition()) 3441 const bool need_temp = (left()->definition() != right()->definition())
3149 && (left_cid != kSmiCid) 3442 && (left_cid != kSmiCid)
3150 && (right_cid != kSmiCid); 3443 && (right_cid != kSmiCid);
3151 const intptr_t kNumTemps = need_temp ? 1 : 0; 3444 const intptr_t kNumTemps = need_temp ? 1 : 0;
(...skipping 1514 matching lines...) Expand 10 before | Expand all | Expand 10 after
4666 } 4959 }
4667 4960
4668 4961
4669 void UnaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 4962 void UnaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
4670 XmmRegister value = locs()->in(0).fpu_reg(); 4963 XmmRegister value = locs()->in(0).fpu_reg();
4671 ASSERT(locs()->out(0).fpu_reg() == value); 4964 ASSERT(locs()->out(0).fpu_reg() == value);
4672 __ DoubleNegate(value); 4965 __ DoubleNegate(value);
4673 } 4966 }
4674 4967
4675 4968
4969 LocationSummary* Int32ToDoubleInstr::MakeLocationSummary(Isolate* isolate,
4970 bool opt) const {
4971 const intptr_t kNumInputs = 1;
4972 const intptr_t kNumTemps = 0;
4973 LocationSummary* result = new(isolate) LocationSummary(
4974 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall);
4975 result->set_in(0, Location::WritableRegister());
4976 result->set_out(0, Location::RequiresFpuRegister());
4977 return result;
4978 }
4979
4980
4981 void Int32ToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
4982 Register value = locs()->in(0).reg();
4983 FpuRegister result = locs()->out(0).fpu_reg();
4984 __ cvtsi2sd(result, value);
4985 }
4986
4987
4676 LocationSummary* SmiToDoubleInstr::MakeLocationSummary(Isolate* isolate, 4988 LocationSummary* SmiToDoubleInstr::MakeLocationSummary(Isolate* isolate,
4677 bool opt) const { 4989 bool opt) const {
4678 const intptr_t kNumInputs = 1; 4990 const intptr_t kNumInputs = 1;
4679 const intptr_t kNumTemps = 0; 4991 const intptr_t kNumTemps = 0;
4680 LocationSummary* result = new(isolate) LocationSummary( 4992 LocationSummary* result = new(isolate) LocationSummary(
4681 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); 4993 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall);
4682 result->set_in(0, Location::WritableRegister()); 4994 result->set_in(0, Location::WritableRegister());
4683 result->set_out(0, Location::RequiresFpuRegister()); 4995 result->set_out(0, Location::RequiresFpuRegister());
4684 return result; 4996 return result;
4685 } 4997 }
(...skipping 1217 matching lines...) Expand 10 before | Expand all | Expand 10 after
5903 CompileType ShiftUint32OpInstr::ComputeType() const { 6215 CompileType ShiftUint32OpInstr::ComputeType() const {
5904 return CompileType::Int(); 6216 return CompileType::Int();
5905 } 6217 }
5906 6218
5907 6219
5908 CompileType UnaryUint32OpInstr::ComputeType() const { 6220 CompileType UnaryUint32OpInstr::ComputeType() const {
5909 return CompileType::Int(); 6221 return CompileType::Int();
5910 } 6222 }
5911 6223
5912 6224
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, 6225 LocationSummary* BinaryUint32OpInstr::MakeLocationSummary(Isolate* isolate,
5924 bool opt) const { 6226 bool opt) const {
5925 const intptr_t kNumInputs = 2; 6227 const intptr_t kNumInputs = 2;
5926 const intptr_t kNumTemps = (op_kind() == Token::kMUL) ? 1 : 0; 6228 const intptr_t kNumTemps = (op_kind() == Token::kMUL) ? 1 : 0;
5927 LocationSummary* summary = new(isolate) LocationSummary( 6229 LocationSummary* summary = new(isolate) LocationSummary(
5928 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); 6230 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall);
5929 if (op_kind() == Token::kMUL) { 6231 if (op_kind() == Token::kMUL) {
5930 summary->set_in(0, Location::RegisterLocation(EAX)); 6232 summary->set_in(0, Location::RegisterLocation(EAX));
5931 summary->set_temp(0, Location::RegisterLocation(EDX)); 6233 summary->set_temp(0, Location::RegisterLocation(EDX));
5932 } else { 6234 } else {
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after
6085 6387
6086 __ notl(out); 6388 __ notl(out);
6087 } 6389 }
6088 6390
6089 6391
6090 LocationSummary* BoxUint32Instr::MakeLocationSummary(Isolate* isolate, 6392 LocationSummary* BoxUint32Instr::MakeLocationSummary(Isolate* isolate,
6091 bool opt) const { 6393 bool opt) const {
6092 const intptr_t kNumInputs = 1; 6394 const intptr_t kNumInputs = 1;
6093 const intptr_t kNumTemps = 0; 6395 const intptr_t kNumTemps = 0;
6094 LocationSummary* summary = new(isolate) LocationSummary( 6396 LocationSummary* summary = new(isolate) LocationSummary(
6095 isolate, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); 6397 isolate,
6398 kNumInputs,
6399 kNumTemps,
6400 ValueFitsSmi() ? LocationSummary::kNoCall
6401 : LocationSummary::kCallOnSlowPath);
6096 summary->set_in(0, Location::RequiresRegister()); 6402 summary->set_in(0, Location::RequiresRegister());
6097 summary->set_out(0, Location::RequiresRegister()); 6403 summary->set_out(0, ValueFitsSmi() ? Location::SameAsFirstInput()
6404 : Location::RequiresRegister());
6098 return summary; 6405 return summary;
6099 } 6406 }
6100 6407
6101 6408
6102 void BoxUint32Instr::EmitNativeCode(FlowGraphCompiler* compiler) { 6409 void BoxUint32Instr::EmitNativeCode(FlowGraphCompiler* compiler) {
6103 Register value = locs()->in(0).reg(); 6410 Register value = locs()->in(0).reg();
6104 Register out = locs()->out(0).reg(); 6411 Register out = locs()->out(0).reg();
6105 ASSERT(value != out);
6106 6412
6107 Label not_smi, done; 6413 Label not_smi, done;
6108 6414
6109 // TODO(johnmccutchan): Use range information to fast path smi / mint boxing. 6415 if (ValueFitsSmi()) {
6110 // Test if this value is <= kSmiMax. 6416 ASSERT(value == out);
6111 __ cmpl(value, Immediate(kSmiMax)); 6417 __ SmiTag(value);
6112 __ j(ABOVE, &not_smi); 6418 } else {
6113 // Smi. 6419 ASSERT(value != out);
6114 __ movl(out, value); 6420 __ cmpl(value, Immediate(kSmiMax));
6115 __ SmiTag(out); 6421 __ j(ABOVE, &not_smi);
6116 __ jmp(&done); 6422 // Smi.
6117 __ Bind(&not_smi); 6423 __ movl(out, value);
6118 // Allocate a mint. 6424 __ SmiTag(out);
6119 BoxAllocationSlowPath::Allocate( 6425 __ jmp(&done);
6120 compiler, this, compiler->mint_class(), out, kNoRegister); 6426 __ Bind(&not_smi);
6121 // Copy low word into mint. 6427 // Allocate a mint.
6122 __ movl(FieldAddress(out, Mint::value_offset()), value); 6428 BoxAllocationSlowPath::Allocate(
6123 // Zero high word. 6429 compiler, this, compiler->mint_class(), out, kNoRegister);
6124 __ movl(FieldAddress(out, Mint::value_offset() + kWordSize), Immediate(0)); 6430 // Copy low word into mint.
6125 __ Bind(&done); 6431 __ movl(FieldAddress(out, Mint::value_offset()), value);
6432 // Zero high word.
6433 __ movl(FieldAddress(out, Mint::value_offset() + kWordSize), Immediate(0));
6434 __ Bind(&done);
6435 }
6126 } 6436 }
6127 6437
6128 6438
6439 LocationSummary* BoxInt32Instr::MakeLocationSummary(Isolate* isolate,
6440 bool opt) const {
6441 const intptr_t kNumInputs = 1;
6442 const intptr_t kNumTemps = 0;
6443 LocationSummary* summary = new(isolate) LocationSummary(
6444 isolate, kNumInputs, kNumTemps,
6445 ValueFitsSmi() ? LocationSummary::kNoCall
6446 : LocationSummary::kCallOnSlowPath);
6447 summary->set_in(0, ValueFitsSmi() ? Location::RequiresRegister()
6448 : Location::WritableRegister());
6449 summary->set_out(0, ValueFitsSmi() ? Location::SameAsFirstInput()
6450 : Location::RequiresRegister());
6451 return summary;
6452 }
6453
6454
6455 void BoxInt32Instr::EmitNativeCode(FlowGraphCompiler* compiler) {
6456 Register value = locs()->in(0).reg();
6457 Register out = locs()->out(0).reg();
6458
6459 if (out != value) {
6460 __ movl(out, value);
6461 }
6462 __ shll(out, Immediate(1));
6463 if (!ValueFitsSmi()) {
6464 Label done;
6465 __ j(NO_OVERFLOW, &done);
6466 // Allocate a mint.
6467 BoxAllocationSlowPath::Allocate(
6468 compiler, this, compiler->mint_class(), out, kNoRegister);
6469 __ movl(FieldAddress(out, Mint::value_offset()), value);
6470 __ sarl(value, Immediate(31)); // Sign extend.
6471 __ movl(FieldAddress(out, Mint::value_offset() + kWordSize), value);
6472 __ Bind(&done);
6473 }
6474 }
6475
6476
6129 LocationSummary* UnboxUint32Instr::MakeLocationSummary(Isolate* isolate, 6477 LocationSummary* UnboxUint32Instr::MakeLocationSummary(Isolate* isolate,
6130 bool opt) const { 6478 bool opt) const {
6131 const intptr_t value_cid = value()->Type()->ToCid(); 6479 const intptr_t value_cid = value()->Type()->ToCid();
6132 const intptr_t kNumInputs = 1; 6480 const intptr_t kNumInputs = 1;
6133 const intptr_t kNumTemps = 6481 const intptr_t kNumTemps =
6134 ((value_cid == kMintCid) || (value_cid == kSmiCid)) ? 0 : 1; 6482 ((value_cid == kMintCid) || (value_cid == kSmiCid)) ? 0 : 1;
6135 LocationSummary* summary = new(isolate) LocationSummary( 6483 LocationSummary* summary = new(isolate) LocationSummary(
6136 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); 6484 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall);
6137 summary->set_in(0, Location::RequiresRegister()); 6485 summary->set_in(0, Location::RequiresRegister());
6138 if (kNumTemps > 0) { 6486 if (kNumTemps > 0) {
(...skipping 25 matching lines...) Expand all
6164 __ j(NOT_EQUAL, deopt); 6512 __ j(NOT_EQUAL, deopt);
6165 __ movl(value, FieldAddress(value, Mint::value_offset())); 6513 __ movl(value, FieldAddress(value, Mint::value_offset()));
6166 __ jmp(&done); 6514 __ jmp(&done);
6167 __ Bind(&is_smi); 6515 __ Bind(&is_smi);
6168 __ SmiUntag(value); 6516 __ SmiUntag(value);
6169 __ Bind(&done); 6517 __ Bind(&done);
6170 } 6518 }
6171 } 6519 }
6172 6520
6173 6521
6522 LocationSummary* UnboxInt32Instr::MakeLocationSummary(Isolate* isolate,
6523 bool opt) const {
6524 const intptr_t value_cid = value()->Type()->ToCid();
6525 const intptr_t kNumInputs = 1;
6526 const intptr_t kNumTemps = CanDeoptimize() ? 1 : 0;
6527 LocationSummary* summary = new(isolate) LocationSummary(
6528 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall);
6529 summary->set_in(0, Location::RequiresRegister());
6530 if (kNumTemps > 0) {
6531 summary->set_temp(0, Location::RequiresRegister());
6532 }
6533 summary->set_out(0, (value_cid == kSmiCid) ? Location::SameAsFirstInput()
6534 : Location::RequiresRegister());
6535 return summary;
6536 }
6537
6538
6539 static void LoadInt32FromMint(FlowGraphCompiler* compiler,
6540 Register mint,
6541 Register result,
6542 Register temp,
6543 Label* deopt) {
6544 __ movl(result, FieldAddress(mint, Mint::value_offset()));
6545 if (deopt != NULL) {
6546 __ movl(temp, result);
6547 __ sarl(temp, Immediate(31));
6548 __ cmpl(temp, FieldAddress(mint, Mint::value_offset() + kWordSize));
6549 __ j(NOT_EQUAL, deopt);
6550 }
6551 }
6552
6553
6554 void UnboxInt32Instr::EmitNativeCode(FlowGraphCompiler* compiler) {
6555 const intptr_t value_cid = value()->Type()->ToCid();
6556 const Register value = locs()->in(0).reg();
6557 const Register result = locs()->out(0).reg();
6558
6559 // TODO(johnmccutchan): Emit better code for constant inputs.
6560 if (value_cid == kMintCid) {
6561 Register temp = CanDeoptimize() ? locs()->temp(0).reg() : kNoRegister;
6562 Label* deopt = CanDeoptimize() ?
6563 compiler->AddDeoptStub(deopt_id_, ICData::kDeoptUnboxInteger) : NULL;
6564 LoadInt32FromMint(compiler,
6565 value,
6566 result,
6567 temp,
6568 deopt);
6569 } else if (value_cid == kSmiCid) {
6570 ASSERT(value == result);
6571 __ SmiUntag(value);
6572 } else {
6573 Register temp = locs()->temp(0).reg();
6574 Label* deopt = compiler->AddDeoptStub(deopt_id_,
6575 ICData::kDeoptUnboxInteger);
6576 Label is_smi, done;
6577 __ testl(value, Immediate(kSmiTagMask));
6578 __ j(ZERO, &is_smi);
6579 __ CompareClassId(value, kMintCid, temp);
6580 __ j(NOT_EQUAL, deopt);
6581 LoadInt32FromMint(compiler,
6582 value,
6583 result,
6584 temp,
6585 deopt);
6586 __ movl(value, FieldAddress(value, Mint::value_offset()));
6587 __ jmp(&done);
6588 __ Bind(&is_smi);
6589 __ SmiUntag(value);
6590 __ Bind(&done);
6591 }
6592 }
6593
6594
6174 LocationSummary* UnboxedIntConverterInstr::MakeLocationSummary(Isolate* isolate, 6595 LocationSummary* UnboxedIntConverterInstr::MakeLocationSummary(Isolate* isolate,
6175 bool opt) const { 6596 bool opt) const {
6176 const intptr_t kNumInputs = 1; 6597 const intptr_t kNumInputs = 1;
6177 const intptr_t kNumTemps = 0; 6598 const intptr_t kNumTemps = 0;
6178 LocationSummary* summary = new(isolate) LocationSummary( 6599 LocationSummary* summary = new(isolate) LocationSummary(
6179 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); 6600 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall);
6180 if (from() == kUnboxedMint) { 6601 if ((from() == kUnboxedInt32 || from() == kUnboxedUint32) &&
6181 summary->set_in(0, Location::Pair(Location::RequiresRegister(), 6602 (to() == kUnboxedInt32 || to() == kUnboxedUint32)) {
6182 Location::RequiresRegister())); 6603 summary->set_in(0, Location::RequiresRegister());
6604 summary->set_out(0, Location::SameAsFirstInput());
6605 } else if (from() == kUnboxedMint) {
6606 summary->set_in(0, Location::Pair(
6607 CanDeoptimize() ? Location::WritableRegister()
6608 : Location::RequiresRegister(),
6609 Location::RequiresRegister()));
6183 summary->set_out(0, Location::RequiresRegister()); 6610 summary->set_out(0, Location::RequiresRegister());
6184 } else { 6611 } else if (from() == kUnboxedUint32) {
6185 ASSERT(from() == kUnboxedUint32);
6186 summary->set_in(0, Location::RequiresRegister()); 6612 summary->set_in(0, Location::RequiresRegister());
6187 summary->set_out(0, Location::Pair(Location::RequiresRegister(), 6613 summary->set_out(0, Location::Pair(Location::RequiresRegister(),
6188 Location::RequiresRegister())); 6614 Location::RequiresRegister()));
6615 } else if (from() == kUnboxedInt32) {
6616 summary->set_in(0, Location::RegisterLocation(EAX));
6617 summary->set_out(0, Location::Pair(Location::RegisterLocation(EAX),
6618 Location::RegisterLocation(EDX)));
6189 } 6619 }
6190 return summary; 6620 return summary;
6191 } 6621 }
6192 6622
6193 6623
6194 void UnboxedIntConverterInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 6624 void UnboxedIntConverterInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
6195 if (from() == kUnboxedMint) { 6625 if (from() == kUnboxedInt32 && to() == kUnboxedUint32) {
6626 // Representations are bitwise equivalent.
6627 ASSERT(locs()->out(0).reg() == locs()->in(0).reg());
6628 } else if (from() == kUnboxedUint32 && to() == kUnboxedInt32) {
6629 // Representations are bitwise equivalent.
6630 ASSERT(locs()->out(0).reg() == locs()->in(0).reg());
6631 if (CanDeoptimize()) {
6632 Label* deopt =
6633 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnboxInteger);
6634 __ testl(locs()->out(0).reg(), locs()->out(0).reg());
6635 __ j(NEGATIVE, deopt);
6636 }
6637 } else if (from() == kUnboxedMint) {
6638 // TODO(vegorov) kUnboxedMint -> kInt32 conversion is currently usually
6639 // dominated by a CheckSmi(BoxInteger(val)) which is an artifact of ordering
6640 // of optimization passes and the way we check smi-ness of values.
6641 // Optimize it away.
6642 ASSERT(to() == kUnboxedInt32 || to() == kUnboxedUint32);
6196 PairLocation* in_pair = locs()->in(0).AsPairLocation(); 6643 PairLocation* in_pair = locs()->in(0).AsPairLocation();
6197 Register in_lo = in_pair->At(0).reg(); 6644 Register in_lo = in_pair->At(0).reg();
6645 Register in_hi = in_pair->At(1).reg();
6198 Register out = locs()->out(0).reg(); 6646 Register out = locs()->out(0).reg();
6199 // Copy low word. 6647 // Copy low word.
6200 __ movl(out, in_lo); 6648 __ movl(out, in_lo);
6201 } else { 6649 if (CanDeoptimize()) {
6202 ASSERT(from() == kUnboxedUint32); 6650 Label* deopt =
6651 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnboxInteger);
6652 __ sarl(in_lo, Immediate(31));
6653 __ cmpl(in_lo, in_hi);
6654 __ j(NOT_EQUAL, deopt);
6655 }
6656 } else if (from() == kUnboxedUint32) {
6657 ASSERT(to() == kUnboxedMint);
6203 Register in = locs()->in(0).reg(); 6658 Register in = locs()->in(0).reg();
6204 PairLocation* out_pair = locs()->out(0).AsPairLocation(); 6659 PairLocation* out_pair = locs()->out(0).AsPairLocation();
6205 Register out_lo = out_pair->At(0).reg(); 6660 Register out_lo = out_pair->At(0).reg();
6206 Register out_hi = out_pair->At(1).reg(); 6661 Register out_hi = out_pair->At(1).reg();
6207 // Copy low word. 6662 // Copy low word.
6208 __ movl(out_lo, in); 6663 __ movl(out_lo, in);
6209 // Zero upper word. 6664 // Zero upper word.
6210 __ xorl(out_hi, out_hi); 6665 __ xorl(out_hi, out_hi);
6666 } else if (from() == kUnboxedInt32) {
6667 ASSERT(to() == kUnboxedMint);
6668 PairLocation* out_pair = locs()->out(0).AsPairLocation();
6669 Register out_lo = out_pair->At(0).reg();
6670 Register out_hi = out_pair->At(1).reg();
6671 ASSERT(locs()->in(0).reg() == EAX);
6672 ASSERT(out_lo == EAX && out_hi == EDX);
6673 __ cdq();
6674 } else {
6675 UNREACHABLE();
6211 } 6676 }
6212 } 6677 }
6213 6678
6214 6679
6215 LocationSummary* ThrowInstr::MakeLocationSummary(Isolate* isolate, 6680 LocationSummary* ThrowInstr::MakeLocationSummary(Isolate* isolate,
6216 bool opt) const { 6681 bool opt) const {
6217 return new(isolate) LocationSummary(isolate, 0, 0, LocationSummary::kCall); 6682 return new(isolate) LocationSummary(isolate, 0, 0, LocationSummary::kCall);
6218 } 6683 }
6219 6684
6220 6685
(...skipping 343 matching lines...) Expand 10 before | Expand all | Expand 10 after
6564 __ movl(EDX, Immediate(kInvalidObjectPointer)); 7029 __ movl(EDX, Immediate(kInvalidObjectPointer));
6565 __ movl(EDX, Immediate(kInvalidObjectPointer)); 7030 __ movl(EDX, Immediate(kInvalidObjectPointer));
6566 #endif 7031 #endif
6567 } 7032 }
6568 7033
6569 } // namespace dart 7034 } // namespace dart
6570 7035
6571 #undef __ 7036 #undef __
6572 7037
6573 #endif // defined TARGET_ARCH_IA32 7038 #endif // defined TARGET_ARCH_IA32
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698