Chromium Code Reviews| 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 if (FLAG_throw_on_javascript_int_overflow) { | |
|
srdjan
2013/08/02 18:07:22
I would move this test at call sites, think it is
zra
2013/08/02 18:30:27
Done.
| |
| 657 // Compare upper half. | |
| 658 Label check_lower, done; | |
| 659 __ pextrd(tmp, result, Immediate(1)); | |
| 660 __ cmpl(tmp, Immediate(0x00200000)); | |
| 661 __ j(GREATER, overflow); | |
| 662 __ j(NOT_EQUAL, &check_lower); | |
| 663 | |
| 664 __ pextrd(tmp, result, Immediate(0)); | |
| 665 __ cmpl(tmp, Immediate(0)); | |
| 666 __ j(ABOVE, overflow); | |
| 667 | |
| 668 __ Bind(&check_lower); | |
| 669 __ pextrd(tmp, result, Immediate(1)); | |
| 670 __ cmpl(tmp, Immediate(-0x00200000)); | |
| 671 __ j(LESS, overflow); | |
| 672 // Anything in the lower part would make the number bigger than the lower | |
| 673 // bound, so we are done. | |
| 674 | |
| 675 __ Bind(&done); | |
| 676 } | |
| 677 } | |
| 678 | |
| 679 | |
| 651 static Condition TokenKindToMintCondition(Token::Kind kind) { | 680 static Condition TokenKindToMintCondition(Token::Kind kind) { |
| 652 switch (kind) { | 681 switch (kind) { |
| 653 case Token::kEQ: return EQUAL; | 682 case Token::kEQ: return EQUAL; |
| 654 case Token::kNE: return NOT_EQUAL; | 683 case Token::kNE: return NOT_EQUAL; |
| 655 case Token::kLT: return LESS; | 684 case Token::kLT: return LESS; |
| 656 case Token::kGT: return GREATER; | 685 case Token::kGT: return GREATER; |
| 657 case Token::kLTE: return LESS_EQUAL; | 686 case Token::kLTE: return LESS_EQUAL; |
| 658 case Token::kGTE: return GREATER_EQUAL; | 687 case Token::kGTE: return GREATER_EQUAL; |
| 659 default: | 688 default: |
| 660 UNREACHABLE(); | 689 UNREACHABLE(); |
| (...skipping 3605 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4266 __ Bind(&done); | 4295 __ Bind(&done); |
| 4267 } | 4296 } |
| 4268 | 4297 |
| 4269 | 4298 |
| 4270 LocationSummary* BinaryMintOpInstr::MakeLocationSummary() const { | 4299 LocationSummary* BinaryMintOpInstr::MakeLocationSummary() const { |
| 4271 const intptr_t kNumInputs = 2; | 4300 const intptr_t kNumInputs = 2; |
| 4272 switch (op_kind()) { | 4301 switch (op_kind()) { |
| 4273 case Token::kBIT_AND: | 4302 case Token::kBIT_AND: |
| 4274 case Token::kBIT_OR: | 4303 case Token::kBIT_OR: |
| 4275 case Token::kBIT_XOR: { | 4304 case Token::kBIT_XOR: { |
| 4276 const intptr_t kNumTemps = 0; | 4305 const intptr_t kNumTemps = |
| 4306 FLAG_throw_on_javascript_int_overflow ? 1 : 0; | |
| 4277 LocationSummary* summary = | 4307 LocationSummary* summary = |
| 4278 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4308 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4279 summary->set_in(0, Location::RequiresFpuRegister()); | 4309 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4280 summary->set_in(1, Location::RequiresFpuRegister()); | 4310 summary->set_in(1, Location::RequiresFpuRegister()); |
| 4311 if (FLAG_throw_on_javascript_int_overflow) { | |
| 4312 summary->set_temp(0, Location::RequiresRegister()); | |
| 4313 } | |
| 4281 summary->set_out(Location::SameAsFirstInput()); | 4314 summary->set_out(Location::SameAsFirstInput()); |
| 4282 return summary; | 4315 return summary; |
| 4283 } | 4316 } |
| 4284 case Token::kADD: | 4317 case Token::kADD: |
| 4285 case Token::kSUB: { | 4318 case Token::kSUB: { |
| 4286 const intptr_t kNumTemps = 2; | 4319 const intptr_t kNumTemps = 2; |
| 4287 LocationSummary* summary = | 4320 LocationSummary* summary = |
| 4288 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4321 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4289 summary->set_in(0, Location::RequiresFpuRegister()); | 4322 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4290 summary->set_in(1, Location::RequiresFpuRegister()); | 4323 summary->set_in(1, Location::RequiresFpuRegister()); |
| 4291 summary->set_temp(0, Location::RequiresRegister()); | 4324 summary->set_temp(0, Location::RequiresRegister()); |
| 4292 summary->set_temp(1, Location::RequiresRegister()); | 4325 summary->set_temp(1, Location::RequiresRegister()); |
| 4293 summary->set_out(Location::SameAsFirstInput()); | 4326 summary->set_out(Location::SameAsFirstInput()); |
| 4294 return summary; | 4327 return summary; |
| 4295 } | 4328 } |
| 4296 default: | 4329 default: |
| 4297 UNREACHABLE(); | 4330 UNREACHABLE(); |
| 4298 return NULL; | 4331 return NULL; |
| 4299 } | 4332 } |
| 4300 } | 4333 } |
| 4301 | 4334 |
| 4302 | 4335 |
| 4303 void BinaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4336 void BinaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4304 XmmRegister left = locs()->in(0).fpu_reg(); | 4337 XmmRegister left = locs()->in(0).fpu_reg(); |
| 4305 XmmRegister right = locs()->in(1).fpu_reg(); | 4338 XmmRegister right = locs()->in(1).fpu_reg(); |
| 4306 | 4339 |
| 4307 ASSERT(locs()->out().fpu_reg() == left); | 4340 ASSERT(locs()->out().fpu_reg() == left); |
| 4308 | 4341 |
| 4342 Label* deopt = NULL; | |
| 4343 if (FLAG_throw_on_javascript_int_overflow) { | |
| 4344 deopt = compiler->AddDeoptStub(deopt_id(), kDeoptBinaryMintOp); | |
| 4345 } | |
| 4309 switch (op_kind()) { | 4346 switch (op_kind()) { |
| 4310 case Token::kBIT_AND: __ andpd(left, right); break; | 4347 case Token::kBIT_AND: __ andpd(left, right); break; |
| 4311 case Token::kBIT_OR: __ orpd(left, right); break; | 4348 case Token::kBIT_OR: __ orpd(left, right); break; |
| 4312 case Token::kBIT_XOR: __ xorpd(left, right); break; | 4349 case Token::kBIT_XOR: __ xorpd(left, right); break; |
| 4313 case Token::kADD: | 4350 case Token::kADD: |
| 4314 case Token::kSUB: { | 4351 case Token::kSUB: { |
| 4315 Register lo = locs()->temp(0).reg(); | 4352 Register lo = locs()->temp(0).reg(); |
| 4316 Register hi = locs()->temp(1).reg(); | 4353 Register hi = locs()->temp(1).reg(); |
| 4317 Label* deopt = compiler->AddDeoptStub(deopt_id(), | 4354 if (!FLAG_throw_on_javascript_int_overflow) { |
| 4318 kDeoptBinaryMintOp); | 4355 deopt = compiler->AddDeoptStub(deopt_id(), kDeoptBinaryMintOp); |
| 4356 } | |
| 4357 | |
| 4319 Label done, overflow; | 4358 Label done, overflow; |
| 4320 __ pextrd(lo, right, Immediate(0)); // Lower half | 4359 __ pextrd(lo, right, Immediate(0)); // Lower half |
| 4321 __ pextrd(hi, right, Immediate(1)); // Upper half | 4360 __ pextrd(hi, right, Immediate(1)); // Upper half |
| 4322 __ subl(ESP, Immediate(2 * kWordSize)); | 4361 __ subl(ESP, Immediate(2 * kWordSize)); |
| 4323 __ movq(Address(ESP, 0), left); | 4362 __ movq(Address(ESP, 0), left); |
| 4324 if (op_kind() == Token::kADD) { | 4363 if (op_kind() == Token::kADD) { |
| 4325 __ addl(Address(ESP, 0), lo); | 4364 __ addl(Address(ESP, 0), lo); |
| 4326 __ adcl(Address(ESP, 1 * kWordSize), hi); | 4365 __ adcl(Address(ESP, 1 * kWordSize), hi); |
| 4327 } else { | 4366 } else { |
| 4328 __ subl(Address(ESP, 0), lo); | 4367 __ subl(Address(ESP, 0), lo); |
| 4329 __ sbbl(Address(ESP, 1 * kWordSize), hi); | 4368 __ sbbl(Address(ESP, 1 * kWordSize), hi); |
| 4330 } | 4369 } |
| 4331 __ j(OVERFLOW, &overflow); | 4370 __ j(OVERFLOW, &overflow); |
| 4332 __ movq(left, Address(ESP, 0)); | 4371 __ movq(left, Address(ESP, 0)); |
| 4333 __ addl(ESP, Immediate(2 * kWordSize)); | 4372 __ addl(ESP, Immediate(2 * kWordSize)); |
| 4334 __ jmp(&done); | 4373 __ jmp(&done); |
| 4335 __ Bind(&overflow); | 4374 __ Bind(&overflow); |
| 4336 __ addl(ESP, Immediate(2 * kWordSize)); | 4375 __ addl(ESP, Immediate(2 * kWordSize)); |
| 4337 __ jmp(deopt); | 4376 __ jmp(deopt); |
| 4338 __ Bind(&done); | 4377 __ Bind(&done); |
| 4339 break; | 4378 break; |
| 4340 } | 4379 } |
| 4341 default: UNREACHABLE(); | 4380 default: UNREACHABLE(); |
| 4342 } | 4381 } |
| 4382 if (FLAG_throw_on_javascript_int_overflow) { | |
| 4383 Register tmp = locs()->temp(0).reg(); | |
| 4384 EmitJavascriptIntOverflowCheck(compiler, deopt, left, tmp); | |
| 4385 } | |
| 4343 } | 4386 } |
| 4344 | 4387 |
| 4345 | 4388 |
| 4346 LocationSummary* ShiftMintOpInstr::MakeLocationSummary() const { | 4389 LocationSummary* ShiftMintOpInstr::MakeLocationSummary() const { |
| 4347 const intptr_t kNumInputs = 2; | 4390 const intptr_t kNumInputs = 2; |
| 4348 const intptr_t kNumTemps = op_kind() == Token::kSHL ? 2 : 1; | 4391 const intptr_t kNumTemps = op_kind() == Token::kSHL ? 2 : 1; |
| 4349 LocationSummary* summary = | 4392 LocationSummary* summary = |
| 4350 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4393 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4351 summary->set_in(0, Location::RequiresFpuRegister()); | 4394 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4352 summary->set_in(1, Location::RegisterLocation(ECX)); | 4395 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); | 4446 __ j(NOT_EQUAL, deopt); |
| 4404 break; | 4447 break; |
| 4405 } | 4448 } |
| 4406 default: | 4449 default: |
| 4407 UNREACHABLE(); | 4450 UNREACHABLE(); |
| 4408 break; | 4451 break; |
| 4409 } | 4452 } |
| 4410 __ movq(left, Address(ESP, 0)); | 4453 __ movq(left, Address(ESP, 0)); |
| 4411 __ addl(ESP, Immediate(2 * kWordSize)); | 4454 __ addl(ESP, Immediate(2 * kWordSize)); |
| 4412 __ Bind(&done); | 4455 __ Bind(&done); |
| 4456 Register tmp = locs()->temp(0).reg(); | |
| 4457 EmitJavascriptIntOverflowCheck(compiler, deopt, left, tmp); | |
| 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 |