| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 335 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 346 current_instruction_, | 346 current_instruction_, |
| 347 instr->hydrogen_value()->id(), | 347 instr->hydrogen_value()->id(), |
| 348 instr->Mnemonic()); | 348 instr->Mnemonic()); |
| 349 } | 349 } |
| 350 | 350 |
| 351 if (!CpuFeatures::IsSupported(SSE2)) FlushX87StackIfNecessary(instr); | 351 if (!CpuFeatures::IsSupported(SSE2)) FlushX87StackIfNecessary(instr); |
| 352 | 352 |
| 353 instr->CompileToNative(this); | 353 instr->CompileToNative(this); |
| 354 | 354 |
| 355 if (!CpuFeatures::IsSupported(SSE2)) { | 355 if (!CpuFeatures::IsSupported(SSE2)) { |
| 356 ASSERT(!instr->HasDoubleRegisterResult() || x87_stack_depth_ == 1); | |
| 357 if (FLAG_debug_code && FLAG_enable_slow_asserts) { | 356 if (FLAG_debug_code && FLAG_enable_slow_asserts) { |
| 358 __ VerifyX87StackDepth(x87_stack_depth_); | 357 __ VerifyX87StackDepth(x87_stack_depth_); |
| 359 } | 358 } |
| 360 } | 359 } |
| 361 } | 360 } |
| 362 EnsureSpaceForLazyDeopt(); | 361 EnsureSpaceForLazyDeopt(); |
| 363 return !is_aborted(); | 362 return !is_aborted(); |
| 364 } | 363 } |
| 365 | 364 |
| 366 | 365 |
| 367 bool LCodeGen::GenerateJumpTable() { | 366 bool LCodeGen::GenerateJumpTable() { |
| 368 Label needs_frame_not_call; | 367 Label needs_frame; |
| 369 Label needs_frame_is_call; | |
| 370 if (jump_table_.length() > 0) { | 368 if (jump_table_.length() > 0) { |
| 371 Comment(";;; -------------------- Jump table --------------------"); | 369 Comment(";;; -------------------- Jump table --------------------"); |
| 372 } | 370 } |
| 373 for (int i = 0; i < jump_table_.length(); i++) { | 371 for (int i = 0; i < jump_table_.length(); i++) { |
| 374 __ bind(&jump_table_[i].label); | 372 __ bind(&jump_table_[i].label); |
| 375 Address entry = jump_table_[i].address; | 373 Address entry = jump_table_[i].address; |
| 376 Deoptimizer::BailoutType type = jump_table_[i].bailout_type; | 374 Deoptimizer::BailoutType type = jump_table_[i].bailout_type; |
| 377 int id = Deoptimizer::GetDeoptimizationId(isolate(), entry, type); | 375 int id = Deoptimizer::GetDeoptimizationId(isolate(), entry, type); |
| 378 if (id == Deoptimizer::kNotDeoptimizationEntry) { | 376 if (id == Deoptimizer::kNotDeoptimizationEntry) { |
| 379 Comment(";;; jump table entry %d.", i); | 377 Comment(";;; jump table entry %d.", i); |
| 380 } else { | 378 } else { |
| 381 Comment(";;; jump table entry %d: deoptimization bailout %d.", i, id); | 379 Comment(";;; jump table entry %d: deoptimization bailout %d.", i, id); |
| 382 } | 380 } |
| 383 if (jump_table_[i].needs_frame) { | 381 if (jump_table_[i].needs_frame) { |
| 384 __ push(Immediate(ExternalReference::ForDeoptEntry(entry))); | 382 __ push(Immediate(ExternalReference::ForDeoptEntry(entry))); |
| 385 if (type == Deoptimizer::LAZY) { | 383 if (needs_frame.is_bound()) { |
| 386 if (needs_frame_is_call.is_bound()) { | 384 __ jmp(&needs_frame); |
| 387 __ jmp(&needs_frame_is_call); | |
| 388 } else { | |
| 389 __ bind(&needs_frame_is_call); | |
| 390 __ push(MemOperand(ebp, StandardFrameConstants::kContextOffset)); | |
| 391 // This variant of deopt can only be used with stubs. Since we don't | |
| 392 // have a function pointer to install in the stack frame that we're | |
| 393 // building, install a special marker there instead. | |
| 394 ASSERT(info()->IsStub()); | |
| 395 __ push(Immediate(Smi::FromInt(StackFrame::STUB))); | |
| 396 // Push a PC inside the function so that the deopt code can find where | |
| 397 // the deopt comes from. It doesn't have to be the precise return | |
| 398 // address of a "calling" LAZY deopt, it only has to be somewhere | |
| 399 // inside the code body. | |
| 400 Label push_approx_pc; | |
| 401 __ call(&push_approx_pc); | |
| 402 __ bind(&push_approx_pc); | |
| 403 // Push the continuation which was stashed were the ebp should | |
| 404 // be. Replace it with the saved ebp. | |
| 405 __ push(MemOperand(esp, 3 * kPointerSize)); | |
| 406 __ mov(MemOperand(esp, 4 * kPointerSize), ebp); | |
| 407 __ lea(ebp, MemOperand(esp, 4 * kPointerSize)); | |
| 408 __ ret(0); // Call the continuation without clobbering registers. | |
| 409 } | |
| 410 } else { | 385 } else { |
| 411 if (needs_frame_not_call.is_bound()) { | 386 __ bind(&needs_frame); |
| 412 __ jmp(&needs_frame_not_call); | 387 __ push(MemOperand(ebp, StandardFrameConstants::kContextOffset)); |
| 413 } else { | 388 // This variant of deopt can only be used with stubs. Since we don't |
| 414 __ bind(&needs_frame_not_call); | 389 // have a function pointer to install in the stack frame that we're |
| 415 __ push(MemOperand(ebp, StandardFrameConstants::kContextOffset)); | 390 // building, install a special marker there instead. |
| 416 // This variant of deopt can only be used with stubs. Since we don't | 391 ASSERT(info()->IsStub()); |
| 417 // have a function pointer to install in the stack frame that we're | 392 __ push(Immediate(Smi::FromInt(StackFrame::STUB))); |
| 418 // building, install a special marker there instead. | 393 // Push a PC inside the function so that the deopt code can find where |
| 419 ASSERT(info()->IsStub()); | 394 // the deopt comes from. It doesn't have to be the precise return |
| 420 __ push(Immediate(Smi::FromInt(StackFrame::STUB))); | 395 // address of a "calling" LAZY deopt, it only has to be somewhere |
| 421 // Push the continuation which was stashed were the ebp should | 396 // inside the code body. |
| 422 // be. Replace it with the saved ebp. | 397 Label push_approx_pc; |
| 423 __ push(MemOperand(esp, 2 * kPointerSize)); | 398 __ call(&push_approx_pc); |
| 424 __ mov(MemOperand(esp, 3 * kPointerSize), ebp); | 399 __ bind(&push_approx_pc); |
| 425 __ lea(ebp, MemOperand(esp, 3 * kPointerSize)); | 400 // Push the continuation which was stashed were the ebp should |
| 426 __ ret(0); // Call the continuation without clobbering registers. | 401 // be. Replace it with the saved ebp. |
| 427 } | 402 __ push(MemOperand(esp, 3 * kPointerSize)); |
| 403 __ mov(MemOperand(esp, 4 * kPointerSize), ebp); |
| 404 __ lea(ebp, MemOperand(esp, 4 * kPointerSize)); |
| 405 __ ret(0); // Call the continuation without clobbering registers. |
| 428 } | 406 } |
| 429 } else { | 407 } else { |
| 430 if (type == Deoptimizer::LAZY) { | 408 __ call(entry, RelocInfo::RUNTIME_ENTRY); |
| 431 __ call(entry, RelocInfo::RUNTIME_ENTRY); | |
| 432 } else { | |
| 433 __ jmp(entry, RelocInfo::RUNTIME_ENTRY); | |
| 434 } | |
| 435 } | 409 } |
| 436 } | 410 } |
| 437 return !is_aborted(); | 411 return !is_aborted(); |
| 438 } | 412 } |
| 439 | 413 |
| 440 | 414 |
| 441 bool LCodeGen::GenerateDeferredCode() { | 415 bool LCodeGen::GenerateDeferredCode() { |
| 442 ASSERT(is_generating()); | 416 ASSERT(is_generating()); |
| 443 if (deferred_.length() > 0) { | 417 if (deferred_.length() > 0) { |
| 444 for (int i = 0; !is_aborted() && i < deferred_.length(); i++) { | 418 for (int i = 0; !is_aborted() && i < deferred_.length(); i++) { |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 494 safepoints_.Emit(masm(), GetStackSlotCount()); | 468 safepoints_.Emit(masm(), GetStackSlotCount()); |
| 495 return !is_aborted(); | 469 return !is_aborted(); |
| 496 } | 470 } |
| 497 | 471 |
| 498 | 472 |
| 499 Register LCodeGen::ToRegister(int index) const { | 473 Register LCodeGen::ToRegister(int index) const { |
| 500 return Register::FromAllocationIndex(index); | 474 return Register::FromAllocationIndex(index); |
| 501 } | 475 } |
| 502 | 476 |
| 503 | 477 |
| 478 X87Register LCodeGen::ToX87Register(int index) const { |
| 479 return X87Register::FromAllocationIndex(index); |
| 480 } |
| 481 |
| 482 |
| 504 XMMRegister LCodeGen::ToDoubleRegister(int index) const { | 483 XMMRegister LCodeGen::ToDoubleRegister(int index) const { |
| 505 return XMMRegister::FromAllocationIndex(index); | 484 return XMMRegister::FromAllocationIndex(index); |
| 506 } | 485 } |
| 507 | 486 |
| 508 | 487 |
| 509 bool LCodeGen::IsX87TopOfStack(LOperand* op) const { | 488 void LCodeGen::X87LoadForUsage(X87Register reg) { |
| 510 return op->IsDoubleRegister(); | 489 ASSERT(X87StackContains(reg)); |
| 490 X87Fxch(reg); |
| 491 x87_stack_depth_--; |
| 511 } | 492 } |
| 512 | 493 |
| 513 | 494 |
| 514 void LCodeGen::ReadX87Operand(Operand dst) { | 495 void LCodeGen::X87Fxch(X87Register reg, int other_slot) { |
| 515 ASSERT(x87_stack_depth_ == 1); | 496 ASSERT(X87StackContains(reg) && x87_stack_depth_ > other_slot); |
| 516 __ fst_d(dst); | 497 int i = X87ArrayIndex(reg); |
| 517 } | 498 int st = x87_st2idx(i); |
| 518 | 499 if (st != other_slot) { |
| 519 | 500 int other_i = x87_st2idx(other_slot); |
| 520 void LCodeGen::PushX87DoubleOperand(Operand src) { | 501 X87Register other = x87_stack_[other_i]; |
| 521 ASSERT(x87_stack_depth_ == 0); | 502 x87_stack_[other_i] = reg; |
| 522 x87_stack_depth_++; | 503 x87_stack_[i] = other; |
| 523 __ fld_d(src); | 504 if (st == 0) { |
| 524 } | 505 __ fxch(other_slot); |
| 525 | 506 } else if (other_slot == 0) { |
| 526 | 507 __ fxch(st); |
| 527 void LCodeGen::PushX87FloatOperand(Operand src) { | 508 } else { |
| 528 ASSERT(x87_stack_depth_ == 0); | 509 __ fxch(st); |
| 529 x87_stack_depth_++; | 510 __ fxch(other_slot); |
| 530 __ fld_s(src); | 511 __ fxch(st); |
| 531 } | |
| 532 | |
| 533 | |
| 534 void LCodeGen::PopX87() { | |
| 535 ASSERT(x87_stack_depth_ == 1); | |
| 536 x87_stack_depth_--; | |
| 537 __ fstp(0); | |
| 538 } | |
| 539 | |
| 540 | |
| 541 void LCodeGen::CurrentInstructionReturnsX87Result() { | |
| 542 ASSERT(x87_stack_depth_ <= 1); | |
| 543 if (x87_stack_depth_ == 0) { | |
| 544 x87_stack_depth_ = 1; | |
| 545 } | |
| 546 } | |
| 547 | |
| 548 | |
| 549 void LCodeGen::FlushX87StackIfNecessary(LInstruction* instr) { | |
| 550 if (x87_stack_depth_ > 0) { | |
| 551 if ((instr->ClobbersDoubleRegisters() || | |
| 552 instr->HasDoubleRegisterResult()) && | |
| 553 !instr->HasDoubleRegisterInput()) { | |
| 554 PopX87(); | |
| 555 } | 512 } |
| 556 } | 513 } |
| 557 } | 514 } |
| 558 | 515 |
| 559 | 516 |
| 517 int LCodeGen::x87_st2idx(int pos) { |
| 518 return x87_stack_depth_ - pos - 1; |
| 519 } |
| 520 |
| 521 |
| 522 int LCodeGen::X87ArrayIndex(X87Register reg) { |
| 523 for (int i = 0; i < x87_stack_depth_; i++) { |
| 524 if (x87_stack_[i].is(reg)) return i; |
| 525 } |
| 526 UNREACHABLE(); |
| 527 return -1; |
| 528 } |
| 529 |
| 530 |
| 531 bool LCodeGen::X87StackContains(X87Register reg) { |
| 532 for (int i = 0; i < x87_stack_depth_; i++) { |
| 533 if (x87_stack_[i].is(reg)) return true; |
| 534 } |
| 535 return false; |
| 536 } |
| 537 |
| 538 |
| 539 void LCodeGen::X87Free(X87Register reg) { |
| 540 ASSERT(X87StackContains(reg)); |
| 541 int i = X87ArrayIndex(reg); |
| 542 int st = x87_st2idx(i); |
| 543 if (st > 0) { |
| 544 // keep track of how fstp(i) changes the order of elements |
| 545 int tos_i = x87_st2idx(0); |
| 546 x87_stack_[i] = x87_stack_[tos_i]; |
| 547 } |
| 548 x87_stack_depth_--; |
| 549 __ fstp(st); |
| 550 } |
| 551 |
| 552 |
| 553 void LCodeGen::X87Mov(X87Register dst, Operand src, X87OperandType opts) { |
| 554 if (X87StackContains(dst)) { |
| 555 X87Fxch(dst); |
| 556 __ fstp(0); |
| 557 } else { |
| 558 ASSERT(x87_stack_depth_ < X87Register::kNumAllocatableRegisters); |
| 559 x87_stack_[x87_stack_depth_] = dst; |
| 560 x87_stack_depth_++; |
| 561 } |
| 562 X87Fld(src, opts); |
| 563 } |
| 564 |
| 565 |
| 566 void LCodeGen::X87Fld(Operand src, X87OperandType opts) { |
| 567 if (opts == kX87DoubleOperand) { |
| 568 __ fld_d(src); |
| 569 } else if (opts == kX87FloatOperand) { |
| 570 __ fld_s(src); |
| 571 } else if (opts == kX87IntOperand) { |
| 572 __ fild_s(src); |
| 573 } else { |
| 574 UNREACHABLE(); |
| 575 } |
| 576 } |
| 577 |
| 578 |
| 579 void LCodeGen::X87Mov(Operand dst, X87Register src) { |
| 580 X87Fxch(src); |
| 581 __ fst_d(dst); |
| 582 } |
| 583 |
| 584 |
| 585 void LCodeGen::X87PrepareToWrite(X87Register reg) { |
| 586 if (X87StackContains(reg)) { |
| 587 X87Free(reg); |
| 588 } |
| 589 // Mark this register as the next register to write to |
| 590 x87_stack_[x87_stack_depth_] = reg; |
| 591 } |
| 592 |
| 593 |
| 594 void LCodeGen::X87CommitWrite(X87Register reg) { |
| 595 // Assert the reg is prepared to write, but not on the virtual stack yet |
| 596 ASSERT(!X87StackContains(reg) && x87_stack_[x87_stack_depth_].is(reg) && |
| 597 x87_stack_depth_ < X87Register::kNumAllocatableRegisters); |
| 598 x87_stack_depth_++; |
| 599 } |
| 600 |
| 601 |
| 602 void LCodeGen::X87PrepareBinaryOp( |
| 603 X87Register left, X87Register right, X87Register result) { |
| 604 // You need to use DefineSameAsFirst for x87 instructions |
| 605 ASSERT(result.is(left)); |
| 606 X87Fxch(right, 1); |
| 607 X87Fxch(left); |
| 608 } |
| 609 |
| 610 |
| 611 void LCodeGen::FlushX87StackIfNecessary(LInstruction* instr) { |
| 612 if (x87_stack_depth_ > 0 && instr->ClobbersDoubleRegisters()) { |
| 613 bool double_inputs = instr->HasDoubleRegisterInput(); |
| 614 |
| 615 // Flush stack from tos down, since FreeX87() will mess with tos |
| 616 for (int i = x87_stack_depth_-1; i >= 0; i--) { |
| 617 X87Register reg = x87_stack_[i]; |
| 618 // Skip registers which contain the inputs for the next instruction |
| 619 // when flushing the stack |
| 620 if (double_inputs && instr->IsDoubleInput(reg, this)) { |
| 621 continue; |
| 622 } |
| 623 X87Free(reg); |
| 624 if (i < x87_stack_depth_-1) i++; |
| 625 } |
| 626 } |
| 627 if (instr->IsReturn()) { |
| 628 while (x87_stack_depth_ > 0) { |
| 629 __ fstp(0); |
| 630 x87_stack_depth_--; |
| 631 } |
| 632 } |
| 633 } |
| 634 |
| 635 |
| 636 void LCodeGen::EmitFlushX87ForDeopt() { |
| 637 for (int i = 0; i < x87_stack_depth_; i++) __ fstp(0); |
| 638 } |
| 639 |
| 640 |
| 560 Register LCodeGen::ToRegister(LOperand* op) const { | 641 Register LCodeGen::ToRegister(LOperand* op) const { |
| 561 ASSERT(op->IsRegister()); | 642 ASSERT(op->IsRegister()); |
| 562 return ToRegister(op->index()); | 643 return ToRegister(op->index()); |
| 563 } | 644 } |
| 564 | 645 |
| 565 | 646 |
| 647 X87Register LCodeGen::ToX87Register(LOperand* op) const { |
| 648 ASSERT(op->IsDoubleRegister()); |
| 649 return ToX87Register(op->index()); |
| 650 } |
| 651 |
| 652 |
| 566 XMMRegister LCodeGen::ToDoubleRegister(LOperand* op) const { | 653 XMMRegister LCodeGen::ToDoubleRegister(LOperand* op) const { |
| 567 ASSERT(op->IsDoubleRegister()); | 654 ASSERT(op->IsDoubleRegister()); |
| 568 return ToDoubleRegister(op->index()); | 655 return ToDoubleRegister(op->index()); |
| 569 } | 656 } |
| 570 | 657 |
| 571 | 658 |
| 572 int LCodeGen::ToInteger32(LConstantOperand* op) const { | 659 int LCodeGen::ToInteger32(LConstantOperand* op) const { |
| 573 HConstant* constant = chunk_->LookupConstant(op); | 660 HConstant* constant = chunk_->LookupConstant(op); |
| 574 return constant->Integer32Value(); | 661 return constant->Integer32Value(); |
| 575 } | 662 } |
| (...skipping 252 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 828 deoptimizations_.Add(environment, zone()); | 915 deoptimizations_.Add(environment, zone()); |
| 829 } | 916 } |
| 830 } | 917 } |
| 831 | 918 |
| 832 | 919 |
| 833 void LCodeGen::DeoptimizeIf(Condition cc, | 920 void LCodeGen::DeoptimizeIf(Condition cc, |
| 834 LEnvironment* environment, | 921 LEnvironment* environment, |
| 835 Deoptimizer::BailoutType bailout_type) { | 922 Deoptimizer::BailoutType bailout_type) { |
| 836 RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt); | 923 RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt); |
| 837 ASSERT(environment->HasBeenRegistered()); | 924 ASSERT(environment->HasBeenRegistered()); |
| 838 // It's an error to deoptimize with the x87 fp stack in use. | |
| 839 ASSERT(x87_stack_depth_ == 0); | |
| 840 int id = environment->deoptimization_index(); | 925 int id = environment->deoptimization_index(); |
| 841 ASSERT(info()->IsOptimizing() || info()->IsStub()); | 926 ASSERT(info()->IsOptimizing() || info()->IsStub()); |
| 842 Address entry = | 927 Address entry = |
| 843 Deoptimizer::GetDeoptimizationEntry(isolate(), id, bailout_type); | 928 Deoptimizer::GetDeoptimizationEntry(isolate(), id, bailout_type); |
| 844 if (entry == NULL) { | 929 if (entry == NULL) { |
| 845 Abort("bailout was not prepared"); | 930 Abort("bailout was not prepared"); |
| 846 return; | 931 return; |
| 847 } | 932 } |
| 848 | 933 |
| 849 if (FLAG_deopt_every_n_times != 0 && !info()->IsStub()) { | 934 if (FLAG_deopt_every_n_times != 0 && !info()->IsStub()) { |
| 850 Handle<SharedFunctionInfo> shared(info()->shared_info()); | 935 Handle<SharedFunctionInfo> shared(info()->shared_info()); |
| 851 Label no_deopt; | 936 Label no_deopt; |
| 852 __ pushfd(); | 937 __ pushfd(); |
| 853 __ push(eax); | 938 __ push(eax); |
| 854 __ push(ebx); | 939 __ push(ebx); |
| 855 __ mov(ebx, shared); | 940 __ mov(ebx, shared); |
| 856 __ mov(eax, | 941 __ mov(eax, |
| 857 FieldOperand(ebx, SharedFunctionInfo::kStressDeoptCounterOffset)); | 942 FieldOperand(ebx, SharedFunctionInfo::kStressDeoptCounterOffset)); |
| 858 __ sub(Operand(eax), Immediate(Smi::FromInt(1))); | 943 __ sub(Operand(eax), Immediate(Smi::FromInt(1))); |
| 859 __ j(not_zero, &no_deopt, Label::kNear); | 944 __ j(not_zero, &no_deopt, Label::kNear); |
| 860 if (FLAG_trap_on_deopt) __ int3(); | 945 if (FLAG_trap_on_deopt) __ int3(); |
| 861 __ mov(eax, Immediate(Smi::FromInt(FLAG_deopt_every_n_times))); | 946 __ mov(eax, Immediate(Smi::FromInt(FLAG_deopt_every_n_times))); |
| 862 __ mov(FieldOperand(ebx, SharedFunctionInfo::kStressDeoptCounterOffset), | 947 __ mov(FieldOperand(ebx, SharedFunctionInfo::kStressDeoptCounterOffset), |
| 863 eax); | 948 eax); |
| 864 __ pop(ebx); | 949 __ pop(ebx); |
| 865 __ pop(eax); | 950 __ pop(eax); |
| 866 __ popfd(); | 951 __ popfd(); |
| 867 __ jmp(entry, RelocInfo::RUNTIME_ENTRY); | 952 ASSERT(frame_is_built_); |
| 953 __ call(entry, RelocInfo::RUNTIME_ENTRY); |
| 868 | 954 |
| 869 __ bind(&no_deopt); | 955 __ bind(&no_deopt); |
| 870 __ mov(FieldOperand(ebx, SharedFunctionInfo::kStressDeoptCounterOffset), | 956 __ mov(FieldOperand(ebx, SharedFunctionInfo::kStressDeoptCounterOffset), |
| 871 eax); | 957 eax); |
| 872 __ pop(ebx); | 958 __ pop(ebx); |
| 873 __ pop(eax); | 959 __ pop(eax); |
| 874 __ popfd(); | 960 __ popfd(); |
| 875 } | 961 } |
| 876 | 962 |
| 963 // Before Instructions which can deopt, we normally flush the x87 stack. But |
| 964 // we can have inputs or outputs of the current instruction on the stack, |
| 965 // thus we need to flush them here from the physical stack to leave it in a |
| 966 // consistent state. |
| 967 if (x87_stack_depth_ > 0) { |
| 968 Label done; |
| 969 if (cc != no_condition) __ j(NegateCondition(cc), &done, Label::kNear); |
| 970 EmitFlushX87ForDeopt(); |
| 971 __ bind(&done); |
| 972 } |
| 973 |
| 877 if (FLAG_trap_on_deopt && info()->IsOptimizing()) { | 974 if (FLAG_trap_on_deopt && info()->IsOptimizing()) { |
| 878 Label done; | 975 Label done; |
| 879 if (cc != no_condition) { | 976 if (cc != no_condition) __ j(NegateCondition(cc), &done, Label::kNear); |
| 880 __ j(NegateCondition(cc), &done, Label::kNear); | |
| 881 } | |
| 882 __ int3(); | 977 __ int3(); |
| 883 __ bind(&done); | 978 __ bind(&done); |
| 884 } | 979 } |
| 885 | 980 |
| 886 ASSERT(info()->IsStub() || frame_is_built_); | 981 ASSERT(info()->IsStub() || frame_is_built_); |
| 887 if (cc == no_condition && frame_is_built_) { | 982 if (cc == no_condition && frame_is_built_) { |
| 888 if (bailout_type == Deoptimizer::LAZY) { | 983 __ call(entry, RelocInfo::RUNTIME_ENTRY); |
| 889 __ call(entry, RelocInfo::RUNTIME_ENTRY); | |
| 890 } else { | |
| 891 __ jmp(entry, RelocInfo::RUNTIME_ENTRY); | |
| 892 } | |
| 893 } else { | 984 } else { |
| 894 // We often have several deopts to the same entry, reuse the last | 985 // We often have several deopts to the same entry, reuse the last |
| 895 // jump entry if this is the case. | 986 // jump entry if this is the case. |
| 896 if (jump_table_.is_empty() || | 987 if (jump_table_.is_empty() || |
| 897 jump_table_.last().address != entry || | 988 jump_table_.last().address != entry || |
| 898 jump_table_.last().needs_frame != !frame_is_built_ || | 989 jump_table_.last().needs_frame != !frame_is_built_ || |
| 899 jump_table_.last().bailout_type != bailout_type) { | 990 jump_table_.last().bailout_type != bailout_type) { |
| 900 Deoptimizer::JumpTableEntry table_entry(entry, | 991 Deoptimizer::JumpTableEntry table_entry(entry, |
| 901 bailout_type, | 992 bailout_type, |
| 902 !frame_is_built_); | 993 !frame_is_built_); |
| (...skipping 811 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1714 } | 1805 } |
| 1715 | 1806 |
| 1716 | 1807 |
| 1717 void LCodeGen::DoConstantD(LConstantD* instr) { | 1808 void LCodeGen::DoConstantD(LConstantD* instr) { |
| 1718 double v = instr->value(); | 1809 double v = instr->value(); |
| 1719 uint64_t int_val = BitCast<uint64_t, double>(v); | 1810 uint64_t int_val = BitCast<uint64_t, double>(v); |
| 1720 int32_t lower = static_cast<int32_t>(int_val); | 1811 int32_t lower = static_cast<int32_t>(int_val); |
| 1721 int32_t upper = static_cast<int32_t>(int_val >> (kBitsPerInt)); | 1812 int32_t upper = static_cast<int32_t>(int_val >> (kBitsPerInt)); |
| 1722 | 1813 |
| 1723 if (!CpuFeatures::IsSafeForSnapshot(SSE2)) { | 1814 if (!CpuFeatures::IsSafeForSnapshot(SSE2)) { |
| 1815 __ push(Immediate(upper)); |
| 1724 __ push(Immediate(lower)); | 1816 __ push(Immediate(lower)); |
| 1725 __ push(Immediate(upper)); | 1817 X87Mov(ToX87Register(instr->result()), Operand(esp, 0)); |
| 1726 PushX87DoubleOperand(Operand(esp, 0)); | |
| 1727 __ add(Operand(esp), Immediate(kDoubleSize)); | 1818 __ add(Operand(esp), Immediate(kDoubleSize)); |
| 1728 CurrentInstructionReturnsX87Result(); | |
| 1729 } else { | 1819 } else { |
| 1730 CpuFeatureScope scope1(masm(), SSE2); | 1820 CpuFeatureScope scope1(masm(), SSE2); |
| 1731 ASSERT(instr->result()->IsDoubleRegister()); | 1821 ASSERT(instr->result()->IsDoubleRegister()); |
| 1732 XMMRegister res = ToDoubleRegister(instr->result()); | 1822 XMMRegister res = ToDoubleRegister(instr->result()); |
| 1733 if (int_val == 0) { | 1823 if (int_val == 0) { |
| 1734 __ xorps(res, res); | 1824 __ xorps(res, res); |
| 1735 } else { | 1825 } else { |
| 1736 Register temp = ToRegister(instr->temp()); | 1826 Register temp = ToRegister(instr->temp()); |
| 1737 if (CpuFeatures::IsSupported(SSE4_1)) { | 1827 if (CpuFeatures::IsSupported(SSE4_1)) { |
| 1738 CpuFeatureScope scope2(masm(), SSE4_1); | 1828 CpuFeatureScope scope2(masm(), SSE4_1); |
| (...skipping 244 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1983 __ j(parity_even, &return_left, Label::kNear); // left == NaN. | 2073 __ j(parity_even, &return_left, Label::kNear); // left == NaN. |
| 1984 __ bind(&return_right); | 2074 __ bind(&return_right); |
| 1985 __ movsd(left_reg, right_reg); | 2075 __ movsd(left_reg, right_reg); |
| 1986 | 2076 |
| 1987 __ bind(&return_left); | 2077 __ bind(&return_left); |
| 1988 } | 2078 } |
| 1989 } | 2079 } |
| 1990 | 2080 |
| 1991 | 2081 |
| 1992 void LCodeGen::DoArithmeticD(LArithmeticD* instr) { | 2082 void LCodeGen::DoArithmeticD(LArithmeticD* instr) { |
| 1993 CpuFeatureScope scope(masm(), SSE2); | 2083 if (CpuFeatures::IsSafeForSnapshot(SSE2)) { |
| 1994 XMMRegister left = ToDoubleRegister(instr->left()); | 2084 CpuFeatureScope scope(masm(), SSE2); |
| 1995 XMMRegister right = ToDoubleRegister(instr->right()); | 2085 XMMRegister left = ToDoubleRegister(instr->left()); |
| 1996 XMMRegister result = ToDoubleRegister(instr->result()); | 2086 XMMRegister right = ToDoubleRegister(instr->right()); |
| 1997 // Modulo uses a fixed result register. | 2087 XMMRegister result = ToDoubleRegister(instr->result()); |
| 1998 ASSERT(instr->op() == Token::MOD || left.is(result)); | 2088 // Modulo uses a fixed result register. |
| 1999 switch (instr->op()) { | 2089 ASSERT(instr->op() == Token::MOD || left.is(result)); |
| 2000 case Token::ADD: | 2090 switch (instr->op()) { |
| 2001 __ addsd(left, right); | 2091 case Token::ADD: |
| 2002 break; | 2092 __ addsd(left, right); |
| 2003 case Token::SUB: | 2093 break; |
| 2004 __ subsd(left, right); | 2094 case Token::SUB: |
| 2005 break; | 2095 __ subsd(left, right); |
| 2006 case Token::MUL: | 2096 break; |
| 2007 __ mulsd(left, right); | 2097 case Token::MUL: |
| 2008 break; | 2098 __ mulsd(left, right); |
| 2009 case Token::DIV: | 2099 break; |
| 2010 __ divsd(left, right); | 2100 case Token::DIV: |
| 2011 // Don't delete this mov. It may improve performance on some CPUs, | 2101 __ divsd(left, right); |
| 2012 // when there is a mulsd depending on the result | 2102 // Don't delete this mov. It may improve performance on some CPUs, |
| 2013 __ movaps(left, left); | 2103 // when there is a mulsd depending on the result |
| 2014 break; | 2104 __ movaps(left, left); |
| 2015 case Token::MOD: { | 2105 break; |
| 2016 // Pass two doubles as arguments on the stack. | 2106 case Token::MOD: { |
| 2017 __ PrepareCallCFunction(4, eax); | 2107 // Pass two doubles as arguments on the stack. |
| 2018 __ movdbl(Operand(esp, 0 * kDoubleSize), left); | 2108 __ PrepareCallCFunction(4, eax); |
| 2019 __ movdbl(Operand(esp, 1 * kDoubleSize), right); | 2109 __ movdbl(Operand(esp, 0 * kDoubleSize), left); |
| 2020 __ CallCFunction( | 2110 __ movdbl(Operand(esp, 1 * kDoubleSize), right); |
| 2021 ExternalReference::double_fp_operation(Token::MOD, isolate()), | 2111 __ CallCFunction( |
| 2022 4); | 2112 ExternalReference::double_fp_operation(Token::MOD, isolate()), |
| 2113 4); |
| 2023 | 2114 |
| 2024 // Return value is in st(0) on ia32. | 2115 // Return value is in st(0) on ia32. |
| 2025 // Store it into the (fixed) result register. | 2116 // Store it into the (fixed) result register. |
| 2026 __ sub(Operand(esp), Immediate(kDoubleSize)); | 2117 __ sub(Operand(esp), Immediate(kDoubleSize)); |
| 2027 __ fstp_d(Operand(esp, 0)); | 2118 __ fstp_d(Operand(esp, 0)); |
| 2028 __ movdbl(result, Operand(esp, 0)); | 2119 __ movdbl(result, Operand(esp, 0)); |
| 2029 __ add(Operand(esp), Immediate(kDoubleSize)); | 2120 __ add(Operand(esp), Immediate(kDoubleSize)); |
| 2030 break; | 2121 break; |
| 2122 } |
| 2123 default: |
| 2124 UNREACHABLE(); |
| 2125 break; |
| 2031 } | 2126 } |
| 2032 default: | 2127 } else { |
| 2033 UNREACHABLE(); | 2128 X87Register left = ToX87Register(instr->left()); |
| 2034 break; | 2129 X87Register right = ToX87Register(instr->right()); |
| 2130 X87Register result = ToX87Register(instr->result()); |
| 2131 X87PrepareBinaryOp(left, right, result); |
| 2132 switch (instr->op()) { |
| 2133 case Token::MUL: |
| 2134 __ fmul_i(1); |
| 2135 break; |
| 2136 default: |
| 2137 UNREACHABLE(); |
| 2138 break; |
| 2139 } |
| 2035 } | 2140 } |
| 2036 } | 2141 } |
| 2037 | 2142 |
| 2038 | 2143 |
| 2039 void LCodeGen::DoNegateNoSSE2D(LNegateNoSSE2D* instr) { | |
| 2040 __ push(Immediate(-1)); | |
| 2041 __ fild_s(Operand(esp, 0)); | |
| 2042 __ add(esp, Immediate(kPointerSize)); | |
| 2043 __ fmulp(); | |
| 2044 CurrentInstructionReturnsX87Result(); | |
| 2045 } | |
| 2046 | |
| 2047 | |
| 2048 | |
| 2049 void LCodeGen::DoArithmeticT(LArithmeticT* instr) { | 2144 void LCodeGen::DoArithmeticT(LArithmeticT* instr) { |
| 2050 ASSERT(ToRegister(instr->context()).is(esi)); | 2145 ASSERT(ToRegister(instr->context()).is(esi)); |
| 2051 ASSERT(ToRegister(instr->left()).is(edx)); | 2146 ASSERT(ToRegister(instr->left()).is(edx)); |
| 2052 ASSERT(ToRegister(instr->right()).is(eax)); | 2147 ASSERT(ToRegister(instr->right()).is(eax)); |
| 2053 ASSERT(ToRegister(instr->result()).is(eax)); | 2148 ASSERT(ToRegister(instr->result()).is(eax)); |
| 2054 | 2149 |
| 2055 BinaryOpStub stub(instr->op(), NO_OVERWRITE); | 2150 BinaryOpStub stub(instr->op(), NO_OVERWRITE); |
| 2056 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | 2151 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); |
| 2057 __ nop(); // Signals no inlined code. | 2152 __ nop(); // Signals no inlined code. |
| 2058 } | 2153 } |
| (...skipping 897 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2956 HObjectAccess access = instr->hydrogen()->access(); | 3051 HObjectAccess access = instr->hydrogen()->access(); |
| 2957 int offset = access.offset(); | 3052 int offset = access.offset(); |
| 2958 Register object = ToRegister(instr->object()); | 3053 Register object = ToRegister(instr->object()); |
| 2959 if (FLAG_track_double_fields && | 3054 if (FLAG_track_double_fields && |
| 2960 instr->hydrogen()->representation().IsDouble()) { | 3055 instr->hydrogen()->representation().IsDouble()) { |
| 2961 if (CpuFeatures::IsSupported(SSE2)) { | 3056 if (CpuFeatures::IsSupported(SSE2)) { |
| 2962 CpuFeatureScope scope(masm(), SSE2); | 3057 CpuFeatureScope scope(masm(), SSE2); |
| 2963 XMMRegister result = ToDoubleRegister(instr->result()); | 3058 XMMRegister result = ToDoubleRegister(instr->result()); |
| 2964 __ movdbl(result, FieldOperand(object, offset)); | 3059 __ movdbl(result, FieldOperand(object, offset)); |
| 2965 } else { | 3060 } else { |
| 2966 PushX87DoubleOperand(FieldOperand(object, offset)); | 3061 X87Mov(ToX87Register(instr->result()), FieldOperand(object, offset)); |
| 2967 CurrentInstructionReturnsX87Result(); | |
| 2968 } | 3062 } |
| 2969 return; | 3063 return; |
| 2970 } | 3064 } |
| 2971 | 3065 |
| 2972 Register result = ToRegister(instr->result()); | 3066 Register result = ToRegister(instr->result()); |
| 2973 if (access.IsInobject()) { | 3067 if (access.IsInobject()) { |
| 2974 __ mov(result, FieldOperand(object, offset)); | 3068 __ mov(result, FieldOperand(object, offset)); |
| 2975 } else { | 3069 } else { |
| 2976 __ mov(result, FieldOperand(object, JSObject::kPropertiesOffset)); | 3070 __ mov(result, FieldOperand(object, JSObject::kPropertiesOffset)); |
| 2977 __ mov(result, FieldOperand(result, offset)); | 3071 __ mov(result, FieldOperand(result, offset)); |
| (...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3202 elements_kind, | 3296 elements_kind, |
| 3203 0, | 3297 0, |
| 3204 instr->additional_index())); | 3298 instr->additional_index())); |
| 3205 if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) { | 3299 if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) { |
| 3206 if (CpuFeatures::IsSupported(SSE2)) { | 3300 if (CpuFeatures::IsSupported(SSE2)) { |
| 3207 CpuFeatureScope scope(masm(), SSE2); | 3301 CpuFeatureScope scope(masm(), SSE2); |
| 3208 XMMRegister result(ToDoubleRegister(instr->result())); | 3302 XMMRegister result(ToDoubleRegister(instr->result())); |
| 3209 __ movss(result, operand); | 3303 __ movss(result, operand); |
| 3210 __ cvtss2sd(result, result); | 3304 __ cvtss2sd(result, result); |
| 3211 } else { | 3305 } else { |
| 3212 PushX87FloatOperand(operand); | 3306 X87Mov(ToX87Register(instr->result()), operand, kX87FloatOperand); |
| 3213 CurrentInstructionReturnsX87Result(); | |
| 3214 } | 3307 } |
| 3215 } else if (elements_kind == EXTERNAL_DOUBLE_ELEMENTS) { | 3308 } else if (elements_kind == EXTERNAL_DOUBLE_ELEMENTS) { |
| 3216 if (CpuFeatures::IsSupported(SSE2)) { | 3309 if (CpuFeatures::IsSupported(SSE2)) { |
| 3217 CpuFeatureScope scope(masm(), SSE2); | 3310 CpuFeatureScope scope(masm(), SSE2); |
| 3218 __ movdbl(ToDoubleRegister(instr->result()), operand); | 3311 __ movdbl(ToDoubleRegister(instr->result()), operand); |
| 3219 } else { | 3312 } else { |
| 3220 PushX87DoubleOperand(operand); | 3313 X87Mov(ToX87Register(instr->result()), operand); |
| 3221 CurrentInstructionReturnsX87Result(); | |
| 3222 } | 3314 } |
| 3223 } else { | 3315 } else { |
| 3224 Register result(ToRegister(instr->result())); | 3316 Register result(ToRegister(instr->result())); |
| 3225 switch (elements_kind) { | 3317 switch (elements_kind) { |
| 3226 case EXTERNAL_BYTE_ELEMENTS: | 3318 case EXTERNAL_BYTE_ELEMENTS: |
| 3227 __ movsx_b(result, operand); | 3319 __ movsx_b(result, operand); |
| 3228 break; | 3320 break; |
| 3229 case EXTERNAL_PIXEL_ELEMENTS: | 3321 case EXTERNAL_PIXEL_ELEMENTS: |
| 3230 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: | 3322 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: |
| 3231 __ movzx_b(result, operand); | 3323 __ movzx_b(result, operand); |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3282 instr->key(), | 3374 instr->key(), |
| 3283 instr->hydrogen()->key()->representation(), | 3375 instr->hydrogen()->key()->representation(), |
| 3284 FAST_DOUBLE_ELEMENTS, | 3376 FAST_DOUBLE_ELEMENTS, |
| 3285 FixedDoubleArray::kHeaderSize - kHeapObjectTag, | 3377 FixedDoubleArray::kHeaderSize - kHeapObjectTag, |
| 3286 instr->additional_index()); | 3378 instr->additional_index()); |
| 3287 if (CpuFeatures::IsSupported(SSE2)) { | 3379 if (CpuFeatures::IsSupported(SSE2)) { |
| 3288 CpuFeatureScope scope(masm(), SSE2); | 3380 CpuFeatureScope scope(masm(), SSE2); |
| 3289 XMMRegister result = ToDoubleRegister(instr->result()); | 3381 XMMRegister result = ToDoubleRegister(instr->result()); |
| 3290 __ movdbl(result, double_load_operand); | 3382 __ movdbl(result, double_load_operand); |
| 3291 } else { | 3383 } else { |
| 3292 PushX87DoubleOperand(double_load_operand); | 3384 X87Mov(ToX87Register(instr->result()), double_load_operand); |
| 3293 CurrentInstructionReturnsX87Result(); | |
| 3294 } | 3385 } |
| 3295 } | 3386 } |
| 3296 | 3387 |
| 3297 | 3388 |
| 3298 void LCodeGen::DoLoadKeyedFixedArray(LLoadKeyed* instr) { | 3389 void LCodeGen::DoLoadKeyedFixedArray(LLoadKeyed* instr) { |
| 3299 Register result = ToRegister(instr->result()); | 3390 Register result = ToRegister(instr->result()); |
| 3300 | 3391 |
| 3301 // Load the result. | 3392 // Load the result. |
| 3302 __ mov(result, | 3393 __ mov(result, |
| 3303 BuildFastArrayOperand(instr->elements(), | 3394 BuildFastArrayOperand(instr->elements(), |
| (...skipping 973 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4277 } | 4368 } |
| 4278 } else if (FLAG_track_double_fields && representation.IsDouble()) { | 4369 } else if (FLAG_track_double_fields && representation.IsDouble()) { |
| 4279 ASSERT(transition.is_null()); | 4370 ASSERT(transition.is_null()); |
| 4280 ASSERT(access.IsInobject()); | 4371 ASSERT(access.IsInobject()); |
| 4281 ASSERT(!instr->hydrogen()->NeedsWriteBarrier()); | 4372 ASSERT(!instr->hydrogen()->NeedsWriteBarrier()); |
| 4282 if (CpuFeatures::IsSupported(SSE2)) { | 4373 if (CpuFeatures::IsSupported(SSE2)) { |
| 4283 CpuFeatureScope scope(masm(), SSE2); | 4374 CpuFeatureScope scope(masm(), SSE2); |
| 4284 XMMRegister value = ToDoubleRegister(instr->value()); | 4375 XMMRegister value = ToDoubleRegister(instr->value()); |
| 4285 __ movdbl(FieldOperand(object, offset), value); | 4376 __ movdbl(FieldOperand(object, offset), value); |
| 4286 } else { | 4377 } else { |
| 4287 __ fstp_d(FieldOperand(object, offset)); | 4378 X87Register value = ToX87Register(instr->value()); |
| 4379 X87Mov(FieldOperand(object, offset), value); |
| 4288 } | 4380 } |
| 4289 return; | 4381 return; |
| 4290 } | 4382 } |
| 4291 | 4383 |
| 4292 if (!transition.is_null()) { | 4384 if (!transition.is_null()) { |
| 4293 if (!instr->hydrogen()->NeedsWriteBarrierForMap()) { | 4385 if (!instr->hydrogen()->NeedsWriteBarrierForMap()) { |
| 4294 __ mov(FieldOperand(object, HeapObject::kMapOffset), transition); | 4386 __ mov(FieldOperand(object, HeapObject::kMapOffset), transition); |
| 4295 } else { | 4387 } else { |
| 4296 Register temp = ToRegister(instr->temp()); | 4388 Register temp = ToRegister(instr->temp()); |
| 4297 Register temp_map = ToRegister(instr->temp_map()); | 4389 Register temp_map = ToRegister(instr->temp_map()); |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4403 __ movss(operand, xmm0); | 4495 __ movss(operand, xmm0); |
| 4404 } else { | 4496 } else { |
| 4405 __ fld(0); | 4497 __ fld(0); |
| 4406 __ fstp_s(operand); | 4498 __ fstp_s(operand); |
| 4407 } | 4499 } |
| 4408 } else if (elements_kind == EXTERNAL_DOUBLE_ELEMENTS) { | 4500 } else if (elements_kind == EXTERNAL_DOUBLE_ELEMENTS) { |
| 4409 if (CpuFeatures::IsSafeForSnapshot(SSE2)) { | 4501 if (CpuFeatures::IsSafeForSnapshot(SSE2)) { |
| 4410 CpuFeatureScope scope(masm(), SSE2); | 4502 CpuFeatureScope scope(masm(), SSE2); |
| 4411 __ movdbl(operand, ToDoubleRegister(instr->value())); | 4503 __ movdbl(operand, ToDoubleRegister(instr->value())); |
| 4412 } else { | 4504 } else { |
| 4413 __ fst_d(operand); | 4505 X87Mov(operand, ToX87Register(instr->value())); |
| 4414 } | 4506 } |
| 4415 } else { | 4507 } else { |
| 4416 Register value = ToRegister(instr->value()); | 4508 Register value = ToRegister(instr->value()); |
| 4417 switch (elements_kind) { | 4509 switch (elements_kind) { |
| 4418 case EXTERNAL_PIXEL_ELEMENTS: | 4510 case EXTERNAL_PIXEL_ELEMENTS: |
| 4419 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: | 4511 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: |
| 4420 case EXTERNAL_BYTE_ELEMENTS: | 4512 case EXTERNAL_BYTE_ELEMENTS: |
| 4421 __ mov_b(operand, value); | 4513 __ mov_b(operand, value); |
| 4422 break; | 4514 break; |
| 4423 case EXTERNAL_SHORT_ELEMENTS: | 4515 case EXTERNAL_SHORT_ELEMENTS: |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4485 Operand double_store_operand2 = BuildFastArrayOperand( | 4577 Operand double_store_operand2 = BuildFastArrayOperand( |
| 4486 instr->elements(), | 4578 instr->elements(), |
| 4487 instr->key(), | 4579 instr->key(), |
| 4488 instr->hydrogen()->key()->representation(), | 4580 instr->hydrogen()->key()->representation(), |
| 4489 FAST_DOUBLE_ELEMENTS, | 4581 FAST_DOUBLE_ELEMENTS, |
| 4490 FixedDoubleArray::kHeaderSize - kHeapObjectTag + kPointerSize, | 4582 FixedDoubleArray::kHeaderSize - kHeapObjectTag + kPointerSize, |
| 4491 instr->additional_index()); | 4583 instr->additional_index()); |
| 4492 __ mov(double_store_operand2, Immediate(upper)); | 4584 __ mov(double_store_operand2, Immediate(upper)); |
| 4493 } else { | 4585 } else { |
| 4494 Label no_special_nan_handling; | 4586 Label no_special_nan_handling; |
| 4495 ASSERT(x87_stack_depth_ > 0); | 4587 X87Register value = ToX87Register(instr->value()); |
| 4588 X87Fxch(value); |
| 4496 | 4589 |
| 4497 if (instr->NeedsCanonicalization()) { | 4590 if (instr->NeedsCanonicalization()) { |
| 4498 __ fld(0); | 4591 __ fld(0); |
| 4499 __ fld(0); | 4592 __ fld(0); |
| 4500 __ FCmp(); | 4593 __ FCmp(); |
| 4501 | 4594 |
| 4502 __ j(parity_odd, &no_special_nan_handling); | 4595 __ j(parity_odd, &no_special_nan_handling); |
| 4503 __ sub(esp, Immediate(kDoubleSize)); | 4596 __ sub(esp, Immediate(kDoubleSize)); |
| 4504 __ fst_d(MemOperand(esp, 0)); | 4597 __ fst_d(MemOperand(esp, 0)); |
| 4505 __ cmp(MemOperand(esp, sizeof(kHoleNanLower32)), | 4598 __ cmp(MemOperand(esp, sizeof(kHoleNanLower32)), |
| (...skipping 449 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4955 | 5048 |
| 4956 Register reg = ToRegister(instr->result()); | 5049 Register reg = ToRegister(instr->result()); |
| 4957 | 5050 |
| 4958 bool convert_hole = false; | 5051 bool convert_hole = false; |
| 4959 HValue* change_input = instr->hydrogen()->value(); | 5052 HValue* change_input = instr->hydrogen()->value(); |
| 4960 if (change_input->IsLoadKeyed()) { | 5053 if (change_input->IsLoadKeyed()) { |
| 4961 HLoadKeyed* load = HLoadKeyed::cast(change_input); | 5054 HLoadKeyed* load = HLoadKeyed::cast(change_input); |
| 4962 convert_hole = load->UsesMustHandleHole(); | 5055 convert_hole = load->UsesMustHandleHole(); |
| 4963 } | 5056 } |
| 4964 | 5057 |
| 5058 bool use_sse2 = CpuFeatures::IsSupported(SSE2); |
| 5059 if (!use_sse2) { |
| 5060 // Put the value to the top of stack |
| 5061 X87Register src = ToX87Register(instr->value()); |
| 5062 X87LoadForUsage(src); |
| 5063 } |
| 5064 |
| 4965 Label no_special_nan_handling; | 5065 Label no_special_nan_handling; |
| 4966 Label done; | 5066 Label done; |
| 4967 if (convert_hole) { | 5067 if (convert_hole) { |
| 4968 bool use_sse2 = CpuFeatures::IsSupported(SSE2); | |
| 4969 if (use_sse2) { | 5068 if (use_sse2) { |
| 4970 CpuFeatureScope scope(masm(), SSE2); | 5069 CpuFeatureScope scope(masm(), SSE2); |
| 4971 XMMRegister input_reg = ToDoubleRegister(instr->value()); | 5070 XMMRegister input_reg = ToDoubleRegister(instr->value()); |
| 4972 __ ucomisd(input_reg, input_reg); | 5071 __ ucomisd(input_reg, input_reg); |
| 4973 } else { | 5072 } else { |
| 4974 __ fld(0); | 5073 __ fld(0); |
| 4975 __ fld(0); | 5074 __ fld(0); |
| 4976 __ FCmp(); | 5075 __ FCmp(); |
| 4977 } | 5076 } |
| 4978 | 5077 |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5012 | 5111 |
| 5013 __ bind(&no_special_nan_handling); | 5112 __ bind(&no_special_nan_handling); |
| 5014 DeferredNumberTagD* deferred = new(zone()) DeferredNumberTagD(this, instr); | 5113 DeferredNumberTagD* deferred = new(zone()) DeferredNumberTagD(this, instr); |
| 5015 if (FLAG_inline_new) { | 5114 if (FLAG_inline_new) { |
| 5016 Register tmp = ToRegister(instr->temp()); | 5115 Register tmp = ToRegister(instr->temp()); |
| 5017 __ AllocateHeapNumber(reg, tmp, no_reg, deferred->entry()); | 5116 __ AllocateHeapNumber(reg, tmp, no_reg, deferred->entry()); |
| 5018 } else { | 5117 } else { |
| 5019 __ jmp(deferred->entry()); | 5118 __ jmp(deferred->entry()); |
| 5020 } | 5119 } |
| 5021 __ bind(deferred->exit()); | 5120 __ bind(deferred->exit()); |
| 5022 if (CpuFeatures::IsSupported(SSE2)) { | 5121 if (use_sse2) { |
| 5023 CpuFeatureScope scope(masm(), SSE2); | 5122 CpuFeatureScope scope(masm(), SSE2); |
| 5024 XMMRegister input_reg = ToDoubleRegister(instr->value()); | 5123 XMMRegister input_reg = ToDoubleRegister(instr->value()); |
| 5025 __ movdbl(FieldOperand(reg, HeapNumber::kValueOffset), input_reg); | 5124 __ movdbl(FieldOperand(reg, HeapNumber::kValueOffset), input_reg); |
| 5026 } else { | 5125 } else { |
| 5027 __ fst_d(FieldOperand(reg, HeapNumber::kValueOffset)); | 5126 __ fstp_d(FieldOperand(reg, HeapNumber::kValueOffset)); |
| 5028 } | 5127 } |
| 5029 __ bind(&done); | 5128 __ bind(&done); |
| 5030 } | 5129 } |
| 5031 | 5130 |
| 5032 | 5131 |
| 5033 void LCodeGen::DoDeferredNumberTagD(LNumberTagD* instr) { | 5132 void LCodeGen::DoDeferredNumberTagD(LNumberTagD* instr) { |
| 5034 // TODO(3095996): Get rid of this. For now, we need to make the | 5133 // TODO(3095996): Get rid of this. For now, we need to make the |
| 5035 // result register contain a valid pointer because it is already | 5134 // result register contain a valid pointer because it is already |
| 5036 // contained in the register pointer map. | 5135 // contained in the register pointer map. |
| 5037 Register reg = ToRegister(instr->result()); | 5136 Register reg = ToRegister(instr->result()); |
| (...skipping 30 matching lines...) Expand all Loading... |
| 5068 DeoptimizeIf(not_zero, instr->environment()); | 5167 DeoptimizeIf(not_zero, instr->environment()); |
| 5069 } else { | 5168 } else { |
| 5070 __ AssertSmi(result); | 5169 __ AssertSmi(result); |
| 5071 } | 5170 } |
| 5072 __ SmiUntag(result); | 5171 __ SmiUntag(result); |
| 5073 } | 5172 } |
| 5074 | 5173 |
| 5075 | 5174 |
| 5076 void LCodeGen::EmitNumberUntagDNoSSE2(Register input_reg, | 5175 void LCodeGen::EmitNumberUntagDNoSSE2(Register input_reg, |
| 5077 Register temp_reg, | 5176 Register temp_reg, |
| 5177 X87Register res_reg, |
| 5078 bool allow_undefined_as_nan, | 5178 bool allow_undefined_as_nan, |
| 5079 bool deoptimize_on_minus_zero, | 5179 bool deoptimize_on_minus_zero, |
| 5080 LEnvironment* env, | 5180 LEnvironment* env, |
| 5081 NumberUntagDMode mode) { | 5181 NumberUntagDMode mode) { |
| 5082 Label load_smi, done; | 5182 Label load_smi, done; |
| 5083 | 5183 |
| 5184 X87PrepareToWrite(res_reg); |
| 5084 STATIC_ASSERT(NUMBER_CANDIDATE_IS_ANY_TAGGED_CONVERT_HOLE > | 5185 STATIC_ASSERT(NUMBER_CANDIDATE_IS_ANY_TAGGED_CONVERT_HOLE > |
| 5085 NUMBER_CANDIDATE_IS_ANY_TAGGED); | 5186 NUMBER_CANDIDATE_IS_ANY_TAGGED); |
| 5086 if (mode >= NUMBER_CANDIDATE_IS_ANY_TAGGED) { | 5187 if (mode >= NUMBER_CANDIDATE_IS_ANY_TAGGED) { |
| 5087 // Smi check. | 5188 // Smi check. |
| 5088 __ JumpIfSmi(input_reg, &load_smi, Label::kNear); | 5189 __ JumpIfSmi(input_reg, &load_smi, Label::kNear); |
| 5089 | 5190 |
| 5090 // Heap number map check. | 5191 // Heap number map check. |
| 5091 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), | 5192 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), |
| 5092 factory()->heap_number_map()); | 5193 factory()->heap_number_map()); |
| 5093 if (!allow_undefined_as_nan) { | 5194 if (!allow_undefined_as_nan) { |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5134 ASSERT(mode == NUMBER_CANDIDATE_IS_SMI); | 5235 ASSERT(mode == NUMBER_CANDIDATE_IS_SMI); |
| 5135 } | 5236 } |
| 5136 | 5237 |
| 5137 __ bind(&load_smi); | 5238 __ bind(&load_smi); |
| 5138 __ SmiUntag(input_reg); // Untag smi before converting to float. | 5239 __ SmiUntag(input_reg); // Untag smi before converting to float. |
| 5139 __ push(input_reg); | 5240 __ push(input_reg); |
| 5140 __ fild_s(Operand(esp, 0)); | 5241 __ fild_s(Operand(esp, 0)); |
| 5141 __ pop(input_reg); | 5242 __ pop(input_reg); |
| 5142 __ SmiTag(input_reg); // Retag smi. | 5243 __ SmiTag(input_reg); // Retag smi. |
| 5143 __ bind(&done); | 5244 __ bind(&done); |
| 5245 X87CommitWrite(res_reg); |
| 5144 } | 5246 } |
| 5145 | 5247 |
| 5146 | 5248 |
| 5147 void LCodeGen::EmitNumberUntagD(Register input_reg, | 5249 void LCodeGen::EmitNumberUntagD(Register input_reg, |
| 5148 Register temp_reg, | 5250 Register temp_reg, |
| 5149 XMMRegister result_reg, | 5251 XMMRegister result_reg, |
| 5150 bool allow_undefined_as_nan, | 5252 bool allow_undefined_as_nan, |
| 5151 bool deoptimize_on_minus_zero, | 5253 bool deoptimize_on_minus_zero, |
| 5152 LEnvironment* env, | 5254 LEnvironment* env, |
| 5153 NumberUntagDMode mode) { | 5255 NumberUntagDMode mode) { |
| (...skipping 361 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5515 EmitNumberUntagD(input_reg, | 5617 EmitNumberUntagD(input_reg, |
| 5516 temp_reg, | 5618 temp_reg, |
| 5517 result_reg, | 5619 result_reg, |
| 5518 instr->hydrogen()->allow_undefined_as_nan(), | 5620 instr->hydrogen()->allow_undefined_as_nan(), |
| 5519 deoptimize_on_minus_zero, | 5621 deoptimize_on_minus_zero, |
| 5520 instr->environment(), | 5622 instr->environment(), |
| 5521 mode); | 5623 mode); |
| 5522 } else { | 5624 } else { |
| 5523 EmitNumberUntagDNoSSE2(input_reg, | 5625 EmitNumberUntagDNoSSE2(input_reg, |
| 5524 temp_reg, | 5626 temp_reg, |
| 5627 ToX87Register(instr->result()), |
| 5525 instr->hydrogen()->allow_undefined_as_nan(), | 5628 instr->hydrogen()->allow_undefined_as_nan(), |
| 5526 deoptimize_on_minus_zero, | 5629 deoptimize_on_minus_zero, |
| 5527 instr->environment(), | 5630 instr->environment(), |
| 5528 mode); | 5631 mode); |
| 5529 CurrentInstructionReturnsX87Result(); | |
| 5530 } | 5632 } |
| 5531 } | 5633 } |
| 5532 | 5634 |
| 5533 | 5635 |
| 5534 void LCodeGen::DoDoubleToI(LDoubleToI* instr) { | 5636 void LCodeGen::DoDoubleToI(LDoubleToI* instr) { |
| 5535 LOperand* input = instr->value(); | 5637 LOperand* input = instr->value(); |
| 5536 ASSERT(input->IsDoubleRegister()); | 5638 ASSERT(input->IsDoubleRegister()); |
| 5537 LOperand* result = instr->result(); | 5639 LOperand* result = instr->result(); |
| 5538 ASSERT(result->IsRegister()); | 5640 ASSERT(result->IsRegister()); |
| 5539 CpuFeatureScope scope(masm(), SSE2); | 5641 CpuFeatureScope scope(masm(), SSE2); |
| 5540 | 5642 |
| 5541 XMMRegister input_reg = ToDoubleRegister(input); | 5643 XMMRegister input_reg = ToDoubleRegister(input); |
| 5542 Register result_reg = ToRegister(result); | 5644 Register result_reg = ToRegister(result); |
| 5543 | 5645 |
| 5646 __ cvttsd2si(result_reg, Operand(input_reg)); |
| 5647 |
| 5544 if (instr->truncating()) { | 5648 if (instr->truncating()) { |
| 5545 // Performs a truncating conversion of a floating point number as used by | 5649 // Performs a truncating conversion of a floating point number as used by |
| 5546 // the JS bitwise operations. | 5650 // the JS bitwise operations. |
| 5547 __ cvttsd2si(result_reg, Operand(input_reg)); | 5651 Label fast_case_succeeded; |
| 5548 __ cmp(result_reg, 0x80000000u); | 5652 __ cmp(result_reg, 0x80000000u); |
| 5549 if (CpuFeatures::IsSupported(SSE3)) { | 5653 __ j(not_equal, &fast_case_succeeded); |
| 5550 // This will deoptimize if the exponent of the input in out of range. | 5654 __ sub(esp, Immediate(kDoubleSize)); |
| 5551 CpuFeatureScope scope(masm(), SSE3); | 5655 __ movdbl(MemOperand(esp, 0), input_reg); |
| 5552 Label convert, done; | 5656 DoubleToIStub stub(esp, result_reg, 0, true); |
| 5553 __ j(not_equal, &done, Label::kNear); | 5657 __ call(stub.GetCode(isolate()), RelocInfo::CODE_TARGET); |
| 5554 __ sub(Operand(esp), Immediate(kDoubleSize)); | 5658 __ add(esp, Immediate(kDoubleSize)); |
| 5555 __ movdbl(Operand(esp, 0), input_reg); | 5659 __ bind(&fast_case_succeeded); |
| 5556 // Get exponent alone and check for too-big exponent. | |
| 5557 __ mov(result_reg, Operand(esp, sizeof(int32_t))); | |
| 5558 __ and_(result_reg, HeapNumber::kExponentMask); | |
| 5559 const uint32_t kTooBigExponent = | |
| 5560 (HeapNumber::kExponentBias + 63) << HeapNumber::kExponentShift; | |
| 5561 __ cmp(Operand(result_reg), Immediate(kTooBigExponent)); | |
| 5562 __ j(less, &convert, Label::kNear); | |
| 5563 __ add(Operand(esp), Immediate(kDoubleSize)); | |
| 5564 DeoptimizeIf(no_condition, instr->environment()); | |
| 5565 __ bind(&convert); | |
| 5566 // Do conversion, which cannot fail because we checked the exponent. | |
| 5567 __ fld_d(Operand(esp, 0)); | |
| 5568 __ fisttp_d(Operand(esp, 0)); | |
| 5569 __ mov(result_reg, Operand(esp, 0)); // Low word of answer is the result. | |
| 5570 __ add(Operand(esp), Immediate(kDoubleSize)); | |
| 5571 __ bind(&done); | |
| 5572 } else { | |
| 5573 Label done; | |
| 5574 Register temp_reg = ToRegister(instr->temp()); | |
| 5575 XMMRegister xmm_scratch = xmm0; | |
| 5576 | |
| 5577 // If cvttsd2si succeeded, we're done. Otherwise, we attempt | |
| 5578 // manual conversion. | |
| 5579 __ j(not_equal, &done, Label::kNear); | |
| 5580 | |
| 5581 // Get high 32 bits of the input in result_reg and temp_reg. | |
| 5582 __ pshufd(xmm_scratch, input_reg, 1); | |
| 5583 __ movd(Operand(temp_reg), xmm_scratch); | |
| 5584 __ mov(result_reg, temp_reg); | |
| 5585 | |
| 5586 // Prepare negation mask in temp_reg. | |
| 5587 __ sar(temp_reg, kBitsPerInt - 1); | |
| 5588 | |
| 5589 // Extract the exponent from result_reg and subtract adjusted | |
| 5590 // bias from it. The adjustment is selected in a way such that | |
| 5591 // when the difference is zero, the answer is in the low 32 bits | |
| 5592 // of the input, otherwise a shift has to be performed. | |
| 5593 __ shr(result_reg, HeapNumber::kExponentShift); | |
| 5594 __ and_(result_reg, | |
| 5595 HeapNumber::kExponentMask >> HeapNumber::kExponentShift); | |
| 5596 __ sub(Operand(result_reg), | |
| 5597 Immediate(HeapNumber::kExponentBias + | |
| 5598 HeapNumber::kExponentBits + | |
| 5599 HeapNumber::kMantissaBits)); | |
| 5600 // Don't handle big (> kMantissaBits + kExponentBits == 63) or | |
| 5601 // special exponents. | |
| 5602 DeoptimizeIf(greater, instr->environment()); | |
| 5603 | |
| 5604 // Zero out the sign and the exponent in the input (by shifting | |
| 5605 // it to the left) and restore the implicit mantissa bit, | |
| 5606 // i.e. convert the input to unsigned int64 shifted left by | |
| 5607 // kExponentBits. | |
| 5608 ExternalReference minus_zero = ExternalReference::address_of_minus_zero(); | |
| 5609 // Minus zero has the most significant bit set and the other | |
| 5610 // bits cleared. | |
| 5611 __ movdbl(xmm_scratch, Operand::StaticVariable(minus_zero)); | |
| 5612 __ psllq(input_reg, HeapNumber::kExponentBits); | |
| 5613 __ por(input_reg, xmm_scratch); | |
| 5614 | |
| 5615 // Get the amount to shift the input right in xmm_scratch. | |
| 5616 __ neg(result_reg); | |
| 5617 __ movd(xmm_scratch, Operand(result_reg)); | |
| 5618 | |
| 5619 // Shift the input right and extract low 32 bits. | |
| 5620 __ psrlq(input_reg, xmm_scratch); | |
| 5621 __ movd(Operand(result_reg), input_reg); | |
| 5622 | |
| 5623 // Use the prepared mask in temp_reg to negate the result if necessary. | |
| 5624 __ xor_(result_reg, Operand(temp_reg)); | |
| 5625 __ sub(result_reg, Operand(temp_reg)); | |
| 5626 __ bind(&done); | |
| 5627 } | |
| 5628 } else { | 5660 } else { |
| 5629 Label done; | 5661 Label done; |
| 5630 __ cvttsd2si(result_reg, Operand(input_reg)); | |
| 5631 __ cvtsi2sd(xmm0, Operand(result_reg)); | 5662 __ cvtsi2sd(xmm0, Operand(result_reg)); |
| 5632 __ ucomisd(xmm0, input_reg); | 5663 __ ucomisd(xmm0, input_reg); |
| 5633 DeoptimizeIf(not_equal, instr->environment()); | 5664 DeoptimizeIf(not_equal, instr->environment()); |
| 5634 DeoptimizeIf(parity_even, instr->environment()); // NaN. | 5665 DeoptimizeIf(parity_even, instr->environment()); // NaN. |
| 5635 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 5666 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 5636 // The integer converted back is equal to the original. We | 5667 // The integer converted back is equal to the original. We |
| 5637 // only have to test if we got -0 as an input. | 5668 // only have to test if we got -0 as an input. |
| 5638 __ test(result_reg, Operand(result_reg)); | 5669 __ test(result_reg, Operand(result_reg)); |
| 5639 __ j(not_zero, &done, Label::kNear); | 5670 __ j(not_zero, &done, Label::kNear); |
| 5640 __ movmskpd(result_reg, input_reg); | 5671 __ movmskpd(result_reg, input_reg); |
| (...skipping 328 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5969 | 6000 |
| 5970 if (!instr->hydrogen()->CanOmitPrototypeChecks()) { | 6001 if (!instr->hydrogen()->CanOmitPrototypeChecks()) { |
| 5971 for (int i = 0; i < prototypes->length(); i++) { | 6002 for (int i = 0; i < prototypes->length(); i++) { |
| 5972 __ LoadHeapObject(reg, prototypes->at(i)); | 6003 __ LoadHeapObject(reg, prototypes->at(i)); |
| 5973 DoCheckMapCommon(reg, maps->at(i), instr); | 6004 DoCheckMapCommon(reg, maps->at(i), instr); |
| 5974 } | 6005 } |
| 5975 } | 6006 } |
| 5976 } | 6007 } |
| 5977 | 6008 |
| 5978 | 6009 |
| 5979 void LCodeGen::DoAllocateObject(LAllocateObject* instr) { | |
| 5980 class DeferredAllocateObject: public LDeferredCode { | |
| 5981 public: | |
| 5982 DeferredAllocateObject(LCodeGen* codegen, LAllocateObject* instr) | |
| 5983 : LDeferredCode(codegen), instr_(instr) { } | |
| 5984 virtual void Generate() { codegen()->DoDeferredAllocateObject(instr_); } | |
| 5985 virtual LInstruction* instr() { return instr_; } | |
| 5986 private: | |
| 5987 LAllocateObject* instr_; | |
| 5988 }; | |
| 5989 | |
| 5990 DeferredAllocateObject* deferred = | |
| 5991 new(zone()) DeferredAllocateObject(this, instr); | |
| 5992 | |
| 5993 Register result = ToRegister(instr->result()); | |
| 5994 Register scratch = ToRegister(instr->temp()); | |
| 5995 Handle<JSFunction> constructor = instr->hydrogen()->constructor(); | |
| 5996 Handle<Map> initial_map = instr->hydrogen()->constructor_initial_map(); | |
| 5997 int instance_size = initial_map->instance_size(); | |
| 5998 ASSERT(initial_map->pre_allocated_property_fields() + | |
| 5999 initial_map->unused_property_fields() - | |
| 6000 initial_map->inobject_properties() == 0); | |
| 6001 | |
| 6002 __ Allocate(instance_size, result, no_reg, scratch, deferred->entry(), | |
| 6003 TAG_OBJECT); | |
| 6004 | |
| 6005 __ bind(deferred->exit()); | |
| 6006 if (FLAG_debug_code) { | |
| 6007 Label is_in_new_space; | |
| 6008 __ JumpIfInNewSpace(result, scratch, &is_in_new_space); | |
| 6009 __ Abort("Allocated object is not in new-space"); | |
| 6010 __ bind(&is_in_new_space); | |
| 6011 } | |
| 6012 | |
| 6013 // Load the initial map. | |
| 6014 Register map = scratch; | |
| 6015 __ LoadHeapObject(scratch, constructor); | |
| 6016 __ mov(map, FieldOperand(scratch, JSFunction::kPrototypeOrInitialMapOffset)); | |
| 6017 | |
| 6018 if (FLAG_debug_code) { | |
| 6019 __ AssertNotSmi(map); | |
| 6020 __ cmpb(FieldOperand(map, Map::kInstanceSizeOffset), | |
| 6021 instance_size >> kPointerSizeLog2); | |
| 6022 __ Assert(equal, "Unexpected instance size"); | |
| 6023 __ cmpb(FieldOperand(map, Map::kPreAllocatedPropertyFieldsOffset), | |
| 6024 initial_map->pre_allocated_property_fields()); | |
| 6025 __ Assert(equal, "Unexpected pre-allocated property fields count"); | |
| 6026 __ cmpb(FieldOperand(map, Map::kUnusedPropertyFieldsOffset), | |
| 6027 initial_map->unused_property_fields()); | |
| 6028 __ Assert(equal, "Unexpected unused property fields count"); | |
| 6029 __ cmpb(FieldOperand(map, Map::kInObjectPropertiesOffset), | |
| 6030 initial_map->inobject_properties()); | |
| 6031 __ Assert(equal, "Unexpected in-object property fields count"); | |
| 6032 } | |
| 6033 | |
| 6034 // Initialize map and fields of the newly allocated object. | |
| 6035 ASSERT(initial_map->instance_type() == JS_OBJECT_TYPE); | |
| 6036 __ mov(FieldOperand(result, JSObject::kMapOffset), map); | |
| 6037 __ mov(scratch, factory()->empty_fixed_array()); | |
| 6038 __ mov(FieldOperand(result, JSObject::kElementsOffset), scratch); | |
| 6039 __ mov(FieldOperand(result, JSObject::kPropertiesOffset), scratch); | |
| 6040 if (initial_map->inobject_properties() != 0) { | |
| 6041 __ mov(scratch, factory()->undefined_value()); | |
| 6042 for (int i = 0; i < initial_map->inobject_properties(); i++) { | |
| 6043 int property_offset = JSObject::kHeaderSize + i * kPointerSize; | |
| 6044 __ mov(FieldOperand(result, property_offset), scratch); | |
| 6045 } | |
| 6046 } | |
| 6047 } | |
| 6048 | |
| 6049 | |
| 6050 void LCodeGen::DoDeferredAllocateObject(LAllocateObject* instr) { | |
| 6051 Register result = ToRegister(instr->result()); | |
| 6052 Handle<Map> initial_map = instr->hydrogen()->constructor_initial_map(); | |
| 6053 int instance_size = initial_map->instance_size(); | |
| 6054 | |
| 6055 // TODO(3095996): Get rid of this. For now, we need to make the | |
| 6056 // result register contain a valid pointer because it is already | |
| 6057 // contained in the register pointer map. | |
| 6058 __ Set(result, Immediate(0)); | |
| 6059 | |
| 6060 PushSafepointRegistersScope scope(this); | |
| 6061 __ push(Immediate(Smi::FromInt(instance_size))); | |
| 6062 CallRuntimeFromDeferred( | |
| 6063 Runtime::kAllocateInNewSpace, 1, instr, instr->context()); | |
| 6064 __ StoreToSafepointRegisterSlot(result, eax); | |
| 6065 } | |
| 6066 | |
| 6067 | |
| 6068 void LCodeGen::DoAllocate(LAllocate* instr) { | 6010 void LCodeGen::DoAllocate(LAllocate* instr) { |
| 6069 class DeferredAllocate: public LDeferredCode { | 6011 class DeferredAllocate: public LDeferredCode { |
| 6070 public: | 6012 public: |
| 6071 DeferredAllocate(LCodeGen* codegen, LAllocate* instr) | 6013 DeferredAllocate(LCodeGen* codegen, LAllocate* instr) |
| 6072 : LDeferredCode(codegen), instr_(instr) { } | 6014 : LDeferredCode(codegen), instr_(instr) { } |
| 6073 virtual void Generate() { codegen()->DoDeferredAllocate(instr_); } | 6015 virtual void Generate() { codegen()->DoDeferredAllocate(instr_); } |
| 6074 virtual LInstruction* instr() { return instr_; } | 6016 virtual LInstruction* instr() { return instr_; } |
| 6075 private: | 6017 private: |
| 6076 LAllocate* instr_; | 6018 LAllocate* instr_; |
| 6077 }; | 6019 }; |
| (...skipping 463 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6541 FixedArray::kHeaderSize - kPointerSize)); | 6483 FixedArray::kHeaderSize - kPointerSize)); |
| 6542 __ bind(&done); | 6484 __ bind(&done); |
| 6543 } | 6485 } |
| 6544 | 6486 |
| 6545 | 6487 |
| 6546 #undef __ | 6488 #undef __ |
| 6547 | 6489 |
| 6548 } } // namespace v8::internal | 6490 } } // namespace v8::internal |
| 6549 | 6491 |
| 6550 #endif // V8_TARGET_ARCH_IA32 | 6492 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |