| 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 "lib/error.h" | 10 #include "lib/error.h" |
| 11 #include "vm/dart_entry.h" | 11 #include "vm/dart_entry.h" |
| 12 #include "vm/flow_graph_compiler.h" | 12 #include "vm/flow_graph_compiler.h" |
| 13 #include "vm/locations.h" | 13 #include "vm/locations.h" |
| 14 #include "vm/object_store.h" | 14 #include "vm/object_store.h" |
| 15 #include "vm/parser.h" | 15 #include "vm/parser.h" |
| 16 #include "vm/stack_frame.h" | 16 #include "vm/stack_frame.h" |
| 17 #include "vm/stub_code.h" | 17 #include "vm/stub_code.h" |
| 18 #include "vm/symbols.h" | 18 #include "vm/symbols.h" |
| 19 | 19 |
| 20 #define __ compiler->assembler()-> | 20 #define __ compiler->assembler()-> |
| 21 | 21 |
| 22 namespace dart { | 22 namespace dart { |
| 23 | 23 |
| 24 DECLARE_FLAG(int, optimization_counter_threshold); | 24 DECLARE_FLAG(int, optimization_counter_threshold); |
| 25 DECLARE_FLAG(bool, propagate_ic_data); | 25 DECLARE_FLAG(bool, propagate_ic_data); |
| 26 DECLARE_FLAG(bool, use_osr); | 26 DECLARE_FLAG(bool, use_osr); |
| 27 DECLARE_FLAG(bool, throw_on_javascript_int_overflow); |
| 27 | 28 |
| 28 // Generic summary for call instructions that have all arguments pushed | 29 // Generic summary for call instructions that have all arguments pushed |
| 29 // on the stack and return the result in a fixed register EAX. | 30 // on the stack and return the result in a fixed register EAX. |
| 30 LocationSummary* Instruction::MakeCallSummary() { | 31 LocationSummary* Instruction::MakeCallSummary() { |
| 31 LocationSummary* result = new LocationSummary(0, 0, LocationSummary::kCall); | 32 LocationSummary* result = new LocationSummary(0, 0, LocationSummary::kCall); |
| 32 result->set_out(Location::RegisterLocation(EAX)); | 33 result->set_out(Location::RegisterLocation(EAX)); |
| 33 return result; | 34 return result; |
| 34 } | 35 } |
| 35 | 36 |
| 36 | 37 |
| (...skipping 604 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 641 __ j(true_condition, &is_true); | 642 __ j(true_condition, &is_true); |
| 642 __ LoadObject(result, Bool::False()); | 643 __ LoadObject(result, Bool::False()); |
| 643 __ jmp(&done); | 644 __ jmp(&done); |
| 644 __ Bind(&is_true); | 645 __ Bind(&is_true); |
| 645 __ LoadObject(result, Bool::True()); | 646 __ LoadObject(result, Bool::True()); |
| 646 __ Bind(&done); | 647 __ Bind(&done); |
| 647 } | 648 } |
| 648 } | 649 } |
| 649 | 650 |
| 650 | 651 |
| 652 static void EmitJavascriptIntOverflowCheck(FlowGraphCompiler* compiler, |
| 653 Label* overflow, |
| 654 XmmRegister result, |
| 655 Register tmp) { |
| 656 // Compare upper half. |
| 657 Label check_lower, done; |
| 658 __ pextrd(tmp, result, Immediate(1)); |
| 659 __ cmpl(tmp, Immediate(0x00200000)); |
| 660 __ j(GREATER, overflow); |
| 661 __ j(NOT_EQUAL, &check_lower); |
| 662 |
| 663 __ pextrd(tmp, result, Immediate(0)); |
| 664 __ cmpl(tmp, Immediate(0)); |
| 665 __ j(ABOVE, overflow); |
| 666 |
| 667 __ Bind(&check_lower); |
| 668 __ pextrd(tmp, result, Immediate(1)); |
| 669 __ cmpl(tmp, Immediate(-0x00200000)); |
| 670 __ j(LESS, overflow); |
| 671 // Anything in the lower part would make the number bigger than the lower |
| 672 // bound, so we are done. |
| 673 |
| 674 __ Bind(&done); |
| 675 } |
| 676 |
| 677 |
| 651 static Condition TokenKindToMintCondition(Token::Kind kind) { | 678 static Condition TokenKindToMintCondition(Token::Kind kind) { |
| 652 switch (kind) { | 679 switch (kind) { |
| 653 case Token::kEQ: return EQUAL; | 680 case Token::kEQ: return EQUAL; |
| 654 case Token::kNE: return NOT_EQUAL; | 681 case Token::kNE: return NOT_EQUAL; |
| 655 case Token::kLT: return LESS; | 682 case Token::kLT: return LESS; |
| 656 case Token::kGT: return GREATER; | 683 case Token::kGT: return GREATER; |
| 657 case Token::kLTE: return LESS_EQUAL; | 684 case Token::kLTE: return LESS_EQUAL; |
| 658 case Token::kGTE: return GREATER_EQUAL; | 685 case Token::kGTE: return GREATER_EQUAL; |
| 659 default: | 686 default: |
| 660 UNREACHABLE(); | 687 UNREACHABLE(); |
| (...skipping 3605 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4266 __ Bind(&done); | 4293 __ Bind(&done); |
| 4267 } | 4294 } |
| 4268 | 4295 |
| 4269 | 4296 |
| 4270 LocationSummary* BinaryMintOpInstr::MakeLocationSummary() const { | 4297 LocationSummary* BinaryMintOpInstr::MakeLocationSummary() const { |
| 4271 const intptr_t kNumInputs = 2; | 4298 const intptr_t kNumInputs = 2; |
| 4272 switch (op_kind()) { | 4299 switch (op_kind()) { |
| 4273 case Token::kBIT_AND: | 4300 case Token::kBIT_AND: |
| 4274 case Token::kBIT_OR: | 4301 case Token::kBIT_OR: |
| 4275 case Token::kBIT_XOR: { | 4302 case Token::kBIT_XOR: { |
| 4276 const intptr_t kNumTemps = 0; | 4303 const intptr_t kNumTemps = |
| 4304 FLAG_throw_on_javascript_int_overflow ? 1 : 0; |
| 4277 LocationSummary* summary = | 4305 LocationSummary* summary = |
| 4278 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4306 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4279 summary->set_in(0, Location::RequiresFpuRegister()); | 4307 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4280 summary->set_in(1, Location::RequiresFpuRegister()); | 4308 summary->set_in(1, Location::RequiresFpuRegister()); |
| 4309 if (FLAG_throw_on_javascript_int_overflow) { |
| 4310 summary->set_temp(0, Location::RequiresRegister()); |
| 4311 } |
| 4281 summary->set_out(Location::SameAsFirstInput()); | 4312 summary->set_out(Location::SameAsFirstInput()); |
| 4282 return summary; | 4313 return summary; |
| 4283 } | 4314 } |
| 4284 case Token::kADD: | 4315 case Token::kADD: |
| 4285 case Token::kSUB: { | 4316 case Token::kSUB: { |
| 4286 const intptr_t kNumTemps = 2; | 4317 const intptr_t kNumTemps = 2; |
| 4287 LocationSummary* summary = | 4318 LocationSummary* summary = |
| 4288 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4319 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4289 summary->set_in(0, Location::RequiresFpuRegister()); | 4320 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4290 summary->set_in(1, Location::RequiresFpuRegister()); | 4321 summary->set_in(1, Location::RequiresFpuRegister()); |
| 4291 summary->set_temp(0, Location::RequiresRegister()); | 4322 summary->set_temp(0, Location::RequiresRegister()); |
| 4292 summary->set_temp(1, Location::RequiresRegister()); | 4323 summary->set_temp(1, Location::RequiresRegister()); |
| 4293 summary->set_out(Location::SameAsFirstInput()); | 4324 summary->set_out(Location::SameAsFirstInput()); |
| 4294 return summary; | 4325 return summary; |
| 4295 } | 4326 } |
| 4296 default: | 4327 default: |
| 4297 UNREACHABLE(); | 4328 UNREACHABLE(); |
| 4298 return NULL; | 4329 return NULL; |
| 4299 } | 4330 } |
| 4300 } | 4331 } |
| 4301 | 4332 |
| 4302 | 4333 |
| 4303 void BinaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4334 void BinaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4304 XmmRegister left = locs()->in(0).fpu_reg(); | 4335 XmmRegister left = locs()->in(0).fpu_reg(); |
| 4305 XmmRegister right = locs()->in(1).fpu_reg(); | 4336 XmmRegister right = locs()->in(1).fpu_reg(); |
| 4306 | 4337 |
| 4307 ASSERT(locs()->out().fpu_reg() == left); | 4338 ASSERT(locs()->out().fpu_reg() == left); |
| 4308 | 4339 |
| 4340 Label* deopt = NULL; |
| 4341 if (FLAG_throw_on_javascript_int_overflow) { |
| 4342 deopt = compiler->AddDeoptStub(deopt_id(), kDeoptBinaryMintOp); |
| 4343 } |
| 4309 switch (op_kind()) { | 4344 switch (op_kind()) { |
| 4310 case Token::kBIT_AND: __ andpd(left, right); break; | 4345 case Token::kBIT_AND: __ andpd(left, right); break; |
| 4311 case Token::kBIT_OR: __ orpd(left, right); break; | 4346 case Token::kBIT_OR: __ orpd(left, right); break; |
| 4312 case Token::kBIT_XOR: __ xorpd(left, right); break; | 4347 case Token::kBIT_XOR: __ xorpd(left, right); break; |
| 4313 case Token::kADD: | 4348 case Token::kADD: |
| 4314 case Token::kSUB: { | 4349 case Token::kSUB: { |
| 4315 Register lo = locs()->temp(0).reg(); | 4350 Register lo = locs()->temp(0).reg(); |
| 4316 Register hi = locs()->temp(1).reg(); | 4351 Register hi = locs()->temp(1).reg(); |
| 4317 Label* deopt = compiler->AddDeoptStub(deopt_id(), | 4352 if (!FLAG_throw_on_javascript_int_overflow) { |
| 4318 kDeoptBinaryMintOp); | 4353 deopt = compiler->AddDeoptStub(deopt_id(), kDeoptBinaryMintOp); |
| 4354 } |
| 4355 |
| 4319 Label done, overflow; | 4356 Label done, overflow; |
| 4320 __ pextrd(lo, right, Immediate(0)); // Lower half | 4357 __ pextrd(lo, right, Immediate(0)); // Lower half |
| 4321 __ pextrd(hi, right, Immediate(1)); // Upper half | 4358 __ pextrd(hi, right, Immediate(1)); // Upper half |
| 4322 __ subl(ESP, Immediate(2 * kWordSize)); | 4359 __ subl(ESP, Immediate(2 * kWordSize)); |
| 4323 __ movq(Address(ESP, 0), left); | 4360 __ movq(Address(ESP, 0), left); |
| 4324 if (op_kind() == Token::kADD) { | 4361 if (op_kind() == Token::kADD) { |
| 4325 __ addl(Address(ESP, 0), lo); | 4362 __ addl(Address(ESP, 0), lo); |
| 4326 __ adcl(Address(ESP, 1 * kWordSize), hi); | 4363 __ adcl(Address(ESP, 1 * kWordSize), hi); |
| 4327 } else { | 4364 } else { |
| 4328 __ subl(Address(ESP, 0), lo); | 4365 __ subl(Address(ESP, 0), lo); |
| 4329 __ sbbl(Address(ESP, 1 * kWordSize), hi); | 4366 __ sbbl(Address(ESP, 1 * kWordSize), hi); |
| 4330 } | 4367 } |
| 4331 __ j(OVERFLOW, &overflow); | 4368 __ j(OVERFLOW, &overflow); |
| 4332 __ movq(left, Address(ESP, 0)); | 4369 __ movq(left, Address(ESP, 0)); |
| 4333 __ addl(ESP, Immediate(2 * kWordSize)); | 4370 __ addl(ESP, Immediate(2 * kWordSize)); |
| 4334 __ jmp(&done); | 4371 __ jmp(&done); |
| 4335 __ Bind(&overflow); | 4372 __ Bind(&overflow); |
| 4336 __ addl(ESP, Immediate(2 * kWordSize)); | 4373 __ addl(ESP, Immediate(2 * kWordSize)); |
| 4337 __ jmp(deopt); | 4374 __ jmp(deopt); |
| 4338 __ Bind(&done); | 4375 __ Bind(&done); |
| 4339 break; | 4376 break; |
| 4340 } | 4377 } |
| 4341 default: UNREACHABLE(); | 4378 default: UNREACHABLE(); |
| 4342 } | 4379 } |
| 4380 if (FLAG_throw_on_javascript_int_overflow) { |
| 4381 Register tmp = locs()->temp(0).reg(); |
| 4382 EmitJavascriptIntOverflowCheck(compiler, deopt, left, tmp); |
| 4383 } |
| 4343 } | 4384 } |
| 4344 | 4385 |
| 4345 | 4386 |
| 4346 LocationSummary* ShiftMintOpInstr::MakeLocationSummary() const { | 4387 LocationSummary* ShiftMintOpInstr::MakeLocationSummary() const { |
| 4347 const intptr_t kNumInputs = 2; | 4388 const intptr_t kNumInputs = 2; |
| 4348 const intptr_t kNumTemps = op_kind() == Token::kSHL ? 2 : 1; | 4389 const intptr_t kNumTemps = op_kind() == Token::kSHL ? 2 : 1; |
| 4349 LocationSummary* summary = | 4390 LocationSummary* summary = |
| 4350 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4391 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4351 summary->set_in(0, Location::RequiresFpuRegister()); | 4392 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4352 summary->set_in(1, Location::RegisterLocation(ECX)); | 4393 summary->set_in(1, Location::RegisterLocation(ECX)); |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4403 __ j(NOT_EQUAL, deopt); | 4444 __ j(NOT_EQUAL, deopt); |
| 4404 break; | 4445 break; |
| 4405 } | 4446 } |
| 4406 default: | 4447 default: |
| 4407 UNREACHABLE(); | 4448 UNREACHABLE(); |
| 4408 break; | 4449 break; |
| 4409 } | 4450 } |
| 4410 __ movq(left, Address(ESP, 0)); | 4451 __ movq(left, Address(ESP, 0)); |
| 4411 __ addl(ESP, Immediate(2 * kWordSize)); | 4452 __ addl(ESP, Immediate(2 * kWordSize)); |
| 4412 __ Bind(&done); | 4453 __ Bind(&done); |
| 4454 if (FLAG_throw_on_javascript_int_overflow) { |
| 4455 Register tmp = locs()->temp(0).reg(); |
| 4456 EmitJavascriptIntOverflowCheck(compiler, deopt, left, tmp); |
| 4457 } |
| 4413 } | 4458 } |
| 4414 | 4459 |
| 4415 | 4460 |
| 4416 LocationSummary* UnaryMintOpInstr::MakeLocationSummary() const { | 4461 LocationSummary* UnaryMintOpInstr::MakeLocationSummary() const { |
| 4417 const intptr_t kNumInputs = 1; | 4462 const intptr_t kNumInputs = 1; |
| 4418 const intptr_t kNumTemps = 0; | 4463 const intptr_t kNumTemps = |
| 4464 FLAG_throw_on_javascript_int_overflow ? 1 : 0; |
| 4419 LocationSummary* summary = | 4465 LocationSummary* summary = |
| 4420 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4466 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4421 summary->set_in(0, Location::RequiresFpuRegister()); | 4467 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4422 summary->set_out(Location::SameAsFirstInput()); | 4468 summary->set_out(Location::SameAsFirstInput()); |
| 4423 return summary; | 4469 return summary; |
| 4424 } | 4470 } |
| 4425 | 4471 |
| 4426 | 4472 |
| 4427 void UnaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4473 void UnaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4428 ASSERT(op_kind() == Token::kBIT_NOT); | 4474 ASSERT(op_kind() == Token::kBIT_NOT); |
| 4429 XmmRegister value = locs()->in(0).fpu_reg(); | 4475 XmmRegister value = locs()->in(0).fpu_reg(); |
| 4430 ASSERT(value == locs()->out().fpu_reg()); | 4476 ASSERT(value == locs()->out().fpu_reg()); |
| 4477 Label* deopt = NULL; |
| 4478 if (FLAG_throw_on_javascript_int_overflow) { |
| 4479 deopt = compiler->AddDeoptStub(deopt_id(), |
| 4480 kDeoptUnaryMintOp); |
| 4481 } |
| 4431 __ pcmpeqq(XMM0, XMM0); // Generate all 1's. | 4482 __ pcmpeqq(XMM0, XMM0); // Generate all 1's. |
| 4432 __ pxor(value, XMM0); | 4483 __ pxor(value, XMM0); |
| 4484 if (FLAG_throw_on_javascript_int_overflow) { |
| 4485 Register tmp = locs()->temp(0).reg(); |
| 4486 EmitJavascriptIntOverflowCheck(compiler, deopt, value, tmp); |
| 4487 } |
| 4433 } | 4488 } |
| 4434 | 4489 |
| 4435 | 4490 |
| 4436 LocationSummary* ThrowInstr::MakeLocationSummary() const { | 4491 LocationSummary* ThrowInstr::MakeLocationSummary() const { |
| 4437 return new LocationSummary(0, 0, LocationSummary::kCall); | 4492 return new LocationSummary(0, 0, LocationSummary::kCall); |
| 4438 } | 4493 } |
| 4439 | 4494 |
| 4440 | 4495 |
| 4441 | 4496 |
| 4442 void ThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4497 void ThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| (...skipping 432 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4875 PcDescriptors::kOther, | 4930 PcDescriptors::kOther, |
| 4876 locs()); | 4931 locs()); |
| 4877 __ Drop(2); // Discard type arguments and receiver. | 4932 __ Drop(2); // Discard type arguments and receiver. |
| 4878 } | 4933 } |
| 4879 | 4934 |
| 4880 } // namespace dart | 4935 } // namespace dart |
| 4881 | 4936 |
| 4882 #undef __ | 4937 #undef __ |
| 4883 | 4938 |
| 4884 #endif // defined TARGET_ARCH_IA32 | 4939 #endif // defined TARGET_ARCH_IA32 |
| OLD | NEW |