OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #include "src/arm64/lithium-codegen-arm64.h" | 7 #include "src/arm64/lithium-codegen-arm64.h" |
8 #include "src/arm64/lithium-gap-resolver-arm64.h" | 8 #include "src/arm64/lithium-gap-resolver-arm64.h" |
9 #include "src/code-stubs.h" | 9 #include "src/code-stubs.h" |
10 #include "src/hydrogen-osr.h" | 10 #include "src/hydrogen-osr.h" |
(...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
231 : Translation::kSelfLiteralId; | 231 : Translation::kSelfLiteralId; |
232 | 232 |
233 switch (environment->frame_type()) { | 233 switch (environment->frame_type()) { |
234 case JS_FUNCTION: | 234 case JS_FUNCTION: |
235 translation->BeginJSFrame(environment->ast_id(), closure_id, height); | 235 translation->BeginJSFrame(environment->ast_id(), closure_id, height); |
236 break; | 236 break; |
237 case JS_CONSTRUCT: | 237 case JS_CONSTRUCT: |
238 translation->BeginConstructStubFrame(closure_id, translation_size); | 238 translation->BeginConstructStubFrame(closure_id, translation_size); |
239 break; | 239 break; |
240 case JS_GETTER: | 240 case JS_GETTER: |
241 ASSERT(translation_size == 1); | 241 DCHECK(translation_size == 1); |
242 ASSERT(height == 0); | 242 DCHECK(height == 0); |
243 translation->BeginGetterStubFrame(closure_id); | 243 translation->BeginGetterStubFrame(closure_id); |
244 break; | 244 break; |
245 case JS_SETTER: | 245 case JS_SETTER: |
246 ASSERT(translation_size == 2); | 246 DCHECK(translation_size == 2); |
247 ASSERT(height == 0); | 247 DCHECK(height == 0); |
248 translation->BeginSetterStubFrame(closure_id); | 248 translation->BeginSetterStubFrame(closure_id); |
249 break; | 249 break; |
250 case STUB: | 250 case STUB: |
251 translation->BeginCompiledStubFrame(); | 251 translation->BeginCompiledStubFrame(); |
252 break; | 252 break; |
253 case ARGUMENTS_ADAPTOR: | 253 case ARGUMENTS_ADAPTOR: |
254 translation->BeginArgumentsAdaptorFrame(closure_id, translation_size); | 254 translation->BeginArgumentsAdaptorFrame(closure_id, translation_size); |
255 break; | 255 break; |
256 default: | 256 default: |
257 UNREACHABLE(); | 257 UNREACHABLE(); |
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
379 RelocInfo::Mode mode, | 379 RelocInfo::Mode mode, |
380 LInstruction* instr) { | 380 LInstruction* instr) { |
381 CallCodeGeneric(code, mode, instr, RECORD_SIMPLE_SAFEPOINT); | 381 CallCodeGeneric(code, mode, instr, RECORD_SIMPLE_SAFEPOINT); |
382 } | 382 } |
383 | 383 |
384 | 384 |
385 void LCodeGen::CallCodeGeneric(Handle<Code> code, | 385 void LCodeGen::CallCodeGeneric(Handle<Code> code, |
386 RelocInfo::Mode mode, | 386 RelocInfo::Mode mode, |
387 LInstruction* instr, | 387 LInstruction* instr, |
388 SafepointMode safepoint_mode) { | 388 SafepointMode safepoint_mode) { |
389 ASSERT(instr != NULL); | 389 DCHECK(instr != NULL); |
390 | 390 |
391 Assembler::BlockPoolsScope scope(masm_); | 391 Assembler::BlockPoolsScope scope(masm_); |
392 __ Call(code, mode); | 392 __ Call(code, mode); |
393 RecordSafepointWithLazyDeopt(instr, safepoint_mode); | 393 RecordSafepointWithLazyDeopt(instr, safepoint_mode); |
394 | 394 |
395 if ((code->kind() == Code::BINARY_OP_IC) || | 395 if ((code->kind() == Code::BINARY_OP_IC) || |
396 (code->kind() == Code::COMPARE_IC)) { | 396 (code->kind() == Code::COMPARE_IC)) { |
397 // Signal that we don't inline smi code before these stubs in the | 397 // Signal that we don't inline smi code before these stubs in the |
398 // optimizing code generator. | 398 // optimizing code generator. |
399 InlineSmiCheckInfo::EmitNotInlined(masm()); | 399 InlineSmiCheckInfo::EmitNotInlined(masm()); |
400 } | 400 } |
401 } | 401 } |
402 | 402 |
403 | 403 |
404 void LCodeGen::DoCallFunction(LCallFunction* instr) { | 404 void LCodeGen::DoCallFunction(LCallFunction* instr) { |
405 ASSERT(ToRegister(instr->context()).is(cp)); | 405 DCHECK(ToRegister(instr->context()).is(cp)); |
406 ASSERT(ToRegister(instr->function()).Is(x1)); | 406 DCHECK(ToRegister(instr->function()).Is(x1)); |
407 ASSERT(ToRegister(instr->result()).Is(x0)); | 407 DCHECK(ToRegister(instr->result()).Is(x0)); |
408 | 408 |
409 int arity = instr->arity(); | 409 int arity = instr->arity(); |
410 CallFunctionStub stub(isolate(), arity, instr->hydrogen()->function_flags()); | 410 CallFunctionStub stub(isolate(), arity, instr->hydrogen()->function_flags()); |
411 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); | 411 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
412 after_push_argument_ = false; | 412 after_push_argument_ = false; |
413 } | 413 } |
414 | 414 |
415 | 415 |
416 void LCodeGen::DoCallNew(LCallNew* instr) { | 416 void LCodeGen::DoCallNew(LCallNew* instr) { |
417 ASSERT(ToRegister(instr->context()).is(cp)); | 417 DCHECK(ToRegister(instr->context()).is(cp)); |
418 ASSERT(instr->IsMarkedAsCall()); | 418 DCHECK(instr->IsMarkedAsCall()); |
419 ASSERT(ToRegister(instr->constructor()).is(x1)); | 419 DCHECK(ToRegister(instr->constructor()).is(x1)); |
420 | 420 |
421 __ Mov(x0, instr->arity()); | 421 __ Mov(x0, instr->arity()); |
422 // No cell in x2 for construct type feedback in optimized code. | 422 // No cell in x2 for construct type feedback in optimized code. |
423 __ LoadRoot(x2, Heap::kUndefinedValueRootIndex); | 423 __ LoadRoot(x2, Heap::kUndefinedValueRootIndex); |
424 | 424 |
425 CallConstructStub stub(isolate(), NO_CALL_CONSTRUCTOR_FLAGS); | 425 CallConstructStub stub(isolate(), NO_CALL_CONSTRUCTOR_FLAGS); |
426 CallCode(stub.GetCode(), RelocInfo::CONSTRUCT_CALL, instr); | 426 CallCode(stub.GetCode(), RelocInfo::CONSTRUCT_CALL, instr); |
427 after_push_argument_ = false; | 427 after_push_argument_ = false; |
428 | 428 |
429 ASSERT(ToRegister(instr->result()).is(x0)); | 429 DCHECK(ToRegister(instr->result()).is(x0)); |
430 } | 430 } |
431 | 431 |
432 | 432 |
433 void LCodeGen::DoCallNewArray(LCallNewArray* instr) { | 433 void LCodeGen::DoCallNewArray(LCallNewArray* instr) { |
434 ASSERT(instr->IsMarkedAsCall()); | 434 DCHECK(instr->IsMarkedAsCall()); |
435 ASSERT(ToRegister(instr->context()).is(cp)); | 435 DCHECK(ToRegister(instr->context()).is(cp)); |
436 ASSERT(ToRegister(instr->constructor()).is(x1)); | 436 DCHECK(ToRegister(instr->constructor()).is(x1)); |
437 | 437 |
438 __ Mov(x0, Operand(instr->arity())); | 438 __ Mov(x0, Operand(instr->arity())); |
439 __ LoadRoot(x2, Heap::kUndefinedValueRootIndex); | 439 __ LoadRoot(x2, Heap::kUndefinedValueRootIndex); |
440 | 440 |
441 ElementsKind kind = instr->hydrogen()->elements_kind(); | 441 ElementsKind kind = instr->hydrogen()->elements_kind(); |
442 AllocationSiteOverrideMode override_mode = | 442 AllocationSiteOverrideMode override_mode = |
443 (AllocationSite::GetMode(kind) == TRACK_ALLOCATION_SITE) | 443 (AllocationSite::GetMode(kind) == TRACK_ALLOCATION_SITE) |
444 ? DISABLE_ALLOCATION_SITES | 444 ? DISABLE_ALLOCATION_SITES |
445 : DONT_OVERRIDE; | 445 : DONT_OVERRIDE; |
446 | 446 |
(...skipping 20 matching lines...) Expand all Loading... |
467 | 467 |
468 ArraySingleArgumentConstructorStub stub(isolate(), kind, override_mode); | 468 ArraySingleArgumentConstructorStub stub(isolate(), kind, override_mode); |
469 CallCode(stub.GetCode(), RelocInfo::CONSTRUCT_CALL, instr); | 469 CallCode(stub.GetCode(), RelocInfo::CONSTRUCT_CALL, instr); |
470 __ Bind(&done); | 470 __ Bind(&done); |
471 } else { | 471 } else { |
472 ArrayNArgumentsConstructorStub stub(isolate(), kind, override_mode); | 472 ArrayNArgumentsConstructorStub stub(isolate(), kind, override_mode); |
473 CallCode(stub.GetCode(), RelocInfo::CONSTRUCT_CALL, instr); | 473 CallCode(stub.GetCode(), RelocInfo::CONSTRUCT_CALL, instr); |
474 } | 474 } |
475 after_push_argument_ = false; | 475 after_push_argument_ = false; |
476 | 476 |
477 ASSERT(ToRegister(instr->result()).is(x0)); | 477 DCHECK(ToRegister(instr->result()).is(x0)); |
478 } | 478 } |
479 | 479 |
480 | 480 |
481 void LCodeGen::CallRuntime(const Runtime::Function* function, | 481 void LCodeGen::CallRuntime(const Runtime::Function* function, |
482 int num_arguments, | 482 int num_arguments, |
483 LInstruction* instr, | 483 LInstruction* instr, |
484 SaveFPRegsMode save_doubles) { | 484 SaveFPRegsMode save_doubles) { |
485 ASSERT(instr != NULL); | 485 DCHECK(instr != NULL); |
486 | 486 |
487 __ CallRuntime(function, num_arguments, save_doubles); | 487 __ CallRuntime(function, num_arguments, save_doubles); |
488 | 488 |
489 RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT); | 489 RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT); |
490 } | 490 } |
491 | 491 |
492 | 492 |
493 void LCodeGen::LoadContextFromDeferred(LOperand* context) { | 493 void LCodeGen::LoadContextFromDeferred(LOperand* context) { |
494 if (context->IsRegister()) { | 494 if (context->IsRegister()) { |
495 __ Mov(cp, ToRegister(context)); | 495 __ Mov(cp, ToRegister(context)); |
(...skipping 26 matching lines...) Expand all Loading... |
522 masm()->positions_recorder()->RecordPosition(position); | 522 masm()->positions_recorder()->RecordPosition(position); |
523 masm()->positions_recorder()->WriteRecordedPositions(); | 523 masm()->positions_recorder()->WriteRecordedPositions(); |
524 } | 524 } |
525 | 525 |
526 | 526 |
527 void LCodeGen::RecordSafepointWithLazyDeopt(LInstruction* instr, | 527 void LCodeGen::RecordSafepointWithLazyDeopt(LInstruction* instr, |
528 SafepointMode safepoint_mode) { | 528 SafepointMode safepoint_mode) { |
529 if (safepoint_mode == RECORD_SIMPLE_SAFEPOINT) { | 529 if (safepoint_mode == RECORD_SIMPLE_SAFEPOINT) { |
530 RecordSafepoint(instr->pointer_map(), Safepoint::kLazyDeopt); | 530 RecordSafepoint(instr->pointer_map(), Safepoint::kLazyDeopt); |
531 } else { | 531 } else { |
532 ASSERT(safepoint_mode == RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS); | 532 DCHECK(safepoint_mode == RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS); |
533 RecordSafepointWithRegisters( | 533 RecordSafepointWithRegisters( |
534 instr->pointer_map(), 0, Safepoint::kLazyDeopt); | 534 instr->pointer_map(), 0, Safepoint::kLazyDeopt); |
535 } | 535 } |
536 } | 536 } |
537 | 537 |
538 | 538 |
539 void LCodeGen::RecordSafepoint(LPointerMap* pointers, | 539 void LCodeGen::RecordSafepoint(LPointerMap* pointers, |
540 Safepoint::Kind kind, | 540 Safepoint::Kind kind, |
541 int arguments, | 541 int arguments, |
542 Safepoint::DeoptMode deopt_mode) { | 542 Safepoint::DeoptMode deopt_mode) { |
543 ASSERT(expected_safepoint_kind_ == kind); | 543 DCHECK(expected_safepoint_kind_ == kind); |
544 | 544 |
545 const ZoneList<LOperand*>* operands = pointers->GetNormalizedOperands(); | 545 const ZoneList<LOperand*>* operands = pointers->GetNormalizedOperands(); |
546 Safepoint safepoint = safepoints_.DefineSafepoint( | 546 Safepoint safepoint = safepoints_.DefineSafepoint( |
547 masm(), kind, arguments, deopt_mode); | 547 masm(), kind, arguments, deopt_mode); |
548 | 548 |
549 for (int i = 0; i < operands->length(); i++) { | 549 for (int i = 0; i < operands->length(); i++) { |
550 LOperand* pointer = operands->at(i); | 550 LOperand* pointer = operands->at(i); |
551 if (pointer->IsStackSlot()) { | 551 if (pointer->IsStackSlot()) { |
552 safepoint.DefinePointerSlot(pointer->index(), zone()); | 552 safepoint.DefinePointerSlot(pointer->index(), zone()); |
553 } else if (pointer->IsRegister() && (kind & Safepoint::kWithRegisters)) { | 553 } else if (pointer->IsRegister() && (kind & Safepoint::kWithRegisters)) { |
(...skipping 21 matching lines...) Expand all Loading... |
575 | 575 |
576 void LCodeGen::RecordSafepointWithRegisters(LPointerMap* pointers, | 576 void LCodeGen::RecordSafepointWithRegisters(LPointerMap* pointers, |
577 int arguments, | 577 int arguments, |
578 Safepoint::DeoptMode deopt_mode) { | 578 Safepoint::DeoptMode deopt_mode) { |
579 RecordSafepoint(pointers, Safepoint::kWithRegisters, arguments, deopt_mode); | 579 RecordSafepoint(pointers, Safepoint::kWithRegisters, arguments, deopt_mode); |
580 } | 580 } |
581 | 581 |
582 | 582 |
583 bool LCodeGen::GenerateCode() { | 583 bool LCodeGen::GenerateCode() { |
584 LPhase phase("Z_Code generation", chunk()); | 584 LPhase phase("Z_Code generation", chunk()); |
585 ASSERT(is_unused()); | 585 DCHECK(is_unused()); |
586 status_ = GENERATING; | 586 status_ = GENERATING; |
587 | 587 |
588 // Open a frame scope to indicate that there is a frame on the stack. The | 588 // Open a frame scope to indicate that there is a frame on the stack. The |
589 // NONE indicates that the scope shouldn't actually generate code to set up | 589 // NONE indicates that the scope shouldn't actually generate code to set up |
590 // the frame (that is done in GeneratePrologue). | 590 // the frame (that is done in GeneratePrologue). |
591 FrameScope frame_scope(masm_, StackFrame::NONE); | 591 FrameScope frame_scope(masm_, StackFrame::NONE); |
592 | 592 |
593 return GeneratePrologue() && | 593 return GeneratePrologue() && |
594 GenerateBody() && | 594 GenerateBody() && |
595 GenerateDeferredCode() && | 595 GenerateDeferredCode() && |
596 GenerateDeoptJumpTable() && | 596 GenerateDeoptJumpTable() && |
597 GenerateSafepointTable(); | 597 GenerateSafepointTable(); |
598 } | 598 } |
599 | 599 |
600 | 600 |
601 void LCodeGen::SaveCallerDoubles() { | 601 void LCodeGen::SaveCallerDoubles() { |
602 ASSERT(info()->saves_caller_doubles()); | 602 DCHECK(info()->saves_caller_doubles()); |
603 ASSERT(NeedsEagerFrame()); | 603 DCHECK(NeedsEagerFrame()); |
604 Comment(";;; Save clobbered callee double registers"); | 604 Comment(";;; Save clobbered callee double registers"); |
605 BitVector* doubles = chunk()->allocated_double_registers(); | 605 BitVector* doubles = chunk()->allocated_double_registers(); |
606 BitVector::Iterator iterator(doubles); | 606 BitVector::Iterator iterator(doubles); |
607 int count = 0; | 607 int count = 0; |
608 while (!iterator.Done()) { | 608 while (!iterator.Done()) { |
609 // TODO(all): Is this supposed to save just the callee-saved doubles? It | 609 // TODO(all): Is this supposed to save just the callee-saved doubles? It |
610 // looks like it's saving all of them. | 610 // looks like it's saving all of them. |
611 FPRegister value = FPRegister::FromAllocationIndex(iterator.Current()); | 611 FPRegister value = FPRegister::FromAllocationIndex(iterator.Current()); |
612 __ Poke(value, count * kDoubleSize); | 612 __ Poke(value, count * kDoubleSize); |
613 iterator.Advance(); | 613 iterator.Advance(); |
614 count++; | 614 count++; |
615 } | 615 } |
616 } | 616 } |
617 | 617 |
618 | 618 |
619 void LCodeGen::RestoreCallerDoubles() { | 619 void LCodeGen::RestoreCallerDoubles() { |
620 ASSERT(info()->saves_caller_doubles()); | 620 DCHECK(info()->saves_caller_doubles()); |
621 ASSERT(NeedsEagerFrame()); | 621 DCHECK(NeedsEagerFrame()); |
622 Comment(";;; Restore clobbered callee double registers"); | 622 Comment(";;; Restore clobbered callee double registers"); |
623 BitVector* doubles = chunk()->allocated_double_registers(); | 623 BitVector* doubles = chunk()->allocated_double_registers(); |
624 BitVector::Iterator iterator(doubles); | 624 BitVector::Iterator iterator(doubles); |
625 int count = 0; | 625 int count = 0; |
626 while (!iterator.Done()) { | 626 while (!iterator.Done()) { |
627 // TODO(all): Is this supposed to restore just the callee-saved doubles? It | 627 // TODO(all): Is this supposed to restore just the callee-saved doubles? It |
628 // looks like it's restoring all of them. | 628 // looks like it's restoring all of them. |
629 FPRegister value = FPRegister::FromAllocationIndex(iterator.Current()); | 629 FPRegister value = FPRegister::FromAllocationIndex(iterator.Current()); |
630 __ Peek(value, count * kDoubleSize); | 630 __ Peek(value, count * kDoubleSize); |
631 iterator.Advance(); | 631 iterator.Advance(); |
632 count++; | 632 count++; |
633 } | 633 } |
634 } | 634 } |
635 | 635 |
636 | 636 |
637 bool LCodeGen::GeneratePrologue() { | 637 bool LCodeGen::GeneratePrologue() { |
638 ASSERT(is_generating()); | 638 DCHECK(is_generating()); |
639 | 639 |
640 if (info()->IsOptimizing()) { | 640 if (info()->IsOptimizing()) { |
641 ProfileEntryHookStub::MaybeCallEntryHook(masm_); | 641 ProfileEntryHookStub::MaybeCallEntryHook(masm_); |
642 | 642 |
643 // TODO(all): Add support for stop_t FLAG in DEBUG mode. | 643 // TODO(all): Add support for stop_t FLAG in DEBUG mode. |
644 | 644 |
645 // Sloppy mode functions and builtins need to replace the receiver with the | 645 // Sloppy mode functions and builtins need to replace the receiver with the |
646 // global proxy when called as functions (without an explicit receiver | 646 // global proxy when called as functions (without an explicit receiver |
647 // object). | 647 // object). |
648 if (info_->this_has_uses() && | 648 if (info_->this_has_uses() && |
649 info_->strict_mode() == SLOPPY && | 649 info_->strict_mode() == SLOPPY && |
650 !info_->is_native()) { | 650 !info_->is_native()) { |
651 Label ok; | 651 Label ok; |
652 int receiver_offset = info_->scope()->num_parameters() * kXRegSize; | 652 int receiver_offset = info_->scope()->num_parameters() * kXRegSize; |
653 __ Peek(x10, receiver_offset); | 653 __ Peek(x10, receiver_offset); |
654 __ JumpIfNotRoot(x10, Heap::kUndefinedValueRootIndex, &ok); | 654 __ JumpIfNotRoot(x10, Heap::kUndefinedValueRootIndex, &ok); |
655 | 655 |
656 __ Ldr(x10, GlobalObjectMemOperand()); | 656 __ Ldr(x10, GlobalObjectMemOperand()); |
657 __ Ldr(x10, FieldMemOperand(x10, GlobalObject::kGlobalProxyOffset)); | 657 __ Ldr(x10, FieldMemOperand(x10, GlobalObject::kGlobalProxyOffset)); |
658 __ Poke(x10, receiver_offset); | 658 __ Poke(x10, receiver_offset); |
659 | 659 |
660 __ Bind(&ok); | 660 __ Bind(&ok); |
661 } | 661 } |
662 } | 662 } |
663 | 663 |
664 ASSERT(__ StackPointer().Is(jssp)); | 664 DCHECK(__ StackPointer().Is(jssp)); |
665 info()->set_prologue_offset(masm_->pc_offset()); | 665 info()->set_prologue_offset(masm_->pc_offset()); |
666 if (NeedsEagerFrame()) { | 666 if (NeedsEagerFrame()) { |
667 if (info()->IsStub()) { | 667 if (info()->IsStub()) { |
668 __ StubPrologue(); | 668 __ StubPrologue(); |
669 } else { | 669 } else { |
670 __ Prologue(info()->IsCodePreAgingActive()); | 670 __ Prologue(info()->IsCodePreAgingActive()); |
671 } | 671 } |
672 frame_is_built_ = true; | 672 frame_is_built_ = true; |
673 info_->AddNoFrameRange(0, masm_->pc_offset()); | 673 info_->AddNoFrameRange(0, masm_->pc_offset()); |
674 } | 674 } |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
747 void LCodeGen::GenerateOsrPrologue() { | 747 void LCodeGen::GenerateOsrPrologue() { |
748 // Generate the OSR entry prologue at the first unknown OSR value, or if there | 748 // Generate the OSR entry prologue at the first unknown OSR value, or if there |
749 // are none, at the OSR entrypoint instruction. | 749 // are none, at the OSR entrypoint instruction. |
750 if (osr_pc_offset_ >= 0) return; | 750 if (osr_pc_offset_ >= 0) return; |
751 | 751 |
752 osr_pc_offset_ = masm()->pc_offset(); | 752 osr_pc_offset_ = masm()->pc_offset(); |
753 | 753 |
754 // Adjust the frame size, subsuming the unoptimized frame into the | 754 // Adjust the frame size, subsuming the unoptimized frame into the |
755 // optimized frame. | 755 // optimized frame. |
756 int slots = GetStackSlotCount() - graph()->osr()->UnoptimizedFrameSlots(); | 756 int slots = GetStackSlotCount() - graph()->osr()->UnoptimizedFrameSlots(); |
757 ASSERT(slots >= 0); | 757 DCHECK(slots >= 0); |
758 __ Claim(slots); | 758 __ Claim(slots); |
759 } | 759 } |
760 | 760 |
761 | 761 |
762 void LCodeGen::GenerateBodyInstructionPre(LInstruction* instr) { | 762 void LCodeGen::GenerateBodyInstructionPre(LInstruction* instr) { |
763 if (instr->IsCall()) { | 763 if (instr->IsCall()) { |
764 EnsureSpaceForLazyDeopt(Deoptimizer::patch_size()); | 764 EnsureSpaceForLazyDeopt(Deoptimizer::patch_size()); |
765 } | 765 } |
766 if (!instr->IsLazyBailout() && !instr->IsGap()) { | 766 if (!instr->IsLazyBailout() && !instr->IsGap()) { |
767 safepoints_.BumpLastLazySafepointIndex(); | 767 safepoints_.BumpLastLazySafepointIndex(); |
768 } | 768 } |
769 } | 769 } |
770 | 770 |
771 | 771 |
772 bool LCodeGen::GenerateDeferredCode() { | 772 bool LCodeGen::GenerateDeferredCode() { |
773 ASSERT(is_generating()); | 773 DCHECK(is_generating()); |
774 if (deferred_.length() > 0) { | 774 if (deferred_.length() > 0) { |
775 for (int i = 0; !is_aborted() && (i < deferred_.length()); i++) { | 775 for (int i = 0; !is_aborted() && (i < deferred_.length()); i++) { |
776 LDeferredCode* code = deferred_[i]; | 776 LDeferredCode* code = deferred_[i]; |
777 | 777 |
778 HValue* value = | 778 HValue* value = |
779 instructions_->at(code->instruction_index())->hydrogen_value(); | 779 instructions_->at(code->instruction_index())->hydrogen_value(); |
780 RecordAndWritePosition( | 780 RecordAndWritePosition( |
781 chunk()->graph()->SourcePositionToScriptPosition(value->position())); | 781 chunk()->graph()->SourcePositionToScriptPosition(value->position())); |
782 | 782 |
783 Comment(";;; <@%d,#%d> " | 783 Comment(";;; <@%d,#%d> " |
784 "-------------------- Deferred %s --------------------", | 784 "-------------------- Deferred %s --------------------", |
785 code->instruction_index(), | 785 code->instruction_index(), |
786 code->instr()->hydrogen_value()->id(), | 786 code->instr()->hydrogen_value()->id(), |
787 code->instr()->Mnemonic()); | 787 code->instr()->Mnemonic()); |
788 | 788 |
789 __ Bind(code->entry()); | 789 __ Bind(code->entry()); |
790 | 790 |
791 if (NeedsDeferredFrame()) { | 791 if (NeedsDeferredFrame()) { |
792 Comment(";;; Build frame"); | 792 Comment(";;; Build frame"); |
793 ASSERT(!frame_is_built_); | 793 DCHECK(!frame_is_built_); |
794 ASSERT(info()->IsStub()); | 794 DCHECK(info()->IsStub()); |
795 frame_is_built_ = true; | 795 frame_is_built_ = true; |
796 __ Push(lr, fp, cp); | 796 __ Push(lr, fp, cp); |
797 __ Mov(fp, Smi::FromInt(StackFrame::STUB)); | 797 __ Mov(fp, Smi::FromInt(StackFrame::STUB)); |
798 __ Push(fp); | 798 __ Push(fp); |
799 __ Add(fp, __ StackPointer(), | 799 __ Add(fp, __ StackPointer(), |
800 StandardFrameConstants::kFixedFrameSizeFromFp); | 800 StandardFrameConstants::kFixedFrameSizeFromFp); |
801 Comment(";;; Deferred code"); | 801 Comment(";;; Deferred code"); |
802 } | 802 } |
803 | 803 |
804 code->Generate(); | 804 code->Generate(); |
805 | 805 |
806 if (NeedsDeferredFrame()) { | 806 if (NeedsDeferredFrame()) { |
807 Comment(";;; Destroy frame"); | 807 Comment(";;; Destroy frame"); |
808 ASSERT(frame_is_built_); | 808 DCHECK(frame_is_built_); |
809 __ Pop(xzr, cp, fp, lr); | 809 __ Pop(xzr, cp, fp, lr); |
810 frame_is_built_ = false; | 810 frame_is_built_ = false; |
811 } | 811 } |
812 | 812 |
813 __ B(code->exit()); | 813 __ B(code->exit()); |
814 } | 814 } |
815 } | 815 } |
816 | 816 |
817 // Force constant pool emission at the end of the deferred code to make | 817 // Force constant pool emission at the end of the deferred code to make |
818 // sure that no constant pools are emitted after deferred code because | 818 // sure that no constant pools are emitted after deferred code because |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
850 // Second-level deopt table entries are contiguous and small, so instead | 850 // Second-level deopt table entries are contiguous and small, so instead |
851 // of loading the full, absolute address of each one, load the base | 851 // of loading the full, absolute address of each one, load the base |
852 // address and add an immediate offset. | 852 // address and add an immediate offset. |
853 __ Mov(entry_offset, entry - base); | 853 __ Mov(entry_offset, entry - base); |
854 | 854 |
855 // The last entry can fall through into `call_deopt_entry`, avoiding a | 855 // The last entry can fall through into `call_deopt_entry`, avoiding a |
856 // branch. | 856 // branch. |
857 bool last_entry = (i + 1) == length; | 857 bool last_entry = (i + 1) == length; |
858 | 858 |
859 if (deopt_jump_table_[i]->needs_frame) { | 859 if (deopt_jump_table_[i]->needs_frame) { |
860 ASSERT(!info()->saves_caller_doubles()); | 860 DCHECK(!info()->saves_caller_doubles()); |
861 if (!needs_frame.is_bound()) { | 861 if (!needs_frame.is_bound()) { |
862 // This variant of deopt can only be used with stubs. Since we don't | 862 // This variant of deopt can only be used with stubs. Since we don't |
863 // have a function pointer to install in the stack frame that we're | 863 // have a function pointer to install in the stack frame that we're |
864 // building, install a special marker there instead. | 864 // building, install a special marker there instead. |
865 ASSERT(info()->IsStub()); | 865 DCHECK(info()->IsStub()); |
866 | 866 |
867 UseScratchRegisterScope temps(masm()); | 867 UseScratchRegisterScope temps(masm()); |
868 Register stub_marker = temps.AcquireX(); | 868 Register stub_marker = temps.AcquireX(); |
869 __ Bind(&needs_frame); | 869 __ Bind(&needs_frame); |
870 __ Mov(stub_marker, Smi::FromInt(StackFrame::STUB)); | 870 __ Mov(stub_marker, Smi::FromInt(StackFrame::STUB)); |
871 __ Push(lr, fp, cp, stub_marker); | 871 __ Push(lr, fp, cp, stub_marker); |
872 __ Add(fp, __ StackPointer(), 2 * kPointerSize); | 872 __ Add(fp, __ StackPointer(), 2 * kPointerSize); |
873 if (!last_entry) __ B(&call_deopt_entry); | 873 if (!last_entry) __ B(&call_deopt_entry); |
874 } else { | 874 } else { |
875 // Reuse the existing needs_frame code. | 875 // Reuse the existing needs_frame code. |
876 __ B(&needs_frame); | 876 __ B(&needs_frame); |
877 } | 877 } |
878 } else if (info()->saves_caller_doubles()) { | 878 } else if (info()->saves_caller_doubles()) { |
879 ASSERT(info()->IsStub()); | 879 DCHECK(info()->IsStub()); |
880 if (!restore_caller_doubles.is_bound()) { | 880 if (!restore_caller_doubles.is_bound()) { |
881 __ Bind(&restore_caller_doubles); | 881 __ Bind(&restore_caller_doubles); |
882 RestoreCallerDoubles(); | 882 RestoreCallerDoubles(); |
883 if (!last_entry) __ B(&call_deopt_entry); | 883 if (!last_entry) __ B(&call_deopt_entry); |
884 } else { | 884 } else { |
885 // Reuse the existing restore_caller_doubles code. | 885 // Reuse the existing restore_caller_doubles code. |
886 __ B(&restore_caller_doubles); | 886 __ B(&restore_caller_doubles); |
887 } | 887 } |
888 } else { | 888 } else { |
889 // There is nothing special to do, so just continue to the second-level | 889 // There is nothing special to do, so just continue to the second-level |
(...skipping 18 matching lines...) Expand all Loading... |
908 masm()->CheckConstPool(true, false); | 908 masm()->CheckConstPool(true, false); |
909 | 909 |
910 // The deoptimization jump table is the last part of the instruction | 910 // The deoptimization jump table is the last part of the instruction |
911 // sequence. Mark the generated code as done unless we bailed out. | 911 // sequence. Mark the generated code as done unless we bailed out. |
912 if (!is_aborted()) status_ = DONE; | 912 if (!is_aborted()) status_ = DONE; |
913 return !is_aborted(); | 913 return !is_aborted(); |
914 } | 914 } |
915 | 915 |
916 | 916 |
917 bool LCodeGen::GenerateSafepointTable() { | 917 bool LCodeGen::GenerateSafepointTable() { |
918 ASSERT(is_done()); | 918 DCHECK(is_done()); |
919 // We do not know how much data will be emitted for the safepoint table, so | 919 // We do not know how much data will be emitted for the safepoint table, so |
920 // force emission of the veneer pool. | 920 // force emission of the veneer pool. |
921 masm()->CheckVeneerPool(true, true); | 921 masm()->CheckVeneerPool(true, true); |
922 safepoints_.Emit(masm(), GetStackSlotCount()); | 922 safepoints_.Emit(masm(), GetStackSlotCount()); |
923 return !is_aborted(); | 923 return !is_aborted(); |
924 } | 924 } |
925 | 925 |
926 | 926 |
927 void LCodeGen::FinishCode(Handle<Code> code) { | 927 void LCodeGen::FinishCode(Handle<Code> code) { |
928 ASSERT(is_done()); | 928 DCHECK(is_done()); |
929 code->set_stack_slots(GetStackSlotCount()); | 929 code->set_stack_slots(GetStackSlotCount()); |
930 code->set_safepoint_table_offset(safepoints_.GetCodeOffset()); | 930 code->set_safepoint_table_offset(safepoints_.GetCodeOffset()); |
931 if (code->is_optimized_code()) RegisterWeakObjectsInOptimizedCode(code); | 931 if (code->is_optimized_code()) RegisterWeakObjectsInOptimizedCode(code); |
932 PopulateDeoptimizationData(code); | 932 PopulateDeoptimizationData(code); |
933 } | 933 } |
934 | 934 |
935 | 935 |
936 void LCodeGen::PopulateDeoptimizationData(Handle<Code> code) { | 936 void LCodeGen::PopulateDeoptimizationData(Handle<Code> code) { |
937 int length = deoptimizations_.length(); | 937 int length = deoptimizations_.length(); |
938 if (length == 0) return; | 938 if (length == 0) return; |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
973 data->SetArgumentsStackHeight(i, | 973 data->SetArgumentsStackHeight(i, |
974 Smi::FromInt(env->arguments_stack_height())); | 974 Smi::FromInt(env->arguments_stack_height())); |
975 data->SetPc(i, Smi::FromInt(env->pc_offset())); | 975 data->SetPc(i, Smi::FromInt(env->pc_offset())); |
976 } | 976 } |
977 | 977 |
978 code->set_deoptimization_data(*data); | 978 code->set_deoptimization_data(*data); |
979 } | 979 } |
980 | 980 |
981 | 981 |
982 void LCodeGen::PopulateDeoptimizationLiteralsWithInlinedFunctions() { | 982 void LCodeGen::PopulateDeoptimizationLiteralsWithInlinedFunctions() { |
983 ASSERT(deoptimization_literals_.length() == 0); | 983 DCHECK(deoptimization_literals_.length() == 0); |
984 | 984 |
985 const ZoneList<Handle<JSFunction> >* inlined_closures = | 985 const ZoneList<Handle<JSFunction> >* inlined_closures = |
986 chunk()->inlined_closures(); | 986 chunk()->inlined_closures(); |
987 | 987 |
988 for (int i = 0, length = inlined_closures->length(); i < length; i++) { | 988 for (int i = 0, length = inlined_closures->length(); i < length; i++) { |
989 DefineDeoptimizationLiteral(inlined_closures->at(i)); | 989 DefineDeoptimizationLiteral(inlined_closures->at(i)); |
990 } | 990 } |
991 | 991 |
992 inlined_function_count_ = deoptimization_literals_.length(); | 992 inlined_function_count_ = deoptimization_literals_.length(); |
993 } | 993 } |
994 | 994 |
995 | 995 |
996 void LCodeGen::DeoptimizeBranch( | 996 void LCodeGen::DeoptimizeBranch( |
997 LEnvironment* environment, | 997 LEnvironment* environment, |
998 BranchType branch_type, Register reg, int bit, | 998 BranchType branch_type, Register reg, int bit, |
999 Deoptimizer::BailoutType* override_bailout_type) { | 999 Deoptimizer::BailoutType* override_bailout_type) { |
1000 RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt); | 1000 RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt); |
1001 Deoptimizer::BailoutType bailout_type = | 1001 Deoptimizer::BailoutType bailout_type = |
1002 info()->IsStub() ? Deoptimizer::LAZY : Deoptimizer::EAGER; | 1002 info()->IsStub() ? Deoptimizer::LAZY : Deoptimizer::EAGER; |
1003 | 1003 |
1004 if (override_bailout_type != NULL) { | 1004 if (override_bailout_type != NULL) { |
1005 bailout_type = *override_bailout_type; | 1005 bailout_type = *override_bailout_type; |
1006 } | 1006 } |
1007 | 1007 |
1008 ASSERT(environment->HasBeenRegistered()); | 1008 DCHECK(environment->HasBeenRegistered()); |
1009 ASSERT(info()->IsOptimizing() || info()->IsStub()); | 1009 DCHECK(info()->IsOptimizing() || info()->IsStub()); |
1010 int id = environment->deoptimization_index(); | 1010 int id = environment->deoptimization_index(); |
1011 Address entry = | 1011 Address entry = |
1012 Deoptimizer::GetDeoptimizationEntry(isolate(), id, bailout_type); | 1012 Deoptimizer::GetDeoptimizationEntry(isolate(), id, bailout_type); |
1013 | 1013 |
1014 if (entry == NULL) { | 1014 if (entry == NULL) { |
1015 Abort(kBailoutWasNotPrepared); | 1015 Abort(kBailoutWasNotPrepared); |
1016 } | 1016 } |
1017 | 1017 |
1018 if (FLAG_deopt_every_n_times != 0 && !info()->IsStub()) { | 1018 if (FLAG_deopt_every_n_times != 0 && !info()->IsStub()) { |
1019 Label not_zero; | 1019 Label not_zero; |
1020 ExternalReference count = ExternalReference::stress_deopt_count(isolate()); | 1020 ExternalReference count = ExternalReference::stress_deopt_count(isolate()); |
1021 | 1021 |
1022 __ Push(x0, x1, x2); | 1022 __ Push(x0, x1, x2); |
1023 __ Mrs(x2, NZCV); | 1023 __ Mrs(x2, NZCV); |
1024 __ Mov(x0, count); | 1024 __ Mov(x0, count); |
1025 __ Ldr(w1, MemOperand(x0)); | 1025 __ Ldr(w1, MemOperand(x0)); |
1026 __ Subs(x1, x1, 1); | 1026 __ Subs(x1, x1, 1); |
1027 __ B(gt, ¬_zero); | 1027 __ B(gt, ¬_zero); |
1028 __ Mov(w1, FLAG_deopt_every_n_times); | 1028 __ Mov(w1, FLAG_deopt_every_n_times); |
1029 __ Str(w1, MemOperand(x0)); | 1029 __ Str(w1, MemOperand(x0)); |
1030 __ Pop(x2, x1, x0); | 1030 __ Pop(x2, x1, x0); |
1031 ASSERT(frame_is_built_); | 1031 DCHECK(frame_is_built_); |
1032 __ Call(entry, RelocInfo::RUNTIME_ENTRY); | 1032 __ Call(entry, RelocInfo::RUNTIME_ENTRY); |
1033 __ Unreachable(); | 1033 __ Unreachable(); |
1034 | 1034 |
1035 __ Bind(¬_zero); | 1035 __ Bind(¬_zero); |
1036 __ Str(w1, MemOperand(x0)); | 1036 __ Str(w1, MemOperand(x0)); |
1037 __ Msr(NZCV, x2); | 1037 __ Msr(NZCV, x2); |
1038 __ Pop(x2, x1, x0); | 1038 __ Pop(x2, x1, x0); |
1039 } | 1039 } |
1040 | 1040 |
1041 if (info()->ShouldTrapOnDeopt()) { | 1041 if (info()->ShouldTrapOnDeopt()) { |
1042 Label dont_trap; | 1042 Label dont_trap; |
1043 __ B(&dont_trap, InvertBranchType(branch_type), reg, bit); | 1043 __ B(&dont_trap, InvertBranchType(branch_type), reg, bit); |
1044 __ Debug("trap_on_deopt", __LINE__, BREAK); | 1044 __ Debug("trap_on_deopt", __LINE__, BREAK); |
1045 __ Bind(&dont_trap); | 1045 __ Bind(&dont_trap); |
1046 } | 1046 } |
1047 | 1047 |
1048 ASSERT(info()->IsStub() || frame_is_built_); | 1048 DCHECK(info()->IsStub() || frame_is_built_); |
1049 // Go through jump table if we need to build frame, or restore caller doubles. | 1049 // Go through jump table if we need to build frame, or restore caller doubles. |
1050 if (branch_type == always && | 1050 if (branch_type == always && |
1051 frame_is_built_ && !info()->saves_caller_doubles()) { | 1051 frame_is_built_ && !info()->saves_caller_doubles()) { |
1052 __ Call(entry, RelocInfo::RUNTIME_ENTRY); | 1052 __ Call(entry, RelocInfo::RUNTIME_ENTRY); |
1053 } else { | 1053 } else { |
1054 // We often have several deopts to the same entry, reuse the last | 1054 // We often have several deopts to the same entry, reuse the last |
1055 // jump entry if this is the case. | 1055 // jump entry if this is the case. |
1056 if (deopt_jump_table_.is_empty() || | 1056 if (deopt_jump_table_.is_empty() || |
1057 (deopt_jump_table_.last()->address != entry) || | 1057 (deopt_jump_table_.last()->address != entry) || |
1058 (deopt_jump_table_.last()->bailout_type != bailout_type) || | 1058 (deopt_jump_table_.last()->bailout_type != bailout_type) || |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1145 | 1145 |
1146 | 1146 |
1147 void LCodeGen::EnsureSpaceForLazyDeopt(int space_needed) { | 1147 void LCodeGen::EnsureSpaceForLazyDeopt(int space_needed) { |
1148 if (!info()->IsStub()) { | 1148 if (!info()->IsStub()) { |
1149 // Ensure that we have enough space after the previous lazy-bailout | 1149 // Ensure that we have enough space after the previous lazy-bailout |
1150 // instruction for patching the code here. | 1150 // instruction for patching the code here. |
1151 intptr_t current_pc = masm()->pc_offset(); | 1151 intptr_t current_pc = masm()->pc_offset(); |
1152 | 1152 |
1153 if (current_pc < (last_lazy_deopt_pc_ + space_needed)) { | 1153 if (current_pc < (last_lazy_deopt_pc_ + space_needed)) { |
1154 ptrdiff_t padding_size = last_lazy_deopt_pc_ + space_needed - current_pc; | 1154 ptrdiff_t padding_size = last_lazy_deopt_pc_ + space_needed - current_pc; |
1155 ASSERT((padding_size % kInstructionSize) == 0); | 1155 DCHECK((padding_size % kInstructionSize) == 0); |
1156 InstructionAccurateScope instruction_accurate( | 1156 InstructionAccurateScope instruction_accurate( |
1157 masm(), padding_size / kInstructionSize); | 1157 masm(), padding_size / kInstructionSize); |
1158 | 1158 |
1159 while (padding_size > 0) { | 1159 while (padding_size > 0) { |
1160 __ nop(); | 1160 __ nop(); |
1161 padding_size -= kInstructionSize; | 1161 padding_size -= kInstructionSize; |
1162 } | 1162 } |
1163 } | 1163 } |
1164 } | 1164 } |
1165 last_lazy_deopt_pc_ = masm()->pc_offset(); | 1165 last_lazy_deopt_pc_ = masm()->pc_offset(); |
1166 } | 1166 } |
1167 | 1167 |
1168 | 1168 |
1169 Register LCodeGen::ToRegister(LOperand* op) const { | 1169 Register LCodeGen::ToRegister(LOperand* op) const { |
1170 // TODO(all): support zero register results, as ToRegister32. | 1170 // TODO(all): support zero register results, as ToRegister32. |
1171 ASSERT((op != NULL) && op->IsRegister()); | 1171 DCHECK((op != NULL) && op->IsRegister()); |
1172 return Register::FromAllocationIndex(op->index()); | 1172 return Register::FromAllocationIndex(op->index()); |
1173 } | 1173 } |
1174 | 1174 |
1175 | 1175 |
1176 Register LCodeGen::ToRegister32(LOperand* op) const { | 1176 Register LCodeGen::ToRegister32(LOperand* op) const { |
1177 ASSERT(op != NULL); | 1177 DCHECK(op != NULL); |
1178 if (op->IsConstantOperand()) { | 1178 if (op->IsConstantOperand()) { |
1179 // If this is a constant operand, the result must be the zero register. | 1179 // If this is a constant operand, the result must be the zero register. |
1180 ASSERT(ToInteger32(LConstantOperand::cast(op)) == 0); | 1180 DCHECK(ToInteger32(LConstantOperand::cast(op)) == 0); |
1181 return wzr; | 1181 return wzr; |
1182 } else { | 1182 } else { |
1183 return ToRegister(op).W(); | 1183 return ToRegister(op).W(); |
1184 } | 1184 } |
1185 } | 1185 } |
1186 | 1186 |
1187 | 1187 |
1188 Smi* LCodeGen::ToSmi(LConstantOperand* op) const { | 1188 Smi* LCodeGen::ToSmi(LConstantOperand* op) const { |
1189 HConstant* constant = chunk_->LookupConstant(op); | 1189 HConstant* constant = chunk_->LookupConstant(op); |
1190 return Smi::FromInt(constant->Integer32Value()); | 1190 return Smi::FromInt(constant->Integer32Value()); |
1191 } | 1191 } |
1192 | 1192 |
1193 | 1193 |
1194 DoubleRegister LCodeGen::ToDoubleRegister(LOperand* op) const { | 1194 DoubleRegister LCodeGen::ToDoubleRegister(LOperand* op) const { |
1195 ASSERT((op != NULL) && op->IsDoubleRegister()); | 1195 DCHECK((op != NULL) && op->IsDoubleRegister()); |
1196 return DoubleRegister::FromAllocationIndex(op->index()); | 1196 return DoubleRegister::FromAllocationIndex(op->index()); |
1197 } | 1197 } |
1198 | 1198 |
1199 | 1199 |
1200 Operand LCodeGen::ToOperand(LOperand* op) { | 1200 Operand LCodeGen::ToOperand(LOperand* op) { |
1201 ASSERT(op != NULL); | 1201 DCHECK(op != NULL); |
1202 if (op->IsConstantOperand()) { | 1202 if (op->IsConstantOperand()) { |
1203 LConstantOperand* const_op = LConstantOperand::cast(op); | 1203 LConstantOperand* const_op = LConstantOperand::cast(op); |
1204 HConstant* constant = chunk()->LookupConstant(const_op); | 1204 HConstant* constant = chunk()->LookupConstant(const_op); |
1205 Representation r = chunk_->LookupLiteralRepresentation(const_op); | 1205 Representation r = chunk_->LookupLiteralRepresentation(const_op); |
1206 if (r.IsSmi()) { | 1206 if (r.IsSmi()) { |
1207 ASSERT(constant->HasSmiValue()); | 1207 DCHECK(constant->HasSmiValue()); |
1208 return Operand(Smi::FromInt(constant->Integer32Value())); | 1208 return Operand(Smi::FromInt(constant->Integer32Value())); |
1209 } else if (r.IsInteger32()) { | 1209 } else if (r.IsInteger32()) { |
1210 ASSERT(constant->HasInteger32Value()); | 1210 DCHECK(constant->HasInteger32Value()); |
1211 return Operand(constant->Integer32Value()); | 1211 return Operand(constant->Integer32Value()); |
1212 } else if (r.IsDouble()) { | 1212 } else if (r.IsDouble()) { |
1213 Abort(kToOperandUnsupportedDoubleImmediate); | 1213 Abort(kToOperandUnsupportedDoubleImmediate); |
1214 } | 1214 } |
1215 ASSERT(r.IsTagged()); | 1215 DCHECK(r.IsTagged()); |
1216 return Operand(constant->handle(isolate())); | 1216 return Operand(constant->handle(isolate())); |
1217 } else if (op->IsRegister()) { | 1217 } else if (op->IsRegister()) { |
1218 return Operand(ToRegister(op)); | 1218 return Operand(ToRegister(op)); |
1219 } else if (op->IsDoubleRegister()) { | 1219 } else if (op->IsDoubleRegister()) { |
1220 Abort(kToOperandIsDoubleRegisterUnimplemented); | 1220 Abort(kToOperandIsDoubleRegisterUnimplemented); |
1221 return Operand(0); | 1221 return Operand(0); |
1222 } | 1222 } |
1223 // Stack slots not implemented, use ToMemOperand instead. | 1223 // Stack slots not implemented, use ToMemOperand instead. |
1224 UNREACHABLE(); | 1224 UNREACHABLE(); |
1225 return Operand(0); | 1225 return Operand(0); |
1226 } | 1226 } |
1227 | 1227 |
1228 | 1228 |
1229 Operand LCodeGen::ToOperand32I(LOperand* op) { | 1229 Operand LCodeGen::ToOperand32I(LOperand* op) { |
1230 return ToOperand32(op, SIGNED_INT32); | 1230 return ToOperand32(op, SIGNED_INT32); |
1231 } | 1231 } |
1232 | 1232 |
1233 | 1233 |
1234 Operand LCodeGen::ToOperand32U(LOperand* op) { | 1234 Operand LCodeGen::ToOperand32U(LOperand* op) { |
1235 return ToOperand32(op, UNSIGNED_INT32); | 1235 return ToOperand32(op, UNSIGNED_INT32); |
1236 } | 1236 } |
1237 | 1237 |
1238 | 1238 |
1239 Operand LCodeGen::ToOperand32(LOperand* op, IntegerSignedness signedness) { | 1239 Operand LCodeGen::ToOperand32(LOperand* op, IntegerSignedness signedness) { |
1240 ASSERT(op != NULL); | 1240 DCHECK(op != NULL); |
1241 if (op->IsRegister()) { | 1241 if (op->IsRegister()) { |
1242 return Operand(ToRegister32(op)); | 1242 return Operand(ToRegister32(op)); |
1243 } else if (op->IsConstantOperand()) { | 1243 } else if (op->IsConstantOperand()) { |
1244 LConstantOperand* const_op = LConstantOperand::cast(op); | 1244 LConstantOperand* const_op = LConstantOperand::cast(op); |
1245 HConstant* constant = chunk()->LookupConstant(const_op); | 1245 HConstant* constant = chunk()->LookupConstant(const_op); |
1246 Representation r = chunk_->LookupLiteralRepresentation(const_op); | 1246 Representation r = chunk_->LookupLiteralRepresentation(const_op); |
1247 if (r.IsInteger32()) { | 1247 if (r.IsInteger32()) { |
1248 ASSERT(constant->HasInteger32Value()); | 1248 DCHECK(constant->HasInteger32Value()); |
1249 return (signedness == SIGNED_INT32) | 1249 return (signedness == SIGNED_INT32) |
1250 ? Operand(constant->Integer32Value()) | 1250 ? Operand(constant->Integer32Value()) |
1251 : Operand(static_cast<uint32_t>(constant->Integer32Value())); | 1251 : Operand(static_cast<uint32_t>(constant->Integer32Value())); |
1252 } else { | 1252 } else { |
1253 // Other constants not implemented. | 1253 // Other constants not implemented. |
1254 Abort(kToOperand32UnsupportedImmediate); | 1254 Abort(kToOperand32UnsupportedImmediate); |
1255 } | 1255 } |
1256 } | 1256 } |
1257 // Other cases are not implemented. | 1257 // Other cases are not implemented. |
1258 UNREACHABLE(); | 1258 UNREACHABLE(); |
1259 return Operand(0); | 1259 return Operand(0); |
1260 } | 1260 } |
1261 | 1261 |
1262 | 1262 |
1263 static ptrdiff_t ArgumentsOffsetWithoutFrame(ptrdiff_t index) { | 1263 static ptrdiff_t ArgumentsOffsetWithoutFrame(ptrdiff_t index) { |
1264 ASSERT(index < 0); | 1264 DCHECK(index < 0); |
1265 return -(index + 1) * kPointerSize; | 1265 return -(index + 1) * kPointerSize; |
1266 } | 1266 } |
1267 | 1267 |
1268 | 1268 |
1269 MemOperand LCodeGen::ToMemOperand(LOperand* op, StackMode stack_mode) const { | 1269 MemOperand LCodeGen::ToMemOperand(LOperand* op, StackMode stack_mode) const { |
1270 ASSERT(op != NULL); | 1270 DCHECK(op != NULL); |
1271 ASSERT(!op->IsRegister()); | 1271 DCHECK(!op->IsRegister()); |
1272 ASSERT(!op->IsDoubleRegister()); | 1272 DCHECK(!op->IsDoubleRegister()); |
1273 ASSERT(op->IsStackSlot() || op->IsDoubleStackSlot()); | 1273 DCHECK(op->IsStackSlot() || op->IsDoubleStackSlot()); |
1274 if (NeedsEagerFrame()) { | 1274 if (NeedsEagerFrame()) { |
1275 int fp_offset = StackSlotOffset(op->index()); | 1275 int fp_offset = StackSlotOffset(op->index()); |
1276 if (op->index() >= 0) { | 1276 if (op->index() >= 0) { |
1277 // Loads and stores have a bigger reach in positive offset than negative. | 1277 // Loads and stores have a bigger reach in positive offset than negative. |
1278 // When the load or the store can't be done in one instruction via fp | 1278 // When the load or the store can't be done in one instruction via fp |
1279 // (too big negative offset), we try to access via jssp (positive offset). | 1279 // (too big negative offset), we try to access via jssp (positive offset). |
1280 // We can reference a stack slot from jssp only if jssp references the end | 1280 // We can reference a stack slot from jssp only if jssp references the end |
1281 // of the stack slots. It's not the case when: | 1281 // of the stack slots. It's not the case when: |
1282 // - stack_mode != kCanUseStackPointer: this is the case when a deferred | 1282 // - stack_mode != kCanUseStackPointer: this is the case when a deferred |
1283 // code saved the registers. | 1283 // code saved the registers. |
(...skipping 18 matching lines...) Expand all Loading... |
1302 // Retrieve parameter without eager stack-frame relative to the | 1302 // Retrieve parameter without eager stack-frame relative to the |
1303 // stack-pointer. | 1303 // stack-pointer. |
1304 return MemOperand(masm()->StackPointer(), | 1304 return MemOperand(masm()->StackPointer(), |
1305 ArgumentsOffsetWithoutFrame(op->index())); | 1305 ArgumentsOffsetWithoutFrame(op->index())); |
1306 } | 1306 } |
1307 } | 1307 } |
1308 | 1308 |
1309 | 1309 |
1310 Handle<Object> LCodeGen::ToHandle(LConstantOperand* op) const { | 1310 Handle<Object> LCodeGen::ToHandle(LConstantOperand* op) const { |
1311 HConstant* constant = chunk_->LookupConstant(op); | 1311 HConstant* constant = chunk_->LookupConstant(op); |
1312 ASSERT(chunk_->LookupLiteralRepresentation(op).IsSmiOrTagged()); | 1312 DCHECK(chunk_->LookupLiteralRepresentation(op).IsSmiOrTagged()); |
1313 return constant->handle(isolate()); | 1313 return constant->handle(isolate()); |
1314 } | 1314 } |
1315 | 1315 |
1316 | 1316 |
1317 template<class LI> | 1317 template<class LI> |
1318 Operand LCodeGen::ToShiftedRightOperand32(LOperand* right, LI* shift_info, | 1318 Operand LCodeGen::ToShiftedRightOperand32(LOperand* right, LI* shift_info, |
1319 IntegerSignedness signedness) { | 1319 IntegerSignedness signedness) { |
1320 if (shift_info->shift() == NO_SHIFT) { | 1320 if (shift_info->shift() == NO_SHIFT) { |
1321 return (signedness == SIGNED_INT32) ? ToOperand32I(right) | 1321 return (signedness == SIGNED_INT32) ? ToOperand32I(right) |
1322 : ToOperand32U(right); | 1322 : ToOperand32U(right); |
(...skipping 17 matching lines...) Expand all Loading... |
1340 | 1340 |
1341 | 1341 |
1342 int32_t LCodeGen::ToInteger32(LConstantOperand* op) const { | 1342 int32_t LCodeGen::ToInteger32(LConstantOperand* op) const { |
1343 HConstant* constant = chunk_->LookupConstant(op); | 1343 HConstant* constant = chunk_->LookupConstant(op); |
1344 return constant->Integer32Value(); | 1344 return constant->Integer32Value(); |
1345 } | 1345 } |
1346 | 1346 |
1347 | 1347 |
1348 double LCodeGen::ToDouble(LConstantOperand* op) const { | 1348 double LCodeGen::ToDouble(LConstantOperand* op) const { |
1349 HConstant* constant = chunk_->LookupConstant(op); | 1349 HConstant* constant = chunk_->LookupConstant(op); |
1350 ASSERT(constant->HasDoubleValue()); | 1350 DCHECK(constant->HasDoubleValue()); |
1351 return constant->DoubleValue(); | 1351 return constant->DoubleValue(); |
1352 } | 1352 } |
1353 | 1353 |
1354 | 1354 |
1355 Condition LCodeGen::TokenToCondition(Token::Value op, bool is_unsigned) { | 1355 Condition LCodeGen::TokenToCondition(Token::Value op, bool is_unsigned) { |
1356 Condition cond = nv; | 1356 Condition cond = nv; |
1357 switch (op) { | 1357 switch (op) { |
1358 case Token::EQ: | 1358 case Token::EQ: |
1359 case Token::EQ_STRICT: | 1359 case Token::EQ_STRICT: |
1360 cond = eq; | 1360 cond = eq; |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1400 branch.Emit(chunk_->GetAssemblyLabel(left_block)); | 1400 branch.Emit(chunk_->GetAssemblyLabel(left_block)); |
1401 } else { | 1401 } else { |
1402 branch.Emit(chunk_->GetAssemblyLabel(left_block)); | 1402 branch.Emit(chunk_->GetAssemblyLabel(left_block)); |
1403 __ B(chunk_->GetAssemblyLabel(right_block)); | 1403 __ B(chunk_->GetAssemblyLabel(right_block)); |
1404 } | 1404 } |
1405 } | 1405 } |
1406 | 1406 |
1407 | 1407 |
1408 template<class InstrType> | 1408 template<class InstrType> |
1409 void LCodeGen::EmitBranch(InstrType instr, Condition condition) { | 1409 void LCodeGen::EmitBranch(InstrType instr, Condition condition) { |
1410 ASSERT((condition != al) && (condition != nv)); | 1410 DCHECK((condition != al) && (condition != nv)); |
1411 BranchOnCondition branch(this, condition); | 1411 BranchOnCondition branch(this, condition); |
1412 EmitBranchGeneric(instr, branch); | 1412 EmitBranchGeneric(instr, branch); |
1413 } | 1413 } |
1414 | 1414 |
1415 | 1415 |
1416 template<class InstrType> | 1416 template<class InstrType> |
1417 void LCodeGen::EmitCompareAndBranch(InstrType instr, | 1417 void LCodeGen::EmitCompareAndBranch(InstrType instr, |
1418 Condition condition, | 1418 Condition condition, |
1419 const Register& lhs, | 1419 const Register& lhs, |
1420 const Operand& rhs) { | 1420 const Operand& rhs) { |
1421 ASSERT((condition != al) && (condition != nv)); | 1421 DCHECK((condition != al) && (condition != nv)); |
1422 CompareAndBranch branch(this, condition, lhs, rhs); | 1422 CompareAndBranch branch(this, condition, lhs, rhs); |
1423 EmitBranchGeneric(instr, branch); | 1423 EmitBranchGeneric(instr, branch); |
1424 } | 1424 } |
1425 | 1425 |
1426 | 1426 |
1427 template<class InstrType> | 1427 template<class InstrType> |
1428 void LCodeGen::EmitTestAndBranch(InstrType instr, | 1428 void LCodeGen::EmitTestAndBranch(InstrType instr, |
1429 Condition condition, | 1429 Condition condition, |
1430 const Register& value, | 1430 const Register& value, |
1431 uint64_t mask) { | 1431 uint64_t mask) { |
1432 ASSERT((condition != al) && (condition != nv)); | 1432 DCHECK((condition != al) && (condition != nv)); |
1433 TestAndBranch branch(this, condition, value, mask); | 1433 TestAndBranch branch(this, condition, value, mask); |
1434 EmitBranchGeneric(instr, branch); | 1434 EmitBranchGeneric(instr, branch); |
1435 } | 1435 } |
1436 | 1436 |
1437 | 1437 |
1438 template<class InstrType> | 1438 template<class InstrType> |
1439 void LCodeGen::EmitBranchIfNonZeroNumber(InstrType instr, | 1439 void LCodeGen::EmitBranchIfNonZeroNumber(InstrType instr, |
1440 const FPRegister& value, | 1440 const FPRegister& value, |
1441 const FPRegister& scratch) { | 1441 const FPRegister& scratch) { |
1442 BranchIfNonZeroNumber branch(this, value, scratch); | 1442 BranchIfNonZeroNumber branch(this, value, scratch); |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1509 } | 1509 } |
1510 | 1510 |
1511 | 1511 |
1512 void LCodeGen::DoAddE(LAddE* instr) { | 1512 void LCodeGen::DoAddE(LAddE* instr) { |
1513 Register result = ToRegister(instr->result()); | 1513 Register result = ToRegister(instr->result()); |
1514 Register left = ToRegister(instr->left()); | 1514 Register left = ToRegister(instr->left()); |
1515 Operand right = (instr->right()->IsConstantOperand()) | 1515 Operand right = (instr->right()->IsConstantOperand()) |
1516 ? ToInteger32(LConstantOperand::cast(instr->right())) | 1516 ? ToInteger32(LConstantOperand::cast(instr->right())) |
1517 : Operand(ToRegister32(instr->right()), SXTW); | 1517 : Operand(ToRegister32(instr->right()), SXTW); |
1518 | 1518 |
1519 ASSERT(!instr->hydrogen()->CheckFlag(HValue::kCanOverflow)); | 1519 DCHECK(!instr->hydrogen()->CheckFlag(HValue::kCanOverflow)); |
1520 __ Add(result, left, right); | 1520 __ Add(result, left, right); |
1521 } | 1521 } |
1522 | 1522 |
1523 | 1523 |
1524 void LCodeGen::DoAddI(LAddI* instr) { | 1524 void LCodeGen::DoAddI(LAddI* instr) { |
1525 bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow); | 1525 bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow); |
1526 Register result = ToRegister32(instr->result()); | 1526 Register result = ToRegister32(instr->result()); |
1527 Register left = ToRegister32(instr->left()); | 1527 Register left = ToRegister32(instr->left()); |
1528 Operand right = ToShiftedRightOperand32I(instr->right(), instr); | 1528 Operand right = ToShiftedRightOperand32I(instr->right(), instr); |
1529 | 1529 |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1567 Register temp1 = ToRegister(instr->temp1()); | 1567 Register temp1 = ToRegister(instr->temp1()); |
1568 Register temp2 = ToRegister(instr->temp2()); | 1568 Register temp2 = ToRegister(instr->temp2()); |
1569 | 1569 |
1570 // Allocate memory for the object. | 1570 // Allocate memory for the object. |
1571 AllocationFlags flags = TAG_OBJECT; | 1571 AllocationFlags flags = TAG_OBJECT; |
1572 if (instr->hydrogen()->MustAllocateDoubleAligned()) { | 1572 if (instr->hydrogen()->MustAllocateDoubleAligned()) { |
1573 flags = static_cast<AllocationFlags>(flags | DOUBLE_ALIGNMENT); | 1573 flags = static_cast<AllocationFlags>(flags | DOUBLE_ALIGNMENT); |
1574 } | 1574 } |
1575 | 1575 |
1576 if (instr->hydrogen()->IsOldPointerSpaceAllocation()) { | 1576 if (instr->hydrogen()->IsOldPointerSpaceAllocation()) { |
1577 ASSERT(!instr->hydrogen()->IsOldDataSpaceAllocation()); | 1577 DCHECK(!instr->hydrogen()->IsOldDataSpaceAllocation()); |
1578 ASSERT(!instr->hydrogen()->IsNewSpaceAllocation()); | 1578 DCHECK(!instr->hydrogen()->IsNewSpaceAllocation()); |
1579 flags = static_cast<AllocationFlags>(flags | PRETENURE_OLD_POINTER_SPACE); | 1579 flags = static_cast<AllocationFlags>(flags | PRETENURE_OLD_POINTER_SPACE); |
1580 } else if (instr->hydrogen()->IsOldDataSpaceAllocation()) { | 1580 } else if (instr->hydrogen()->IsOldDataSpaceAllocation()) { |
1581 ASSERT(!instr->hydrogen()->IsNewSpaceAllocation()); | 1581 DCHECK(!instr->hydrogen()->IsNewSpaceAllocation()); |
1582 flags = static_cast<AllocationFlags>(flags | PRETENURE_OLD_DATA_SPACE); | 1582 flags = static_cast<AllocationFlags>(flags | PRETENURE_OLD_DATA_SPACE); |
1583 } | 1583 } |
1584 | 1584 |
1585 if (instr->size()->IsConstantOperand()) { | 1585 if (instr->size()->IsConstantOperand()) { |
1586 int32_t size = ToInteger32(LConstantOperand::cast(instr->size())); | 1586 int32_t size = ToInteger32(LConstantOperand::cast(instr->size())); |
1587 if (size <= Page::kMaxRegularHeapObjectSize) { | 1587 if (size <= Page::kMaxRegularHeapObjectSize) { |
1588 __ Allocate(size, result, temp1, temp2, deferred->entry(), flags); | 1588 __ Allocate(size, result, temp1, temp2, deferred->entry(), flags); |
1589 } else { | 1589 } else { |
1590 __ B(deferred->entry()); | 1590 __ B(deferred->entry()); |
1591 } | 1591 } |
(...skipping 14 matching lines...) Expand all Loading... |
1606 int32_t size = ToInteger32(LConstantOperand::cast(instr->size())); | 1606 int32_t size = ToInteger32(LConstantOperand::cast(instr->size())); |
1607 __ Mov(filler_count, size / kPointerSize); | 1607 __ Mov(filler_count, size / kPointerSize); |
1608 } else { | 1608 } else { |
1609 __ Lsr(filler_count.W(), ToRegister32(instr->size()), kPointerSizeLog2); | 1609 __ Lsr(filler_count.W(), ToRegister32(instr->size()), kPointerSizeLog2); |
1610 } | 1610 } |
1611 | 1611 |
1612 __ Sub(untagged_result, result, kHeapObjectTag); | 1612 __ Sub(untagged_result, result, kHeapObjectTag); |
1613 __ Mov(filler, Operand(isolate()->factory()->one_pointer_filler_map())); | 1613 __ Mov(filler, Operand(isolate()->factory()->one_pointer_filler_map())); |
1614 __ FillFields(untagged_result, filler_count, filler); | 1614 __ FillFields(untagged_result, filler_count, filler); |
1615 } else { | 1615 } else { |
1616 ASSERT(instr->temp3() == NULL); | 1616 DCHECK(instr->temp3() == NULL); |
1617 } | 1617 } |
1618 } | 1618 } |
1619 | 1619 |
1620 | 1620 |
1621 void LCodeGen::DoDeferredAllocate(LAllocate* instr) { | 1621 void LCodeGen::DoDeferredAllocate(LAllocate* instr) { |
1622 // TODO(3095996): Get rid of this. For now, we need to make the | 1622 // TODO(3095996): Get rid of this. For now, we need to make the |
1623 // result register contain a valid pointer because it is already | 1623 // result register contain a valid pointer because it is already |
1624 // contained in the register pointer map. | 1624 // contained in the register pointer map. |
1625 __ Mov(ToRegister(instr->result()), Smi::FromInt(0)); | 1625 __ Mov(ToRegister(instr->result()), Smi::FromInt(0)); |
1626 | 1626 |
1627 PushSafepointRegistersScope scope(this); | 1627 PushSafepointRegistersScope scope(this); |
1628 // We're in a SafepointRegistersScope so we can use any scratch registers. | 1628 // We're in a SafepointRegistersScope so we can use any scratch registers. |
1629 Register size = x0; | 1629 Register size = x0; |
1630 if (instr->size()->IsConstantOperand()) { | 1630 if (instr->size()->IsConstantOperand()) { |
1631 __ Mov(size, ToSmi(LConstantOperand::cast(instr->size()))); | 1631 __ Mov(size, ToSmi(LConstantOperand::cast(instr->size()))); |
1632 } else { | 1632 } else { |
1633 __ SmiTag(size, ToRegister32(instr->size()).X()); | 1633 __ SmiTag(size, ToRegister32(instr->size()).X()); |
1634 } | 1634 } |
1635 int flags = AllocateDoubleAlignFlag::encode( | 1635 int flags = AllocateDoubleAlignFlag::encode( |
1636 instr->hydrogen()->MustAllocateDoubleAligned()); | 1636 instr->hydrogen()->MustAllocateDoubleAligned()); |
1637 if (instr->hydrogen()->IsOldPointerSpaceAllocation()) { | 1637 if (instr->hydrogen()->IsOldPointerSpaceAllocation()) { |
1638 ASSERT(!instr->hydrogen()->IsOldDataSpaceAllocation()); | 1638 DCHECK(!instr->hydrogen()->IsOldDataSpaceAllocation()); |
1639 ASSERT(!instr->hydrogen()->IsNewSpaceAllocation()); | 1639 DCHECK(!instr->hydrogen()->IsNewSpaceAllocation()); |
1640 flags = AllocateTargetSpace::update(flags, OLD_POINTER_SPACE); | 1640 flags = AllocateTargetSpace::update(flags, OLD_POINTER_SPACE); |
1641 } else if (instr->hydrogen()->IsOldDataSpaceAllocation()) { | 1641 } else if (instr->hydrogen()->IsOldDataSpaceAllocation()) { |
1642 ASSERT(!instr->hydrogen()->IsNewSpaceAllocation()); | 1642 DCHECK(!instr->hydrogen()->IsNewSpaceAllocation()); |
1643 flags = AllocateTargetSpace::update(flags, OLD_DATA_SPACE); | 1643 flags = AllocateTargetSpace::update(flags, OLD_DATA_SPACE); |
1644 } else { | 1644 } else { |
1645 flags = AllocateTargetSpace::update(flags, NEW_SPACE); | 1645 flags = AllocateTargetSpace::update(flags, NEW_SPACE); |
1646 } | 1646 } |
1647 __ Mov(x10, Smi::FromInt(flags)); | 1647 __ Mov(x10, Smi::FromInt(flags)); |
1648 __ Push(size, x10); | 1648 __ Push(size, x10); |
1649 | 1649 |
1650 CallRuntimeFromDeferred( | 1650 CallRuntimeFromDeferred( |
1651 Runtime::kAllocateInTargetSpace, 2, instr, instr->context()); | 1651 Runtime::kAllocateInTargetSpace, 2, instr, instr->context()); |
1652 __ StoreToSafepointRegisterSlot(x0, ToRegister(instr->result())); | 1652 __ StoreToSafepointRegisterSlot(x0, ToRegister(instr->result())); |
1653 } | 1653 } |
1654 | 1654 |
1655 | 1655 |
1656 void LCodeGen::DoApplyArguments(LApplyArguments* instr) { | 1656 void LCodeGen::DoApplyArguments(LApplyArguments* instr) { |
1657 Register receiver = ToRegister(instr->receiver()); | 1657 Register receiver = ToRegister(instr->receiver()); |
1658 Register function = ToRegister(instr->function()); | 1658 Register function = ToRegister(instr->function()); |
1659 Register length = ToRegister32(instr->length()); | 1659 Register length = ToRegister32(instr->length()); |
1660 | 1660 |
1661 Register elements = ToRegister(instr->elements()); | 1661 Register elements = ToRegister(instr->elements()); |
1662 Register scratch = x5; | 1662 Register scratch = x5; |
1663 ASSERT(receiver.Is(x0)); // Used for parameter count. | 1663 DCHECK(receiver.Is(x0)); // Used for parameter count. |
1664 ASSERT(function.Is(x1)); // Required by InvokeFunction. | 1664 DCHECK(function.Is(x1)); // Required by InvokeFunction. |
1665 ASSERT(ToRegister(instr->result()).Is(x0)); | 1665 DCHECK(ToRegister(instr->result()).Is(x0)); |
1666 ASSERT(instr->IsMarkedAsCall()); | 1666 DCHECK(instr->IsMarkedAsCall()); |
1667 | 1667 |
1668 // Copy the arguments to this function possibly from the | 1668 // Copy the arguments to this function possibly from the |
1669 // adaptor frame below it. | 1669 // adaptor frame below it. |
1670 const uint32_t kArgumentsLimit = 1 * KB; | 1670 const uint32_t kArgumentsLimit = 1 * KB; |
1671 __ Cmp(length, kArgumentsLimit); | 1671 __ Cmp(length, kArgumentsLimit); |
1672 DeoptimizeIf(hi, instr->environment()); | 1672 DeoptimizeIf(hi, instr->environment()); |
1673 | 1673 |
1674 // Push the receiver and use the register to keep the original | 1674 // Push the receiver and use the register to keep the original |
1675 // number of arguments. | 1675 // number of arguments. |
1676 __ Push(receiver); | 1676 __ Push(receiver); |
1677 Register argc = receiver; | 1677 Register argc = receiver; |
1678 receiver = NoReg; | 1678 receiver = NoReg; |
1679 __ Sxtw(argc, length); | 1679 __ Sxtw(argc, length); |
1680 // The arguments are at a one pointer size offset from elements. | 1680 // The arguments are at a one pointer size offset from elements. |
1681 __ Add(elements, elements, 1 * kPointerSize); | 1681 __ Add(elements, elements, 1 * kPointerSize); |
1682 | 1682 |
1683 // Loop through the arguments pushing them onto the execution | 1683 // Loop through the arguments pushing them onto the execution |
1684 // stack. | 1684 // stack. |
1685 Label invoke, loop; | 1685 Label invoke, loop; |
1686 // length is a small non-negative integer, due to the test above. | 1686 // length is a small non-negative integer, due to the test above. |
1687 __ Cbz(length, &invoke); | 1687 __ Cbz(length, &invoke); |
1688 __ Bind(&loop); | 1688 __ Bind(&loop); |
1689 __ Ldr(scratch, MemOperand(elements, length, SXTW, kPointerSizeLog2)); | 1689 __ Ldr(scratch, MemOperand(elements, length, SXTW, kPointerSizeLog2)); |
1690 __ Push(scratch); | 1690 __ Push(scratch); |
1691 __ Subs(length, length, 1); | 1691 __ Subs(length, length, 1); |
1692 __ B(ne, &loop); | 1692 __ B(ne, &loop); |
1693 | 1693 |
1694 __ Bind(&invoke); | 1694 __ Bind(&invoke); |
1695 ASSERT(instr->HasPointerMap()); | 1695 DCHECK(instr->HasPointerMap()); |
1696 LPointerMap* pointers = instr->pointer_map(); | 1696 LPointerMap* pointers = instr->pointer_map(); |
1697 SafepointGenerator safepoint_generator(this, pointers, Safepoint::kLazyDeopt); | 1697 SafepointGenerator safepoint_generator(this, pointers, Safepoint::kLazyDeopt); |
1698 // The number of arguments is stored in argc (receiver) which is x0, as | 1698 // The number of arguments is stored in argc (receiver) which is x0, as |
1699 // expected by InvokeFunction. | 1699 // expected by InvokeFunction. |
1700 ParameterCount actual(argc); | 1700 ParameterCount actual(argc); |
1701 __ InvokeFunction(function, actual, CALL_FUNCTION, safepoint_generator); | 1701 __ InvokeFunction(function, actual, CALL_FUNCTION, safepoint_generator); |
1702 } | 1702 } |
1703 | 1703 |
1704 | 1704 |
1705 void LCodeGen::DoArgumentsElements(LArgumentsElements* instr) { | 1705 void LCodeGen::DoArgumentsElements(LArgumentsElements* instr) { |
1706 // We push some arguments and they will be pop in an other block. We can't | 1706 // We push some arguments and they will be pop in an other block. We can't |
1707 // trust that jssp references the end of the stack slots until the end of | 1707 // trust that jssp references the end of the stack slots until the end of |
1708 // the function. | 1708 // the function. |
1709 inlined_arguments_ = true; | 1709 inlined_arguments_ = true; |
1710 Register result = ToRegister(instr->result()); | 1710 Register result = ToRegister(instr->result()); |
1711 | 1711 |
1712 if (instr->hydrogen()->from_inlined()) { | 1712 if (instr->hydrogen()->from_inlined()) { |
1713 // When we are inside an inlined function, the arguments are the last things | 1713 // When we are inside an inlined function, the arguments are the last things |
1714 // that have been pushed on the stack. Therefore the arguments array can be | 1714 // that have been pushed on the stack. Therefore the arguments array can be |
1715 // accessed directly from jssp. | 1715 // accessed directly from jssp. |
1716 // However in the normal case, it is accessed via fp but there are two words | 1716 // However in the normal case, it is accessed via fp but there are two words |
1717 // on the stack between fp and the arguments (the saved lr and fp) and the | 1717 // on the stack between fp and the arguments (the saved lr and fp) and the |
1718 // LAccessArgumentsAt implementation take that into account. | 1718 // LAccessArgumentsAt implementation take that into account. |
1719 // In the inlined case we need to subtract the size of 2 words to jssp to | 1719 // In the inlined case we need to subtract the size of 2 words to jssp to |
1720 // get a pointer which will work well with LAccessArgumentsAt. | 1720 // get a pointer which will work well with LAccessArgumentsAt. |
1721 ASSERT(masm()->StackPointer().Is(jssp)); | 1721 DCHECK(masm()->StackPointer().Is(jssp)); |
1722 __ Sub(result, jssp, 2 * kPointerSize); | 1722 __ Sub(result, jssp, 2 * kPointerSize); |
1723 } else { | 1723 } else { |
1724 ASSERT(instr->temp() != NULL); | 1724 DCHECK(instr->temp() != NULL); |
1725 Register previous_fp = ToRegister(instr->temp()); | 1725 Register previous_fp = ToRegister(instr->temp()); |
1726 | 1726 |
1727 __ Ldr(previous_fp, | 1727 __ Ldr(previous_fp, |
1728 MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); | 1728 MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); |
1729 __ Ldr(result, | 1729 __ Ldr(result, |
1730 MemOperand(previous_fp, StandardFrameConstants::kContextOffset)); | 1730 MemOperand(previous_fp, StandardFrameConstants::kContextOffset)); |
1731 __ Cmp(result, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); | 1731 __ Cmp(result, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); |
1732 __ Csel(result, fp, previous_fp, ne); | 1732 __ Csel(result, fp, previous_fp, ne); |
1733 } | 1733 } |
1734 } | 1734 } |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1768 case Token::MOD: { | 1768 case Token::MOD: { |
1769 // The ECMA-262 remainder operator is the remainder from a truncating | 1769 // The ECMA-262 remainder operator is the remainder from a truncating |
1770 // (round-towards-zero) division. Note that this differs from IEEE-754. | 1770 // (round-towards-zero) division. Note that this differs from IEEE-754. |
1771 // | 1771 // |
1772 // TODO(jbramley): See if it's possible to do this inline, rather than by | 1772 // TODO(jbramley): See if it's possible to do this inline, rather than by |
1773 // calling a helper function. With frintz (to produce the intermediate | 1773 // calling a helper function. With frintz (to produce the intermediate |
1774 // quotient) and fmsub (to calculate the remainder without loss of | 1774 // quotient) and fmsub (to calculate the remainder without loss of |
1775 // precision), it should be possible. However, we would need support for | 1775 // precision), it should be possible. However, we would need support for |
1776 // fdiv in round-towards-zero mode, and the ARM64 simulator doesn't | 1776 // fdiv in round-towards-zero mode, and the ARM64 simulator doesn't |
1777 // support that yet. | 1777 // support that yet. |
1778 ASSERT(left.Is(d0)); | 1778 DCHECK(left.Is(d0)); |
1779 ASSERT(right.Is(d1)); | 1779 DCHECK(right.Is(d1)); |
1780 __ CallCFunction( | 1780 __ CallCFunction( |
1781 ExternalReference::mod_two_doubles_operation(isolate()), | 1781 ExternalReference::mod_two_doubles_operation(isolate()), |
1782 0, 2); | 1782 0, 2); |
1783 ASSERT(result.Is(d0)); | 1783 DCHECK(result.Is(d0)); |
1784 break; | 1784 break; |
1785 } | 1785 } |
1786 default: | 1786 default: |
1787 UNREACHABLE(); | 1787 UNREACHABLE(); |
1788 break; | 1788 break; |
1789 } | 1789 } |
1790 } | 1790 } |
1791 | 1791 |
1792 | 1792 |
1793 void LCodeGen::DoArithmeticT(LArithmeticT* instr) { | 1793 void LCodeGen::DoArithmeticT(LArithmeticT* instr) { |
1794 ASSERT(ToRegister(instr->context()).is(cp)); | 1794 DCHECK(ToRegister(instr->context()).is(cp)); |
1795 ASSERT(ToRegister(instr->left()).is(x1)); | 1795 DCHECK(ToRegister(instr->left()).is(x1)); |
1796 ASSERT(ToRegister(instr->right()).is(x0)); | 1796 DCHECK(ToRegister(instr->right()).is(x0)); |
1797 ASSERT(ToRegister(instr->result()).is(x0)); | 1797 DCHECK(ToRegister(instr->result()).is(x0)); |
1798 | 1798 |
1799 BinaryOpICStub stub(isolate(), instr->op(), NO_OVERWRITE); | 1799 BinaryOpICStub stub(isolate(), instr->op(), NO_OVERWRITE); |
1800 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); | 1800 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
1801 } | 1801 } |
1802 | 1802 |
1803 | 1803 |
1804 void LCodeGen::DoBitI(LBitI* instr) { | 1804 void LCodeGen::DoBitI(LBitI* instr) { |
1805 Register result = ToRegister32(instr->result()); | 1805 Register result = ToRegister32(instr->result()); |
1806 Register left = ToRegister32(instr->left()); | 1806 Register left = ToRegister32(instr->left()); |
1807 Operand right = ToShiftedRightOperand32U(instr->right(), instr); | 1807 Operand right = ToShiftedRightOperand32U(instr->right(), instr); |
(...skipping 20 matching lines...) Expand all Loading... |
1828 case Token::BIT_XOR: __ Eor(result, left, right); break; | 1828 case Token::BIT_XOR: __ Eor(result, left, right); break; |
1829 default: | 1829 default: |
1830 UNREACHABLE(); | 1830 UNREACHABLE(); |
1831 break; | 1831 break; |
1832 } | 1832 } |
1833 } | 1833 } |
1834 | 1834 |
1835 | 1835 |
1836 void LCodeGen::DoBoundsCheck(LBoundsCheck *instr) { | 1836 void LCodeGen::DoBoundsCheck(LBoundsCheck *instr) { |
1837 Condition cond = instr->hydrogen()->allow_equality() ? hi : hs; | 1837 Condition cond = instr->hydrogen()->allow_equality() ? hi : hs; |
1838 ASSERT(instr->hydrogen()->index()->representation().IsInteger32()); | 1838 DCHECK(instr->hydrogen()->index()->representation().IsInteger32()); |
1839 ASSERT(instr->hydrogen()->length()->representation().IsInteger32()); | 1839 DCHECK(instr->hydrogen()->length()->representation().IsInteger32()); |
1840 if (instr->index()->IsConstantOperand()) { | 1840 if (instr->index()->IsConstantOperand()) { |
1841 Operand index = ToOperand32I(instr->index()); | 1841 Operand index = ToOperand32I(instr->index()); |
1842 Register length = ToRegister32(instr->length()); | 1842 Register length = ToRegister32(instr->length()); |
1843 __ Cmp(length, index); | 1843 __ Cmp(length, index); |
1844 cond = CommuteCondition(cond); | 1844 cond = CommuteCondition(cond); |
1845 } else { | 1845 } else { |
1846 Register index = ToRegister32(instr->index()); | 1846 Register index = ToRegister32(instr->index()); |
1847 Operand length = ToOperand32I(instr->length()); | 1847 Operand length = ToOperand32I(instr->length()); |
1848 __ Cmp(index, length); | 1848 __ Cmp(index, length); |
1849 } | 1849 } |
1850 if (FLAG_debug_code && instr->hydrogen()->skip_check()) { | 1850 if (FLAG_debug_code && instr->hydrogen()->skip_check()) { |
1851 __ Assert(NegateCondition(cond), kEliminatedBoundsCheckFailed); | 1851 __ Assert(NegateCondition(cond), kEliminatedBoundsCheckFailed); |
1852 } else { | 1852 } else { |
1853 DeoptimizeIf(cond, instr->environment()); | 1853 DeoptimizeIf(cond, instr->environment()); |
1854 } | 1854 } |
1855 } | 1855 } |
1856 | 1856 |
1857 | 1857 |
1858 void LCodeGen::DoBranch(LBranch* instr) { | 1858 void LCodeGen::DoBranch(LBranch* instr) { |
1859 Representation r = instr->hydrogen()->value()->representation(); | 1859 Representation r = instr->hydrogen()->value()->representation(); |
1860 Label* true_label = instr->TrueLabel(chunk_); | 1860 Label* true_label = instr->TrueLabel(chunk_); |
1861 Label* false_label = instr->FalseLabel(chunk_); | 1861 Label* false_label = instr->FalseLabel(chunk_); |
1862 | 1862 |
1863 if (r.IsInteger32()) { | 1863 if (r.IsInteger32()) { |
1864 ASSERT(!info()->IsStub()); | 1864 DCHECK(!info()->IsStub()); |
1865 EmitCompareAndBranch(instr, ne, ToRegister32(instr->value()), 0); | 1865 EmitCompareAndBranch(instr, ne, ToRegister32(instr->value()), 0); |
1866 } else if (r.IsSmi()) { | 1866 } else if (r.IsSmi()) { |
1867 ASSERT(!info()->IsStub()); | 1867 DCHECK(!info()->IsStub()); |
1868 STATIC_ASSERT(kSmiTag == 0); | 1868 STATIC_ASSERT(kSmiTag == 0); |
1869 EmitCompareAndBranch(instr, ne, ToRegister(instr->value()), 0); | 1869 EmitCompareAndBranch(instr, ne, ToRegister(instr->value()), 0); |
1870 } else if (r.IsDouble()) { | 1870 } else if (r.IsDouble()) { |
1871 DoubleRegister value = ToDoubleRegister(instr->value()); | 1871 DoubleRegister value = ToDoubleRegister(instr->value()); |
1872 // Test the double value. Zero and NaN are false. | 1872 // Test the double value. Zero and NaN are false. |
1873 EmitBranchIfNonZeroNumber(instr, value, double_scratch()); | 1873 EmitBranchIfNonZeroNumber(instr, value, double_scratch()); |
1874 } else { | 1874 } else { |
1875 ASSERT(r.IsTagged()); | 1875 DCHECK(r.IsTagged()); |
1876 Register value = ToRegister(instr->value()); | 1876 Register value = ToRegister(instr->value()); |
1877 HType type = instr->hydrogen()->value()->type(); | 1877 HType type = instr->hydrogen()->value()->type(); |
1878 | 1878 |
1879 if (type.IsBoolean()) { | 1879 if (type.IsBoolean()) { |
1880 ASSERT(!info()->IsStub()); | 1880 DCHECK(!info()->IsStub()); |
1881 __ CompareRoot(value, Heap::kTrueValueRootIndex); | 1881 __ CompareRoot(value, Heap::kTrueValueRootIndex); |
1882 EmitBranch(instr, eq); | 1882 EmitBranch(instr, eq); |
1883 } else if (type.IsSmi()) { | 1883 } else if (type.IsSmi()) { |
1884 ASSERT(!info()->IsStub()); | 1884 DCHECK(!info()->IsStub()); |
1885 EmitCompareAndBranch(instr, ne, value, Smi::FromInt(0)); | 1885 EmitCompareAndBranch(instr, ne, value, Smi::FromInt(0)); |
1886 } else if (type.IsJSArray()) { | 1886 } else if (type.IsJSArray()) { |
1887 ASSERT(!info()->IsStub()); | 1887 DCHECK(!info()->IsStub()); |
1888 EmitGoto(instr->TrueDestination(chunk())); | 1888 EmitGoto(instr->TrueDestination(chunk())); |
1889 } else if (type.IsHeapNumber()) { | 1889 } else if (type.IsHeapNumber()) { |
1890 ASSERT(!info()->IsStub()); | 1890 DCHECK(!info()->IsStub()); |
1891 __ Ldr(double_scratch(), FieldMemOperand(value, | 1891 __ Ldr(double_scratch(), FieldMemOperand(value, |
1892 HeapNumber::kValueOffset)); | 1892 HeapNumber::kValueOffset)); |
1893 // Test the double value. Zero and NaN are false. | 1893 // Test the double value. Zero and NaN are false. |
1894 EmitBranchIfNonZeroNumber(instr, double_scratch(), double_scratch()); | 1894 EmitBranchIfNonZeroNumber(instr, double_scratch(), double_scratch()); |
1895 } else if (type.IsString()) { | 1895 } else if (type.IsString()) { |
1896 ASSERT(!info()->IsStub()); | 1896 DCHECK(!info()->IsStub()); |
1897 Register temp = ToRegister(instr->temp1()); | 1897 Register temp = ToRegister(instr->temp1()); |
1898 __ Ldr(temp, FieldMemOperand(value, String::kLengthOffset)); | 1898 __ Ldr(temp, FieldMemOperand(value, String::kLengthOffset)); |
1899 EmitCompareAndBranch(instr, ne, temp, 0); | 1899 EmitCompareAndBranch(instr, ne, temp, 0); |
1900 } else { | 1900 } else { |
1901 ToBooleanStub::Types expected = instr->hydrogen()->expected_input_types(); | 1901 ToBooleanStub::Types expected = instr->hydrogen()->expected_input_types(); |
1902 // Avoid deopts in the case where we've never executed this path before. | 1902 // Avoid deopts in the case where we've never executed this path before. |
1903 if (expected.IsEmpty()) expected = ToBooleanStub::Types::Generic(); | 1903 if (expected.IsEmpty()) expected = ToBooleanStub::Types::Generic(); |
1904 | 1904 |
1905 if (expected.Contains(ToBooleanStub::UNDEFINED)) { | 1905 if (expected.Contains(ToBooleanStub::UNDEFINED)) { |
1906 // undefined -> false. | 1906 // undefined -> false. |
(...skipping 10 matching lines...) Expand all Loading... |
1917 } | 1917 } |
1918 | 1918 |
1919 if (expected.Contains(ToBooleanStub::NULL_TYPE)) { | 1919 if (expected.Contains(ToBooleanStub::NULL_TYPE)) { |
1920 // 'null' -> false. | 1920 // 'null' -> false. |
1921 __ JumpIfRoot( | 1921 __ JumpIfRoot( |
1922 value, Heap::kNullValueRootIndex, false_label); | 1922 value, Heap::kNullValueRootIndex, false_label); |
1923 } | 1923 } |
1924 | 1924 |
1925 if (expected.Contains(ToBooleanStub::SMI)) { | 1925 if (expected.Contains(ToBooleanStub::SMI)) { |
1926 // Smis: 0 -> false, all other -> true. | 1926 // Smis: 0 -> false, all other -> true. |
1927 ASSERT(Smi::FromInt(0) == 0); | 1927 DCHECK(Smi::FromInt(0) == 0); |
1928 __ Cbz(value, false_label); | 1928 __ Cbz(value, false_label); |
1929 __ JumpIfSmi(value, true_label); | 1929 __ JumpIfSmi(value, true_label); |
1930 } else if (expected.NeedsMap()) { | 1930 } else if (expected.NeedsMap()) { |
1931 // If we need a map later and have a smi, deopt. | 1931 // If we need a map later and have a smi, deopt. |
1932 DeoptimizeIfSmi(value, instr->environment()); | 1932 DeoptimizeIfSmi(value, instr->environment()); |
1933 } | 1933 } |
1934 | 1934 |
1935 Register map = NoReg; | 1935 Register map = NoReg; |
1936 Register scratch = NoReg; | 1936 Register scratch = NoReg; |
1937 | 1937 |
1938 if (expected.NeedsMap()) { | 1938 if (expected.NeedsMap()) { |
1939 ASSERT((instr->temp1() != NULL) && (instr->temp2() != NULL)); | 1939 DCHECK((instr->temp1() != NULL) && (instr->temp2() != NULL)); |
1940 map = ToRegister(instr->temp1()); | 1940 map = ToRegister(instr->temp1()); |
1941 scratch = ToRegister(instr->temp2()); | 1941 scratch = ToRegister(instr->temp2()); |
1942 | 1942 |
1943 __ Ldr(map, FieldMemOperand(value, HeapObject::kMapOffset)); | 1943 __ Ldr(map, FieldMemOperand(value, HeapObject::kMapOffset)); |
1944 | 1944 |
1945 if (expected.CanBeUndetectable()) { | 1945 if (expected.CanBeUndetectable()) { |
1946 // Undetectable -> false. | 1946 // Undetectable -> false. |
1947 __ Ldrb(scratch, FieldMemOperand(map, Map::kBitFieldOffset)); | 1947 __ Ldrb(scratch, FieldMemOperand(map, Map::kBitFieldOffset)); |
1948 __ TestAndBranchIfAnySet( | 1948 __ TestAndBranchIfAnySet( |
1949 scratch, 1 << Map::kIsUndetectable, false_label); | 1949 scratch, 1 << Map::kIsUndetectable, false_label); |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2001 int formal_parameter_count, | 2001 int formal_parameter_count, |
2002 int arity, | 2002 int arity, |
2003 LInstruction* instr, | 2003 LInstruction* instr, |
2004 Register function_reg) { | 2004 Register function_reg) { |
2005 bool dont_adapt_arguments = | 2005 bool dont_adapt_arguments = |
2006 formal_parameter_count == SharedFunctionInfo::kDontAdaptArgumentsSentinel; | 2006 formal_parameter_count == SharedFunctionInfo::kDontAdaptArgumentsSentinel; |
2007 bool can_invoke_directly = | 2007 bool can_invoke_directly = |
2008 dont_adapt_arguments || formal_parameter_count == arity; | 2008 dont_adapt_arguments || formal_parameter_count == arity; |
2009 | 2009 |
2010 // The function interface relies on the following register assignments. | 2010 // The function interface relies on the following register assignments. |
2011 ASSERT(function_reg.Is(x1) || function_reg.IsNone()); | 2011 DCHECK(function_reg.Is(x1) || function_reg.IsNone()); |
2012 Register arity_reg = x0; | 2012 Register arity_reg = x0; |
2013 | 2013 |
2014 LPointerMap* pointers = instr->pointer_map(); | 2014 LPointerMap* pointers = instr->pointer_map(); |
2015 | 2015 |
2016 // If necessary, load the function object. | 2016 // If necessary, load the function object. |
2017 if (function_reg.IsNone()) { | 2017 if (function_reg.IsNone()) { |
2018 function_reg = x1; | 2018 function_reg = x1; |
2019 __ LoadObject(function_reg, function); | 2019 __ LoadObject(function_reg, function); |
2020 } | 2020 } |
2021 | 2021 |
(...skipping 24 matching lines...) Expand all Loading... |
2046 } else { | 2046 } else { |
2047 SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt); | 2047 SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt); |
2048 ParameterCount count(arity); | 2048 ParameterCount count(arity); |
2049 ParameterCount expected(formal_parameter_count); | 2049 ParameterCount expected(formal_parameter_count); |
2050 __ InvokeFunction(function_reg, expected, count, CALL_FUNCTION, generator); | 2050 __ InvokeFunction(function_reg, expected, count, CALL_FUNCTION, generator); |
2051 } | 2051 } |
2052 } | 2052 } |
2053 | 2053 |
2054 | 2054 |
2055 void LCodeGen::DoCallWithDescriptor(LCallWithDescriptor* instr) { | 2055 void LCodeGen::DoCallWithDescriptor(LCallWithDescriptor* instr) { |
2056 ASSERT(instr->IsMarkedAsCall()); | 2056 DCHECK(instr->IsMarkedAsCall()); |
2057 ASSERT(ToRegister(instr->result()).Is(x0)); | 2057 DCHECK(ToRegister(instr->result()).Is(x0)); |
2058 | 2058 |
2059 LPointerMap* pointers = instr->pointer_map(); | 2059 LPointerMap* pointers = instr->pointer_map(); |
2060 SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt); | 2060 SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt); |
2061 | 2061 |
2062 if (instr->target()->IsConstantOperand()) { | 2062 if (instr->target()->IsConstantOperand()) { |
2063 LConstantOperand* target = LConstantOperand::cast(instr->target()); | 2063 LConstantOperand* target = LConstantOperand::cast(instr->target()); |
2064 Handle<Code> code = Handle<Code>::cast(ToHandle(target)); | 2064 Handle<Code> code = Handle<Code>::cast(ToHandle(target)); |
2065 generator.BeforeCall(__ CallSize(code, RelocInfo::CODE_TARGET)); | 2065 generator.BeforeCall(__ CallSize(code, RelocInfo::CODE_TARGET)); |
2066 // TODO(all): on ARM we use a call descriptor to specify a storage mode | 2066 // TODO(all): on ARM we use a call descriptor to specify a storage mode |
2067 // but on ARM64 we only have one storage mode so it isn't necessary. Check | 2067 // but on ARM64 we only have one storage mode so it isn't necessary. Check |
2068 // this understanding is correct. | 2068 // this understanding is correct. |
2069 __ Call(code, RelocInfo::CODE_TARGET, TypeFeedbackId::None()); | 2069 __ Call(code, RelocInfo::CODE_TARGET, TypeFeedbackId::None()); |
2070 } else { | 2070 } else { |
2071 ASSERT(instr->target()->IsRegister()); | 2071 DCHECK(instr->target()->IsRegister()); |
2072 Register target = ToRegister(instr->target()); | 2072 Register target = ToRegister(instr->target()); |
2073 generator.BeforeCall(__ CallSize(target)); | 2073 generator.BeforeCall(__ CallSize(target)); |
2074 __ Add(target, target, Code::kHeaderSize - kHeapObjectTag); | 2074 __ Add(target, target, Code::kHeaderSize - kHeapObjectTag); |
2075 __ Call(target); | 2075 __ Call(target); |
2076 } | 2076 } |
2077 generator.AfterCall(); | 2077 generator.AfterCall(); |
2078 after_push_argument_ = false; | 2078 after_push_argument_ = false; |
2079 } | 2079 } |
2080 | 2080 |
2081 | 2081 |
2082 void LCodeGen::DoCallJSFunction(LCallJSFunction* instr) { | 2082 void LCodeGen::DoCallJSFunction(LCallJSFunction* instr) { |
2083 ASSERT(instr->IsMarkedAsCall()); | 2083 DCHECK(instr->IsMarkedAsCall()); |
2084 ASSERT(ToRegister(instr->function()).is(x1)); | 2084 DCHECK(ToRegister(instr->function()).is(x1)); |
2085 | 2085 |
2086 if (instr->hydrogen()->pass_argument_count()) { | 2086 if (instr->hydrogen()->pass_argument_count()) { |
2087 __ Mov(x0, Operand(instr->arity())); | 2087 __ Mov(x0, Operand(instr->arity())); |
2088 } | 2088 } |
2089 | 2089 |
2090 // Change context. | 2090 // Change context. |
2091 __ Ldr(cp, FieldMemOperand(x1, JSFunction::kContextOffset)); | 2091 __ Ldr(cp, FieldMemOperand(x1, JSFunction::kContextOffset)); |
2092 | 2092 |
2093 // Load the code entry address | 2093 // Load the code entry address |
2094 __ Ldr(x10, FieldMemOperand(x1, JSFunction::kCodeEntryOffset)); | 2094 __ Ldr(x10, FieldMemOperand(x1, JSFunction::kCodeEntryOffset)); |
2095 __ Call(x10); | 2095 __ Call(x10); |
2096 | 2096 |
2097 RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT); | 2097 RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT); |
2098 after_push_argument_ = false; | 2098 after_push_argument_ = false; |
2099 } | 2099 } |
2100 | 2100 |
2101 | 2101 |
2102 void LCodeGen::DoCallRuntime(LCallRuntime* instr) { | 2102 void LCodeGen::DoCallRuntime(LCallRuntime* instr) { |
2103 CallRuntime(instr->function(), instr->arity(), instr); | 2103 CallRuntime(instr->function(), instr->arity(), instr); |
2104 after_push_argument_ = false; | 2104 after_push_argument_ = false; |
2105 } | 2105 } |
2106 | 2106 |
2107 | 2107 |
2108 void LCodeGen::DoCallStub(LCallStub* instr) { | 2108 void LCodeGen::DoCallStub(LCallStub* instr) { |
2109 ASSERT(ToRegister(instr->context()).is(cp)); | 2109 DCHECK(ToRegister(instr->context()).is(cp)); |
2110 ASSERT(ToRegister(instr->result()).is(x0)); | 2110 DCHECK(ToRegister(instr->result()).is(x0)); |
2111 switch (instr->hydrogen()->major_key()) { | 2111 switch (instr->hydrogen()->major_key()) { |
2112 case CodeStub::RegExpExec: { | 2112 case CodeStub::RegExpExec: { |
2113 RegExpExecStub stub(isolate()); | 2113 RegExpExecStub stub(isolate()); |
2114 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); | 2114 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
2115 break; | 2115 break; |
2116 } | 2116 } |
2117 case CodeStub::SubString: { | 2117 case CodeStub::SubString: { |
2118 SubStringStub stub(isolate()); | 2118 SubStringStub stub(isolate()); |
2119 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); | 2119 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
2120 break; | 2120 break; |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2211 | 2211 |
2212 void LCodeGen::DoCheckNonSmi(LCheckNonSmi* instr) { | 2212 void LCodeGen::DoCheckNonSmi(LCheckNonSmi* instr) { |
2213 if (!instr->hydrogen()->value()->type().IsHeapObject()) { | 2213 if (!instr->hydrogen()->value()->type().IsHeapObject()) { |
2214 DeoptimizeIfSmi(ToRegister(instr->value()), instr->environment()); | 2214 DeoptimizeIfSmi(ToRegister(instr->value()), instr->environment()); |
2215 } | 2215 } |
2216 } | 2216 } |
2217 | 2217 |
2218 | 2218 |
2219 void LCodeGen::DoCheckSmi(LCheckSmi* instr) { | 2219 void LCodeGen::DoCheckSmi(LCheckSmi* instr) { |
2220 Register value = ToRegister(instr->value()); | 2220 Register value = ToRegister(instr->value()); |
2221 ASSERT(!instr->result() || ToRegister(instr->result()).Is(value)); | 2221 DCHECK(!instr->result() || ToRegister(instr->result()).Is(value)); |
2222 DeoptimizeIfNotSmi(value, instr->environment()); | 2222 DeoptimizeIfNotSmi(value, instr->environment()); |
2223 } | 2223 } |
2224 | 2224 |
2225 | 2225 |
2226 void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) { | 2226 void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) { |
2227 Register input = ToRegister(instr->value()); | 2227 Register input = ToRegister(instr->value()); |
2228 Register scratch = ToRegister(instr->temp()); | 2228 Register scratch = ToRegister(instr->temp()); |
2229 | 2229 |
2230 __ Ldr(scratch, FieldMemOperand(input, HeapObject::kMapOffset)); | 2230 __ Ldr(scratch, FieldMemOperand(input, HeapObject::kMapOffset)); |
2231 __ Ldrb(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset)); | 2231 __ Ldrb(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset)); |
(...skipping 14 matching lines...) Expand all Loading... |
2246 // to force a deopt. | 2246 // to force a deopt. |
2247 __ Ccmp(scratch, last, CFlag, hs); | 2247 __ Ccmp(scratch, last, CFlag, hs); |
2248 DeoptimizeIf(hi, instr->environment()); | 2248 DeoptimizeIf(hi, instr->environment()); |
2249 } | 2249 } |
2250 } else { | 2250 } else { |
2251 uint8_t mask; | 2251 uint8_t mask; |
2252 uint8_t tag; | 2252 uint8_t tag; |
2253 instr->hydrogen()->GetCheckMaskAndTag(&mask, &tag); | 2253 instr->hydrogen()->GetCheckMaskAndTag(&mask, &tag); |
2254 | 2254 |
2255 if (IsPowerOf2(mask)) { | 2255 if (IsPowerOf2(mask)) { |
2256 ASSERT((tag == 0) || (tag == mask)); | 2256 DCHECK((tag == 0) || (tag == mask)); |
2257 if (tag == 0) { | 2257 if (tag == 0) { |
2258 DeoptimizeIfBitSet(scratch, MaskToBit(mask), instr->environment()); | 2258 DeoptimizeIfBitSet(scratch, MaskToBit(mask), instr->environment()); |
2259 } else { | 2259 } else { |
2260 DeoptimizeIfBitClear(scratch, MaskToBit(mask), instr->environment()); | 2260 DeoptimizeIfBitClear(scratch, MaskToBit(mask), instr->environment()); |
2261 } | 2261 } |
2262 } else { | 2262 } else { |
2263 if (tag == 0) { | 2263 if (tag == 0) { |
2264 __ Tst(scratch, mask); | 2264 __ Tst(scratch, mask); |
2265 } else { | 2265 } else { |
2266 __ And(scratch, scratch, mask); | 2266 __ And(scratch, scratch, mask); |
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2402 // The name in the constructor is internalized because of the way the context | 2402 // The name in the constructor is internalized because of the way the context |
2403 // is booted. This routine isn't expected to work for random API-created | 2403 // is booted. This routine isn't expected to work for random API-created |
2404 // classes and it doesn't have to because you can't access it with natives | 2404 // classes and it doesn't have to because you can't access it with natives |
2405 // syntax. Since both sides are internalized it is sufficient to use an | 2405 // syntax. Since both sides are internalized it is sufficient to use an |
2406 // identity comparison. | 2406 // identity comparison. |
2407 EmitCompareAndBranch(instr, eq, scratch1, Operand(class_name)); | 2407 EmitCompareAndBranch(instr, eq, scratch1, Operand(class_name)); |
2408 } | 2408 } |
2409 | 2409 |
2410 | 2410 |
2411 void LCodeGen::DoCmpHoleAndBranchD(LCmpHoleAndBranchD* instr) { | 2411 void LCodeGen::DoCmpHoleAndBranchD(LCmpHoleAndBranchD* instr) { |
2412 ASSERT(instr->hydrogen()->representation().IsDouble()); | 2412 DCHECK(instr->hydrogen()->representation().IsDouble()); |
2413 FPRegister object = ToDoubleRegister(instr->object()); | 2413 FPRegister object = ToDoubleRegister(instr->object()); |
2414 Register temp = ToRegister(instr->temp()); | 2414 Register temp = ToRegister(instr->temp()); |
2415 | 2415 |
2416 // If we don't have a NaN, we don't have the hole, so branch now to avoid the | 2416 // If we don't have a NaN, we don't have the hole, so branch now to avoid the |
2417 // (relatively expensive) hole-NaN check. | 2417 // (relatively expensive) hole-NaN check. |
2418 __ Fcmp(object, object); | 2418 __ Fcmp(object, object); |
2419 __ B(vc, instr->FalseLabel(chunk_)); | 2419 __ B(vc, instr->FalseLabel(chunk_)); |
2420 | 2420 |
2421 // We have a NaN, but is it the hole? | 2421 // We have a NaN, but is it the hole? |
2422 __ Fmov(temp, object); | 2422 __ Fmov(temp, object); |
2423 EmitCompareAndBranch(instr, eq, temp, kHoleNanInt64); | 2423 EmitCompareAndBranch(instr, eq, temp, kHoleNanInt64); |
2424 } | 2424 } |
2425 | 2425 |
2426 | 2426 |
2427 void LCodeGen::DoCmpHoleAndBranchT(LCmpHoleAndBranchT* instr) { | 2427 void LCodeGen::DoCmpHoleAndBranchT(LCmpHoleAndBranchT* instr) { |
2428 ASSERT(instr->hydrogen()->representation().IsTagged()); | 2428 DCHECK(instr->hydrogen()->representation().IsTagged()); |
2429 Register object = ToRegister(instr->object()); | 2429 Register object = ToRegister(instr->object()); |
2430 | 2430 |
2431 EmitBranchIfRoot(instr, object, Heap::kTheHoleValueRootIndex); | 2431 EmitBranchIfRoot(instr, object, Heap::kTheHoleValueRootIndex); |
2432 } | 2432 } |
2433 | 2433 |
2434 | 2434 |
2435 void LCodeGen::DoCmpMapAndBranch(LCmpMapAndBranch* instr) { | 2435 void LCodeGen::DoCmpMapAndBranch(LCmpMapAndBranch* instr) { |
2436 Register value = ToRegister(instr->value()); | 2436 Register value = ToRegister(instr->value()); |
2437 Register map = ToRegister(instr->temp()); | 2437 Register map = ToRegister(instr->temp()); |
2438 | 2438 |
2439 __ Ldr(map, FieldMemOperand(value, HeapObject::kMapOffset)); | 2439 __ Ldr(map, FieldMemOperand(value, HeapObject::kMapOffset)); |
2440 EmitCompareAndBranch(instr, eq, map, Operand(instr->map())); | 2440 EmitCompareAndBranch(instr, eq, map, Operand(instr->map())); |
2441 } | 2441 } |
2442 | 2442 |
2443 | 2443 |
2444 void LCodeGen::DoCompareMinusZeroAndBranch(LCompareMinusZeroAndBranch* instr) { | 2444 void LCodeGen::DoCompareMinusZeroAndBranch(LCompareMinusZeroAndBranch* instr) { |
2445 Representation rep = instr->hydrogen()->value()->representation(); | 2445 Representation rep = instr->hydrogen()->value()->representation(); |
2446 ASSERT(!rep.IsInteger32()); | 2446 DCHECK(!rep.IsInteger32()); |
2447 Register scratch = ToRegister(instr->temp()); | 2447 Register scratch = ToRegister(instr->temp()); |
2448 | 2448 |
2449 if (rep.IsDouble()) { | 2449 if (rep.IsDouble()) { |
2450 __ JumpIfMinusZero(ToDoubleRegister(instr->value()), | 2450 __ JumpIfMinusZero(ToDoubleRegister(instr->value()), |
2451 instr->TrueLabel(chunk())); | 2451 instr->TrueLabel(chunk())); |
2452 } else { | 2452 } else { |
2453 Register value = ToRegister(instr->value()); | 2453 Register value = ToRegister(instr->value()); |
2454 __ CheckMap(value, scratch, Heap::kHeapNumberMapRootIndex, | 2454 __ CheckMap(value, scratch, Heap::kHeapNumberMapRootIndex, |
2455 instr->FalseLabel(chunk()), DO_SMI_CHECK); | 2455 instr->FalseLabel(chunk()), DO_SMI_CHECK); |
2456 __ Ldr(scratch, FieldMemOperand(value, HeapNumber::kValueOffset)); | 2456 __ Ldr(scratch, FieldMemOperand(value, HeapNumber::kValueOffset)); |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2491 ToRegister32(left), | 2491 ToRegister32(left), |
2492 ToOperand32I(right)); | 2492 ToOperand32I(right)); |
2493 } else { | 2493 } else { |
2494 // Commute the operands and the condition. | 2494 // Commute the operands and the condition. |
2495 EmitCompareAndBranch(instr, | 2495 EmitCompareAndBranch(instr, |
2496 CommuteCondition(cond), | 2496 CommuteCondition(cond), |
2497 ToRegister32(right), | 2497 ToRegister32(right), |
2498 ToOperand32I(left)); | 2498 ToOperand32I(left)); |
2499 } | 2499 } |
2500 } else { | 2500 } else { |
2501 ASSERT(instr->hydrogen_value()->representation().IsSmi()); | 2501 DCHECK(instr->hydrogen_value()->representation().IsSmi()); |
2502 if (right->IsConstantOperand()) { | 2502 if (right->IsConstantOperand()) { |
2503 int32_t value = ToInteger32(LConstantOperand::cast(right)); | 2503 int32_t value = ToInteger32(LConstantOperand::cast(right)); |
2504 EmitCompareAndBranch(instr, | 2504 EmitCompareAndBranch(instr, |
2505 cond, | 2505 cond, |
2506 ToRegister(left), | 2506 ToRegister(left), |
2507 Operand(Smi::FromInt(value))); | 2507 Operand(Smi::FromInt(value))); |
2508 } else if (left->IsConstantOperand()) { | 2508 } else if (left->IsConstantOperand()) { |
2509 // Commute the operands and the condition. | 2509 // Commute the operands and the condition. |
2510 int32_t value = ToInteger32(LConstantOperand::cast(left)); | 2510 int32_t value = ToInteger32(LConstantOperand::cast(left)); |
2511 EmitCompareAndBranch(instr, | 2511 EmitCompareAndBranch(instr, |
(...skipping 13 matching lines...) Expand all Loading... |
2525 | 2525 |
2526 | 2526 |
2527 void LCodeGen::DoCmpObjectEqAndBranch(LCmpObjectEqAndBranch* instr) { | 2527 void LCodeGen::DoCmpObjectEqAndBranch(LCmpObjectEqAndBranch* instr) { |
2528 Register left = ToRegister(instr->left()); | 2528 Register left = ToRegister(instr->left()); |
2529 Register right = ToRegister(instr->right()); | 2529 Register right = ToRegister(instr->right()); |
2530 EmitCompareAndBranch(instr, eq, left, right); | 2530 EmitCompareAndBranch(instr, eq, left, right); |
2531 } | 2531 } |
2532 | 2532 |
2533 | 2533 |
2534 void LCodeGen::DoCmpT(LCmpT* instr) { | 2534 void LCodeGen::DoCmpT(LCmpT* instr) { |
2535 ASSERT(ToRegister(instr->context()).is(cp)); | 2535 DCHECK(ToRegister(instr->context()).is(cp)); |
2536 Token::Value op = instr->op(); | 2536 Token::Value op = instr->op(); |
2537 Condition cond = TokenToCondition(op, false); | 2537 Condition cond = TokenToCondition(op, false); |
2538 | 2538 |
2539 ASSERT(ToRegister(instr->left()).Is(x1)); | 2539 DCHECK(ToRegister(instr->left()).Is(x1)); |
2540 ASSERT(ToRegister(instr->right()).Is(x0)); | 2540 DCHECK(ToRegister(instr->right()).Is(x0)); |
2541 Handle<Code> ic = CompareIC::GetUninitialized(isolate(), op); | 2541 Handle<Code> ic = CompareIC::GetUninitialized(isolate(), op); |
2542 CallCode(ic, RelocInfo::CODE_TARGET, instr); | 2542 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
2543 // Signal that we don't inline smi code before this stub. | 2543 // Signal that we don't inline smi code before this stub. |
2544 InlineSmiCheckInfo::EmitNotInlined(masm()); | 2544 InlineSmiCheckInfo::EmitNotInlined(masm()); |
2545 | 2545 |
2546 // Return true or false depending on CompareIC result. | 2546 // Return true or false depending on CompareIC result. |
2547 // This instruction is marked as call. We can clobber any register. | 2547 // This instruction is marked as call. We can clobber any register. |
2548 ASSERT(instr->IsMarkedAsCall()); | 2548 DCHECK(instr->IsMarkedAsCall()); |
2549 __ LoadTrueFalseRoots(x1, x2); | 2549 __ LoadTrueFalseRoots(x1, x2); |
2550 __ Cmp(x0, 0); | 2550 __ Cmp(x0, 0); |
2551 __ Csel(ToRegister(instr->result()), x1, x2, cond); | 2551 __ Csel(ToRegister(instr->result()), x1, x2, cond); |
2552 } | 2552 } |
2553 | 2553 |
2554 | 2554 |
2555 void LCodeGen::DoConstantD(LConstantD* instr) { | 2555 void LCodeGen::DoConstantD(LConstantD* instr) { |
2556 ASSERT(instr->result()->IsDoubleRegister()); | 2556 DCHECK(instr->result()->IsDoubleRegister()); |
2557 DoubleRegister result = ToDoubleRegister(instr->result()); | 2557 DoubleRegister result = ToDoubleRegister(instr->result()); |
2558 if (instr->value() == 0) { | 2558 if (instr->value() == 0) { |
2559 if (copysign(1.0, instr->value()) == 1.0) { | 2559 if (copysign(1.0, instr->value()) == 1.0) { |
2560 __ Fmov(result, fp_zero); | 2560 __ Fmov(result, fp_zero); |
2561 } else { | 2561 } else { |
2562 __ Fneg(result, fp_zero); | 2562 __ Fneg(result, fp_zero); |
2563 } | 2563 } |
2564 } else { | 2564 } else { |
2565 __ Fmov(result, instr->value()); | 2565 __ Fmov(result, instr->value()); |
2566 } | 2566 } |
2567 } | 2567 } |
2568 | 2568 |
2569 | 2569 |
2570 void LCodeGen::DoConstantE(LConstantE* instr) { | 2570 void LCodeGen::DoConstantE(LConstantE* instr) { |
2571 __ Mov(ToRegister(instr->result()), Operand(instr->value())); | 2571 __ Mov(ToRegister(instr->result()), Operand(instr->value())); |
2572 } | 2572 } |
2573 | 2573 |
2574 | 2574 |
2575 void LCodeGen::DoConstantI(LConstantI* instr) { | 2575 void LCodeGen::DoConstantI(LConstantI* instr) { |
2576 ASSERT(is_int32(instr->value())); | 2576 DCHECK(is_int32(instr->value())); |
2577 // Cast the value here to ensure that the value isn't sign extended by the | 2577 // Cast the value here to ensure that the value isn't sign extended by the |
2578 // implicit Operand constructor. | 2578 // implicit Operand constructor. |
2579 __ Mov(ToRegister32(instr->result()), static_cast<uint32_t>(instr->value())); | 2579 __ Mov(ToRegister32(instr->result()), static_cast<uint32_t>(instr->value())); |
2580 } | 2580 } |
2581 | 2581 |
2582 | 2582 |
2583 void LCodeGen::DoConstantS(LConstantS* instr) { | 2583 void LCodeGen::DoConstantS(LConstantS* instr) { |
2584 __ Mov(ToRegister(instr->result()), Operand(instr->value())); | 2584 __ Mov(ToRegister(instr->result()), Operand(instr->value())); |
2585 } | 2585 } |
2586 | 2586 |
2587 | 2587 |
2588 void LCodeGen::DoConstantT(LConstantT* instr) { | 2588 void LCodeGen::DoConstantT(LConstantT* instr) { |
2589 Handle<Object> object = instr->value(isolate()); | 2589 Handle<Object> object = instr->value(isolate()); |
2590 AllowDeferredHandleDereference smi_check; | 2590 AllowDeferredHandleDereference smi_check; |
2591 __ LoadObject(ToRegister(instr->result()), object); | 2591 __ LoadObject(ToRegister(instr->result()), object); |
2592 } | 2592 } |
2593 | 2593 |
2594 | 2594 |
2595 void LCodeGen::DoContext(LContext* instr) { | 2595 void LCodeGen::DoContext(LContext* instr) { |
2596 // If there is a non-return use, the context must be moved to a register. | 2596 // If there is a non-return use, the context must be moved to a register. |
2597 Register result = ToRegister(instr->result()); | 2597 Register result = ToRegister(instr->result()); |
2598 if (info()->IsOptimizing()) { | 2598 if (info()->IsOptimizing()) { |
2599 __ Ldr(result, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 2599 __ Ldr(result, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
2600 } else { | 2600 } else { |
2601 // If there is no frame, the context must be in cp. | 2601 // If there is no frame, the context must be in cp. |
2602 ASSERT(result.is(cp)); | 2602 DCHECK(result.is(cp)); |
2603 } | 2603 } |
2604 } | 2604 } |
2605 | 2605 |
2606 | 2606 |
2607 void LCodeGen::DoCheckValue(LCheckValue* instr) { | 2607 void LCodeGen::DoCheckValue(LCheckValue* instr) { |
2608 Register reg = ToRegister(instr->value()); | 2608 Register reg = ToRegister(instr->value()); |
2609 Handle<HeapObject> object = instr->hydrogen()->object().handle(); | 2609 Handle<HeapObject> object = instr->hydrogen()->object().handle(); |
2610 AllowDeferredHandleDereference smi_check; | 2610 AllowDeferredHandleDereference smi_check; |
2611 if (isolate()->heap()->InNewSpace(*object)) { | 2611 if (isolate()->heap()->InNewSpace(*object)) { |
2612 UseScratchRegisterScope temps(masm()); | 2612 UseScratchRegisterScope temps(masm()); |
2613 Register temp = temps.AcquireX(); | 2613 Register temp = temps.AcquireX(); |
2614 Handle<Cell> cell = isolate()->factory()->NewCell(object); | 2614 Handle<Cell> cell = isolate()->factory()->NewCell(object); |
2615 __ Mov(temp, Operand(Handle<Object>(cell))); | 2615 __ Mov(temp, Operand(Handle<Object>(cell))); |
2616 __ Ldr(temp, FieldMemOperand(temp, Cell::kValueOffset)); | 2616 __ Ldr(temp, FieldMemOperand(temp, Cell::kValueOffset)); |
2617 __ Cmp(reg, temp); | 2617 __ Cmp(reg, temp); |
2618 } else { | 2618 } else { |
2619 __ Cmp(reg, Operand(object)); | 2619 __ Cmp(reg, Operand(object)); |
2620 } | 2620 } |
2621 DeoptimizeIf(ne, instr->environment()); | 2621 DeoptimizeIf(ne, instr->environment()); |
2622 } | 2622 } |
2623 | 2623 |
2624 | 2624 |
2625 void LCodeGen::DoLazyBailout(LLazyBailout* instr) { | 2625 void LCodeGen::DoLazyBailout(LLazyBailout* instr) { |
2626 last_lazy_deopt_pc_ = masm()->pc_offset(); | 2626 last_lazy_deopt_pc_ = masm()->pc_offset(); |
2627 ASSERT(instr->HasEnvironment()); | 2627 DCHECK(instr->HasEnvironment()); |
2628 LEnvironment* env = instr->environment(); | 2628 LEnvironment* env = instr->environment(); |
2629 RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt); | 2629 RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt); |
2630 safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index()); | 2630 safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index()); |
2631 } | 2631 } |
2632 | 2632 |
2633 | 2633 |
2634 void LCodeGen::DoDateField(LDateField* instr) { | 2634 void LCodeGen::DoDateField(LDateField* instr) { |
2635 Register object = ToRegister(instr->date()); | 2635 Register object = ToRegister(instr->date()); |
2636 Register result = ToRegister(instr->result()); | 2636 Register result = ToRegister(instr->result()); |
2637 Register temp1 = x10; | 2637 Register temp1 = x10; |
2638 Register temp2 = x11; | 2638 Register temp2 = x11; |
2639 Smi* index = instr->index(); | 2639 Smi* index = instr->index(); |
2640 Label runtime, done; | 2640 Label runtime, done; |
2641 | 2641 |
2642 ASSERT(object.is(result) && object.Is(x0)); | 2642 DCHECK(object.is(result) && object.Is(x0)); |
2643 ASSERT(instr->IsMarkedAsCall()); | 2643 DCHECK(instr->IsMarkedAsCall()); |
2644 | 2644 |
2645 DeoptimizeIfSmi(object, instr->environment()); | 2645 DeoptimizeIfSmi(object, instr->environment()); |
2646 __ CompareObjectType(object, temp1, temp1, JS_DATE_TYPE); | 2646 __ CompareObjectType(object, temp1, temp1, JS_DATE_TYPE); |
2647 DeoptimizeIf(ne, instr->environment()); | 2647 DeoptimizeIf(ne, instr->environment()); |
2648 | 2648 |
2649 if (index->value() == 0) { | 2649 if (index->value() == 0) { |
2650 __ Ldr(result, FieldMemOperand(object, JSDate::kValueOffset)); | 2650 __ Ldr(result, FieldMemOperand(object, JSDate::kValueOffset)); |
2651 } else { | 2651 } else { |
2652 if (index->value() < JSDate::kFirstUncachedField) { | 2652 if (index->value() < JSDate::kFirstUncachedField) { |
2653 ExternalReference stamp = ExternalReference::date_cache_stamp(isolate()); | 2653 ExternalReference stamp = ExternalReference::date_cache_stamp(isolate()); |
(...skipping 28 matching lines...) Expand all Loading... |
2682 | 2682 |
2683 Comment(";;; deoptimize: %s", instr->hydrogen()->reason()); | 2683 Comment(";;; deoptimize: %s", instr->hydrogen()->reason()); |
2684 Deoptimize(instr->environment(), &type); | 2684 Deoptimize(instr->environment(), &type); |
2685 } | 2685 } |
2686 | 2686 |
2687 | 2687 |
2688 void LCodeGen::DoDivByPowerOf2I(LDivByPowerOf2I* instr) { | 2688 void LCodeGen::DoDivByPowerOf2I(LDivByPowerOf2I* instr) { |
2689 Register dividend = ToRegister32(instr->dividend()); | 2689 Register dividend = ToRegister32(instr->dividend()); |
2690 int32_t divisor = instr->divisor(); | 2690 int32_t divisor = instr->divisor(); |
2691 Register result = ToRegister32(instr->result()); | 2691 Register result = ToRegister32(instr->result()); |
2692 ASSERT(divisor == kMinInt || IsPowerOf2(Abs(divisor))); | 2692 DCHECK(divisor == kMinInt || IsPowerOf2(Abs(divisor))); |
2693 ASSERT(!result.is(dividend)); | 2693 DCHECK(!result.is(dividend)); |
2694 | 2694 |
2695 // Check for (0 / -x) that will produce negative zero. | 2695 // Check for (0 / -x) that will produce negative zero. |
2696 HDiv* hdiv = instr->hydrogen(); | 2696 HDiv* hdiv = instr->hydrogen(); |
2697 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) { | 2697 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) { |
2698 DeoptimizeIfZero(dividend, instr->environment()); | 2698 DeoptimizeIfZero(dividend, instr->environment()); |
2699 } | 2699 } |
2700 // Check for (kMinInt / -1). | 2700 // Check for (kMinInt / -1). |
2701 if (hdiv->CheckFlag(HValue::kCanOverflow) && divisor == -1) { | 2701 if (hdiv->CheckFlag(HValue::kCanOverflow) && divisor == -1) { |
2702 // Test dividend for kMinInt by subtracting one (cmp) and checking for | 2702 // Test dividend for kMinInt by subtracting one (cmp) and checking for |
2703 // overflow. | 2703 // overflow. |
(...skipping 23 matching lines...) Expand all Loading... |
2727 } | 2727 } |
2728 if (shift > 0) __ Mov(result, Operand(result, ASR, shift)); | 2728 if (shift > 0) __ Mov(result, Operand(result, ASR, shift)); |
2729 if (divisor < 0) __ Neg(result, result); | 2729 if (divisor < 0) __ Neg(result, result); |
2730 } | 2730 } |
2731 | 2731 |
2732 | 2732 |
2733 void LCodeGen::DoDivByConstI(LDivByConstI* instr) { | 2733 void LCodeGen::DoDivByConstI(LDivByConstI* instr) { |
2734 Register dividend = ToRegister32(instr->dividend()); | 2734 Register dividend = ToRegister32(instr->dividend()); |
2735 int32_t divisor = instr->divisor(); | 2735 int32_t divisor = instr->divisor(); |
2736 Register result = ToRegister32(instr->result()); | 2736 Register result = ToRegister32(instr->result()); |
2737 ASSERT(!AreAliased(dividend, result)); | 2737 DCHECK(!AreAliased(dividend, result)); |
2738 | 2738 |
2739 if (divisor == 0) { | 2739 if (divisor == 0) { |
2740 Deoptimize(instr->environment()); | 2740 Deoptimize(instr->environment()); |
2741 return; | 2741 return; |
2742 } | 2742 } |
2743 | 2743 |
2744 // Check for (0 / -x) that will produce negative zero. | 2744 // Check for (0 / -x) that will produce negative zero. |
2745 HDiv* hdiv = instr->hydrogen(); | 2745 HDiv* hdiv = instr->hydrogen(); |
2746 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) { | 2746 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) { |
2747 DeoptimizeIfZero(dividend, instr->environment()); | 2747 DeoptimizeIfZero(dividend, instr->environment()); |
2748 } | 2748 } |
2749 | 2749 |
2750 __ TruncatingDiv(result, dividend, Abs(divisor)); | 2750 __ TruncatingDiv(result, dividend, Abs(divisor)); |
2751 if (divisor < 0) __ Neg(result, result); | 2751 if (divisor < 0) __ Neg(result, result); |
2752 | 2752 |
2753 if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32)) { | 2753 if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32)) { |
2754 Register temp = ToRegister32(instr->temp()); | 2754 Register temp = ToRegister32(instr->temp()); |
2755 ASSERT(!AreAliased(dividend, result, temp)); | 2755 DCHECK(!AreAliased(dividend, result, temp)); |
2756 __ Sxtw(dividend.X(), dividend); | 2756 __ Sxtw(dividend.X(), dividend); |
2757 __ Mov(temp, divisor); | 2757 __ Mov(temp, divisor); |
2758 __ Smsubl(temp.X(), result, temp, dividend.X()); | 2758 __ Smsubl(temp.X(), result, temp, dividend.X()); |
2759 DeoptimizeIfNotZero(temp, instr->environment()); | 2759 DeoptimizeIfNotZero(temp, instr->environment()); |
2760 } | 2760 } |
2761 } | 2761 } |
2762 | 2762 |
2763 | 2763 |
2764 // TODO(svenpanne) Refactor this to avoid code duplication with DoFlooringDivI. | 2764 // TODO(svenpanne) Refactor this to avoid code duplication with DoFlooringDivI. |
2765 void LCodeGen::DoDivI(LDivI* instr) { | 2765 void LCodeGen::DoDivI(LDivI* instr) { |
2766 HBinaryOperation* hdiv = instr->hydrogen(); | 2766 HBinaryOperation* hdiv = instr->hydrogen(); |
2767 Register dividend = ToRegister32(instr->dividend()); | 2767 Register dividend = ToRegister32(instr->dividend()); |
2768 Register divisor = ToRegister32(instr->divisor()); | 2768 Register divisor = ToRegister32(instr->divisor()); |
2769 Register result = ToRegister32(instr->result()); | 2769 Register result = ToRegister32(instr->result()); |
2770 | 2770 |
2771 // Issue the division first, and then check for any deopt cases whilst the | 2771 // Issue the division first, and then check for any deopt cases whilst the |
2772 // result is computed. | 2772 // result is computed. |
2773 __ Sdiv(result, dividend, divisor); | 2773 __ Sdiv(result, dividend, divisor); |
2774 | 2774 |
2775 if (hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32)) { | 2775 if (hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32)) { |
2776 ASSERT_EQ(NULL, instr->temp()); | 2776 DCHECK_EQ(NULL, instr->temp()); |
2777 return; | 2777 return; |
2778 } | 2778 } |
2779 | 2779 |
2780 // Check for x / 0. | 2780 // Check for x / 0. |
2781 if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) { | 2781 if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) { |
2782 DeoptimizeIfZero(divisor, instr->environment()); | 2782 DeoptimizeIfZero(divisor, instr->environment()); |
2783 } | 2783 } |
2784 | 2784 |
2785 // Check for (0 / -x) as that will produce negative zero. | 2785 // Check for (0 / -x) as that will produce negative zero. |
2786 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) { | 2786 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) { |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2839 // Nothing to see here, move on! | 2839 // Nothing to see here, move on! |
2840 } | 2840 } |
2841 | 2841 |
2842 | 2842 |
2843 void LCodeGen::DoDummyUse(LDummyUse* instr) { | 2843 void LCodeGen::DoDummyUse(LDummyUse* instr) { |
2844 // Nothing to see here, move on! | 2844 // Nothing to see here, move on! |
2845 } | 2845 } |
2846 | 2846 |
2847 | 2847 |
2848 void LCodeGen::DoFunctionLiteral(LFunctionLiteral* instr) { | 2848 void LCodeGen::DoFunctionLiteral(LFunctionLiteral* instr) { |
2849 ASSERT(ToRegister(instr->context()).is(cp)); | 2849 DCHECK(ToRegister(instr->context()).is(cp)); |
2850 // FunctionLiteral instruction is marked as call, we can trash any register. | 2850 // FunctionLiteral instruction is marked as call, we can trash any register. |
2851 ASSERT(instr->IsMarkedAsCall()); | 2851 DCHECK(instr->IsMarkedAsCall()); |
2852 | 2852 |
2853 // Use the fast case closure allocation code that allocates in new | 2853 // Use the fast case closure allocation code that allocates in new |
2854 // space for nested functions that don't need literals cloning. | 2854 // space for nested functions that don't need literals cloning. |
2855 bool pretenure = instr->hydrogen()->pretenure(); | 2855 bool pretenure = instr->hydrogen()->pretenure(); |
2856 if (!pretenure && instr->hydrogen()->has_no_literals()) { | 2856 if (!pretenure && instr->hydrogen()->has_no_literals()) { |
2857 FastNewClosureStub stub(isolate(), | 2857 FastNewClosureStub stub(isolate(), |
2858 instr->hydrogen()->strict_mode(), | 2858 instr->hydrogen()->strict_mode(), |
2859 instr->hydrogen()->is_generator()); | 2859 instr->hydrogen()->is_generator()); |
2860 __ Mov(x2, Operand(instr->hydrogen()->shared_info())); | 2860 __ Mov(x2, Operand(instr->hydrogen()->shared_info())); |
2861 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); | 2861 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
(...skipping 25 matching lines...) Expand all Loading... |
2887 DeoptimizeIfZero(result, instr->environment()); | 2887 DeoptimizeIfZero(result, instr->environment()); |
2888 | 2888 |
2889 __ Bind(&done); | 2889 __ Bind(&done); |
2890 } | 2890 } |
2891 | 2891 |
2892 | 2892 |
2893 void LCodeGen::DoForInPrepareMap(LForInPrepareMap* instr) { | 2893 void LCodeGen::DoForInPrepareMap(LForInPrepareMap* instr) { |
2894 Register object = ToRegister(instr->object()); | 2894 Register object = ToRegister(instr->object()); |
2895 Register null_value = x5; | 2895 Register null_value = x5; |
2896 | 2896 |
2897 ASSERT(instr->IsMarkedAsCall()); | 2897 DCHECK(instr->IsMarkedAsCall()); |
2898 ASSERT(object.Is(x0)); | 2898 DCHECK(object.Is(x0)); |
2899 | 2899 |
2900 DeoptimizeIfRoot(object, Heap::kUndefinedValueRootIndex, | 2900 DeoptimizeIfRoot(object, Heap::kUndefinedValueRootIndex, |
2901 instr->environment()); | 2901 instr->environment()); |
2902 | 2902 |
2903 __ LoadRoot(null_value, Heap::kNullValueRootIndex); | 2903 __ LoadRoot(null_value, Heap::kNullValueRootIndex); |
2904 __ Cmp(object, null_value); | 2904 __ Cmp(object, null_value); |
2905 DeoptimizeIf(eq, instr->environment()); | 2905 DeoptimizeIf(eq, instr->environment()); |
2906 | 2906 |
2907 DeoptimizeIfSmi(object, instr->environment()); | 2907 DeoptimizeIfSmi(object, instr->environment()); |
2908 | 2908 |
(...skipping 19 matching lines...) Expand all Loading... |
2928 } | 2928 } |
2929 | 2929 |
2930 | 2930 |
2931 void LCodeGen::DoGetCachedArrayIndex(LGetCachedArrayIndex* instr) { | 2931 void LCodeGen::DoGetCachedArrayIndex(LGetCachedArrayIndex* instr) { |
2932 Register input = ToRegister(instr->value()); | 2932 Register input = ToRegister(instr->value()); |
2933 Register result = ToRegister(instr->result()); | 2933 Register result = ToRegister(instr->result()); |
2934 | 2934 |
2935 __ AssertString(input); | 2935 __ AssertString(input); |
2936 | 2936 |
2937 // Assert that we can use a W register load to get the hash. | 2937 // Assert that we can use a W register load to get the hash. |
2938 ASSERT((String::kHashShift + String::kArrayIndexValueBits) < kWRegSizeInBits); | 2938 DCHECK((String::kHashShift + String::kArrayIndexValueBits) < kWRegSizeInBits); |
2939 __ Ldr(result.W(), FieldMemOperand(input, String::kHashFieldOffset)); | 2939 __ Ldr(result.W(), FieldMemOperand(input, String::kHashFieldOffset)); |
2940 __ IndexFromHash(result, result); | 2940 __ IndexFromHash(result, result); |
2941 } | 2941 } |
2942 | 2942 |
2943 | 2943 |
2944 void LCodeGen::EmitGoto(int block) { | 2944 void LCodeGen::EmitGoto(int block) { |
2945 // Do not emit jump if we are emitting a goto to the next block. | 2945 // Do not emit jump if we are emitting a goto to the next block. |
2946 if (!IsNextEmittedBlock(block)) { | 2946 if (!IsNextEmittedBlock(block)) { |
2947 __ B(chunk_->GetAssemblyLabel(LookupDestination(block))); | 2947 __ B(chunk_->GetAssemblyLabel(LookupDestination(block))); |
2948 } | 2948 } |
2949 } | 2949 } |
2950 | 2950 |
2951 | 2951 |
2952 void LCodeGen::DoGoto(LGoto* instr) { | 2952 void LCodeGen::DoGoto(LGoto* instr) { |
2953 EmitGoto(instr->block_id()); | 2953 EmitGoto(instr->block_id()); |
2954 } | 2954 } |
2955 | 2955 |
2956 | 2956 |
2957 void LCodeGen::DoHasCachedArrayIndexAndBranch( | 2957 void LCodeGen::DoHasCachedArrayIndexAndBranch( |
2958 LHasCachedArrayIndexAndBranch* instr) { | 2958 LHasCachedArrayIndexAndBranch* instr) { |
2959 Register input = ToRegister(instr->value()); | 2959 Register input = ToRegister(instr->value()); |
2960 Register temp = ToRegister32(instr->temp()); | 2960 Register temp = ToRegister32(instr->temp()); |
2961 | 2961 |
2962 // Assert that the cache status bits fit in a W register. | 2962 // Assert that the cache status bits fit in a W register. |
2963 ASSERT(is_uint32(String::kContainsCachedArrayIndexMask)); | 2963 DCHECK(is_uint32(String::kContainsCachedArrayIndexMask)); |
2964 __ Ldr(temp, FieldMemOperand(input, String::kHashFieldOffset)); | 2964 __ Ldr(temp, FieldMemOperand(input, String::kHashFieldOffset)); |
2965 __ Tst(temp, String::kContainsCachedArrayIndexMask); | 2965 __ Tst(temp, String::kContainsCachedArrayIndexMask); |
2966 EmitBranch(instr, eq); | 2966 EmitBranch(instr, eq); |
2967 } | 2967 } |
2968 | 2968 |
2969 | 2969 |
2970 // HHasInstanceTypeAndBranch instruction is built with an interval of type | 2970 // HHasInstanceTypeAndBranch instruction is built with an interval of type |
2971 // to test but is only used in very restricted ways. The only possible kinds | 2971 // to test but is only used in very restricted ways. The only possible kinds |
2972 // of intervals are: | 2972 // of intervals are: |
2973 // - [ FIRST_TYPE, instr->to() ] | 2973 // - [ FIRST_TYPE, instr->to() ] |
2974 // - [ instr->form(), LAST_TYPE ] | 2974 // - [ instr->form(), LAST_TYPE ] |
2975 // - instr->from() == instr->to() | 2975 // - instr->from() == instr->to() |
2976 // | 2976 // |
2977 // These kinds of intervals can be check with only one compare instruction | 2977 // These kinds of intervals can be check with only one compare instruction |
2978 // providing the correct value and test condition are used. | 2978 // providing the correct value and test condition are used. |
2979 // | 2979 // |
2980 // TestType() will return the value to use in the compare instruction and | 2980 // TestType() will return the value to use in the compare instruction and |
2981 // BranchCondition() will return the condition to use depending on the kind | 2981 // BranchCondition() will return the condition to use depending on the kind |
2982 // of interval actually specified in the instruction. | 2982 // of interval actually specified in the instruction. |
2983 static InstanceType TestType(HHasInstanceTypeAndBranch* instr) { | 2983 static InstanceType TestType(HHasInstanceTypeAndBranch* instr) { |
2984 InstanceType from = instr->from(); | 2984 InstanceType from = instr->from(); |
2985 InstanceType to = instr->to(); | 2985 InstanceType to = instr->to(); |
2986 if (from == FIRST_TYPE) return to; | 2986 if (from == FIRST_TYPE) return to; |
2987 ASSERT((from == to) || (to == LAST_TYPE)); | 2987 DCHECK((from == to) || (to == LAST_TYPE)); |
2988 return from; | 2988 return from; |
2989 } | 2989 } |
2990 | 2990 |
2991 | 2991 |
2992 // See comment above TestType function for what this function does. | 2992 // See comment above TestType function for what this function does. |
2993 static Condition BranchCondition(HHasInstanceTypeAndBranch* instr) { | 2993 static Condition BranchCondition(HHasInstanceTypeAndBranch* instr) { |
2994 InstanceType from = instr->from(); | 2994 InstanceType from = instr->from(); |
2995 InstanceType to = instr->to(); | 2995 InstanceType to = instr->to(); |
2996 if (from == to) return eq; | 2996 if (from == to) return eq; |
2997 if (to == LAST_TYPE) return hs; | 2997 if (to == LAST_TYPE) return hs; |
(...skipping 20 matching lines...) Expand all Loading... |
3018 Register base = ToRegister(instr->base_object()); | 3018 Register base = ToRegister(instr->base_object()); |
3019 if (instr->offset()->IsConstantOperand()) { | 3019 if (instr->offset()->IsConstantOperand()) { |
3020 __ Add(result, base, ToOperand32I(instr->offset())); | 3020 __ Add(result, base, ToOperand32I(instr->offset())); |
3021 } else { | 3021 } else { |
3022 __ Add(result, base, Operand(ToRegister32(instr->offset()), SXTW)); | 3022 __ Add(result, base, Operand(ToRegister32(instr->offset()), SXTW)); |
3023 } | 3023 } |
3024 } | 3024 } |
3025 | 3025 |
3026 | 3026 |
3027 void LCodeGen::DoInstanceOf(LInstanceOf* instr) { | 3027 void LCodeGen::DoInstanceOf(LInstanceOf* instr) { |
3028 ASSERT(ToRegister(instr->context()).is(cp)); | 3028 DCHECK(ToRegister(instr->context()).is(cp)); |
3029 // Assert that the arguments are in the registers expected by InstanceofStub. | 3029 // Assert that the arguments are in the registers expected by InstanceofStub. |
3030 ASSERT(ToRegister(instr->left()).Is(InstanceofStub::left())); | 3030 DCHECK(ToRegister(instr->left()).Is(InstanceofStub::left())); |
3031 ASSERT(ToRegister(instr->right()).Is(InstanceofStub::right())); | 3031 DCHECK(ToRegister(instr->right()).Is(InstanceofStub::right())); |
3032 | 3032 |
3033 InstanceofStub stub(isolate(), InstanceofStub::kArgsInRegisters); | 3033 InstanceofStub stub(isolate(), InstanceofStub::kArgsInRegisters); |
3034 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); | 3034 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
3035 | 3035 |
3036 // InstanceofStub returns a result in x0: | 3036 // InstanceofStub returns a result in x0: |
3037 // 0 => not an instance | 3037 // 0 => not an instance |
3038 // smi 1 => instance. | 3038 // smi 1 => instance. |
3039 __ Cmp(x0, 0); | 3039 __ Cmp(x0, 0); |
3040 __ LoadTrueFalseRoots(x0, x1); | 3040 __ LoadTrueFalseRoots(x0, x1); |
3041 __ Csel(x0, x0, x1, eq); | 3041 __ Csel(x0, x0, x1, eq); |
(...skipping 18 matching lines...) Expand all Loading... |
3060 new(zone()) DeferredInstanceOfKnownGlobal(this, instr); | 3060 new(zone()) DeferredInstanceOfKnownGlobal(this, instr); |
3061 | 3061 |
3062 Label map_check, return_false, cache_miss, done; | 3062 Label map_check, return_false, cache_miss, done; |
3063 Register object = ToRegister(instr->value()); | 3063 Register object = ToRegister(instr->value()); |
3064 Register result = ToRegister(instr->result()); | 3064 Register result = ToRegister(instr->result()); |
3065 // x4 is expected in the associated deferred code and stub. | 3065 // x4 is expected in the associated deferred code and stub. |
3066 Register map_check_site = x4; | 3066 Register map_check_site = x4; |
3067 Register map = x5; | 3067 Register map = x5; |
3068 | 3068 |
3069 // This instruction is marked as call. We can clobber any register. | 3069 // This instruction is marked as call. We can clobber any register. |
3070 ASSERT(instr->IsMarkedAsCall()); | 3070 DCHECK(instr->IsMarkedAsCall()); |
3071 | 3071 |
3072 // We must take into account that object is in x11. | 3072 // We must take into account that object is in x11. |
3073 ASSERT(object.Is(x11)); | 3073 DCHECK(object.Is(x11)); |
3074 Register scratch = x10; | 3074 Register scratch = x10; |
3075 | 3075 |
3076 // A Smi is not instance of anything. | 3076 // A Smi is not instance of anything. |
3077 __ JumpIfSmi(object, &return_false); | 3077 __ JumpIfSmi(object, &return_false); |
3078 | 3078 |
3079 // This is the inlined call site instanceof cache. The two occurences of the | 3079 // This is the inlined call site instanceof cache. The two occurences of the |
3080 // hole value will be patched to the last map/result pair generated by the | 3080 // hole value will be patched to the last map/result pair generated by the |
3081 // instanceof stub. | 3081 // instanceof stub. |
3082 __ Ldr(map, FieldMemOperand(object, HeapObject::kMapOffset)); | 3082 __ Ldr(map, FieldMemOperand(object, HeapObject::kMapOffset)); |
3083 { | 3083 { |
3084 // Below we use Factory::the_hole_value() on purpose instead of loading from | 3084 // Below we use Factory::the_hole_value() on purpose instead of loading from |
3085 // the root array to force relocation and later be able to patch with a | 3085 // the root array to force relocation and later be able to patch with a |
3086 // custom value. | 3086 // custom value. |
3087 InstructionAccurateScope scope(masm(), 5); | 3087 InstructionAccurateScope scope(masm(), 5); |
3088 __ bind(&map_check); | 3088 __ bind(&map_check); |
3089 // Will be patched with the cached map. | 3089 // Will be patched with the cached map. |
3090 Handle<Cell> cell = factory()->NewCell(factory()->the_hole_value()); | 3090 Handle<Cell> cell = factory()->NewCell(factory()->the_hole_value()); |
3091 __ ldr(scratch, Immediate(Handle<Object>(cell))); | 3091 __ ldr(scratch, Immediate(Handle<Object>(cell))); |
3092 __ ldr(scratch, FieldMemOperand(scratch, PropertyCell::kValueOffset)); | 3092 __ ldr(scratch, FieldMemOperand(scratch, PropertyCell::kValueOffset)); |
3093 __ cmp(map, scratch); | 3093 __ cmp(map, scratch); |
3094 __ b(&cache_miss, ne); | 3094 __ b(&cache_miss, ne); |
3095 // The address of this instruction is computed relative to the map check | 3095 // The address of this instruction is computed relative to the map check |
3096 // above, so check the size of the code generated. | 3096 // above, so check the size of the code generated. |
3097 ASSERT(masm()->InstructionsGeneratedSince(&map_check) == 4); | 3097 DCHECK(masm()->InstructionsGeneratedSince(&map_check) == 4); |
3098 // Will be patched with the cached result. | 3098 // Will be patched with the cached result. |
3099 __ ldr(result, Immediate(factory()->the_hole_value())); | 3099 __ ldr(result, Immediate(factory()->the_hole_value())); |
3100 } | 3100 } |
3101 __ B(&done); | 3101 __ B(&done); |
3102 | 3102 |
3103 // The inlined call site cache did not match. | 3103 // The inlined call site cache did not match. |
3104 // Check null and string before calling the deferred code. | 3104 // Check null and string before calling the deferred code. |
3105 __ Bind(&cache_miss); | 3105 __ Bind(&cache_miss); |
3106 // Compute the address of the map check. It must not be clobbered until the | 3106 // Compute the address of the map check. It must not be clobbered until the |
3107 // InstanceOfStub has used it. | 3107 // InstanceOfStub has used it. |
(...skipping 14 matching lines...) Expand all Loading... |
3122 __ LoadRoot(result, Heap::kFalseValueRootIndex); | 3122 __ LoadRoot(result, Heap::kFalseValueRootIndex); |
3123 | 3123 |
3124 // Here result is either true or false. | 3124 // Here result is either true or false. |
3125 __ Bind(deferred->exit()); | 3125 __ Bind(deferred->exit()); |
3126 __ Bind(&done); | 3126 __ Bind(&done); |
3127 } | 3127 } |
3128 | 3128 |
3129 | 3129 |
3130 void LCodeGen::DoDeferredInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr) { | 3130 void LCodeGen::DoDeferredInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr) { |
3131 Register result = ToRegister(instr->result()); | 3131 Register result = ToRegister(instr->result()); |
3132 ASSERT(result.Is(x0)); // InstanceofStub returns its result in x0. | 3132 DCHECK(result.Is(x0)); // InstanceofStub returns its result in x0. |
3133 InstanceofStub::Flags flags = InstanceofStub::kNoFlags; | 3133 InstanceofStub::Flags flags = InstanceofStub::kNoFlags; |
3134 flags = static_cast<InstanceofStub::Flags>( | 3134 flags = static_cast<InstanceofStub::Flags>( |
3135 flags | InstanceofStub::kArgsInRegisters); | 3135 flags | InstanceofStub::kArgsInRegisters); |
3136 flags = static_cast<InstanceofStub::Flags>( | 3136 flags = static_cast<InstanceofStub::Flags>( |
3137 flags | InstanceofStub::kReturnTrueFalseObject); | 3137 flags | InstanceofStub::kReturnTrueFalseObject); |
3138 flags = static_cast<InstanceofStub::Flags>( | 3138 flags = static_cast<InstanceofStub::Flags>( |
3139 flags | InstanceofStub::kCallSiteInlineCheck); | 3139 flags | InstanceofStub::kCallSiteInlineCheck); |
3140 | 3140 |
3141 PushSafepointRegistersScope scope(this); | 3141 PushSafepointRegistersScope scope(this); |
3142 LoadContextFromDeferred(instr->context()); | 3142 LoadContextFromDeferred(instr->context()); |
3143 | 3143 |
3144 // Prepare InstanceofStub arguments. | 3144 // Prepare InstanceofStub arguments. |
3145 ASSERT(ToRegister(instr->value()).Is(InstanceofStub::left())); | 3145 DCHECK(ToRegister(instr->value()).Is(InstanceofStub::left())); |
3146 __ LoadObject(InstanceofStub::right(), instr->function()); | 3146 __ LoadObject(InstanceofStub::right(), instr->function()); |
3147 | 3147 |
3148 InstanceofStub stub(isolate(), flags); | 3148 InstanceofStub stub(isolate(), flags); |
3149 CallCodeGeneric(stub.GetCode(), | 3149 CallCodeGeneric(stub.GetCode(), |
3150 RelocInfo::CODE_TARGET, | 3150 RelocInfo::CODE_TARGET, |
3151 instr, | 3151 instr, |
3152 RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS); | 3152 RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS); |
3153 LEnvironment* env = instr->GetDeferredLazyDeoptimizationEnvironment(); | 3153 LEnvironment* env = instr->GetDeferredLazyDeoptimizationEnvironment(); |
3154 safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index()); | 3154 safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index()); |
3155 | 3155 |
3156 // Put the result value into the result register slot. | 3156 // Put the result value into the result register slot. |
3157 __ StoreToSafepointRegisterSlot(result, result); | 3157 __ StoreToSafepointRegisterSlot(result, result); |
3158 } | 3158 } |
3159 | 3159 |
3160 | 3160 |
3161 void LCodeGen::DoInstructionGap(LInstructionGap* instr) { | 3161 void LCodeGen::DoInstructionGap(LInstructionGap* instr) { |
3162 DoGap(instr); | 3162 DoGap(instr); |
3163 } | 3163 } |
3164 | 3164 |
3165 | 3165 |
3166 void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) { | 3166 void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) { |
3167 Register value = ToRegister32(instr->value()); | 3167 Register value = ToRegister32(instr->value()); |
3168 DoubleRegister result = ToDoubleRegister(instr->result()); | 3168 DoubleRegister result = ToDoubleRegister(instr->result()); |
3169 __ Scvtf(result, value); | 3169 __ Scvtf(result, value); |
3170 } | 3170 } |
3171 | 3171 |
3172 | 3172 |
3173 void LCodeGen::DoInvokeFunction(LInvokeFunction* instr) { | 3173 void LCodeGen::DoInvokeFunction(LInvokeFunction* instr) { |
3174 ASSERT(ToRegister(instr->context()).is(cp)); | 3174 DCHECK(ToRegister(instr->context()).is(cp)); |
3175 // The function is required to be in x1. | 3175 // The function is required to be in x1. |
3176 ASSERT(ToRegister(instr->function()).is(x1)); | 3176 DCHECK(ToRegister(instr->function()).is(x1)); |
3177 ASSERT(instr->HasPointerMap()); | 3177 DCHECK(instr->HasPointerMap()); |
3178 | 3178 |
3179 Handle<JSFunction> known_function = instr->hydrogen()->known_function(); | 3179 Handle<JSFunction> known_function = instr->hydrogen()->known_function(); |
3180 if (known_function.is_null()) { | 3180 if (known_function.is_null()) { |
3181 LPointerMap* pointers = instr->pointer_map(); | 3181 LPointerMap* pointers = instr->pointer_map(); |
3182 SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt); | 3182 SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt); |
3183 ParameterCount count(instr->arity()); | 3183 ParameterCount count(instr->arity()); |
3184 __ InvokeFunction(x1, count, CALL_FUNCTION, generator); | 3184 __ InvokeFunction(x1, count, CALL_FUNCTION, generator); |
3185 } else { | 3185 } else { |
3186 CallKnownFunction(known_function, | 3186 CallKnownFunction(known_function, |
3187 instr->hydrogen()->formal_parameter_count(), | 3187 instr->hydrogen()->formal_parameter_count(), |
(...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3358 __ Mov(result, Operand(Handle<Object>(instr->hydrogen()->cell().handle()))); | 3358 __ Mov(result, Operand(Handle<Object>(instr->hydrogen()->cell().handle()))); |
3359 __ Ldr(result, FieldMemOperand(result, Cell::kValueOffset)); | 3359 __ Ldr(result, FieldMemOperand(result, Cell::kValueOffset)); |
3360 if (instr->hydrogen()->RequiresHoleCheck()) { | 3360 if (instr->hydrogen()->RequiresHoleCheck()) { |
3361 DeoptimizeIfRoot( | 3361 DeoptimizeIfRoot( |
3362 result, Heap::kTheHoleValueRootIndex, instr->environment()); | 3362 result, Heap::kTheHoleValueRootIndex, instr->environment()); |
3363 } | 3363 } |
3364 } | 3364 } |
3365 | 3365 |
3366 | 3366 |
3367 void LCodeGen::DoLoadGlobalGeneric(LLoadGlobalGeneric* instr) { | 3367 void LCodeGen::DoLoadGlobalGeneric(LLoadGlobalGeneric* instr) { |
3368 ASSERT(ToRegister(instr->context()).is(cp)); | 3368 DCHECK(ToRegister(instr->context()).is(cp)); |
3369 ASSERT(ToRegister(instr->global_object()).is(LoadIC::ReceiverRegister())); | 3369 DCHECK(ToRegister(instr->global_object()).is(LoadIC::ReceiverRegister())); |
3370 ASSERT(ToRegister(instr->result()).Is(x0)); | 3370 DCHECK(ToRegister(instr->result()).Is(x0)); |
3371 __ Mov(LoadIC::NameRegister(), Operand(instr->name())); | 3371 __ Mov(LoadIC::NameRegister(), Operand(instr->name())); |
3372 if (FLAG_vector_ics) { | 3372 if (FLAG_vector_ics) { |
3373 Register vector = ToRegister(instr->temp_vector()); | 3373 Register vector = ToRegister(instr->temp_vector()); |
3374 ASSERT(vector.is(LoadIC::VectorRegister())); | 3374 DCHECK(vector.is(LoadIC::VectorRegister())); |
3375 __ Mov(vector, instr->hydrogen()->feedback_vector()); | 3375 __ Mov(vector, instr->hydrogen()->feedback_vector()); |
3376 // No need to allocate this register. | 3376 // No need to allocate this register. |
3377 ASSERT(LoadIC::SlotRegister().is(x0)); | 3377 DCHECK(LoadIC::SlotRegister().is(x0)); |
3378 __ Mov(LoadIC::SlotRegister(), | 3378 __ Mov(LoadIC::SlotRegister(), |
3379 Smi::FromInt(instr->hydrogen()->slot())); | 3379 Smi::FromInt(instr->hydrogen()->slot())); |
3380 } | 3380 } |
3381 ContextualMode mode = instr->for_typeof() ? NOT_CONTEXTUAL : CONTEXTUAL; | 3381 ContextualMode mode = instr->for_typeof() ? NOT_CONTEXTUAL : CONTEXTUAL; |
3382 Handle<Code> ic = LoadIC::initialize_stub(isolate(), mode); | 3382 Handle<Code> ic = LoadIC::initialize_stub(isolate(), mode); |
3383 CallCode(ic, RelocInfo::CODE_TARGET, instr); | 3383 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
3384 } | 3384 } |
3385 | 3385 |
3386 | 3386 |
3387 MemOperand LCodeGen::PrepareKeyedExternalArrayOperand( | 3387 MemOperand LCodeGen::PrepareKeyedExternalArrayOperand( |
(...skipping 14 matching lines...) Expand all Loading... |
3402 | 3402 |
3403 if (key_is_smi) { | 3403 if (key_is_smi) { |
3404 __ Add(scratch, base, Operand::UntagSmiAndScale(key, element_size_shift)); | 3404 __ Add(scratch, base, Operand::UntagSmiAndScale(key, element_size_shift)); |
3405 return MemOperand(scratch, base_offset); | 3405 return MemOperand(scratch, base_offset); |
3406 } | 3406 } |
3407 | 3407 |
3408 if (base_offset == 0) { | 3408 if (base_offset == 0) { |
3409 return MemOperand(base, key, SXTW, element_size_shift); | 3409 return MemOperand(base, key, SXTW, element_size_shift); |
3410 } | 3410 } |
3411 | 3411 |
3412 ASSERT(!AreAliased(scratch, key)); | 3412 DCHECK(!AreAliased(scratch, key)); |
3413 __ Add(scratch, base, base_offset); | 3413 __ Add(scratch, base, base_offset); |
3414 return MemOperand(scratch, key, SXTW, element_size_shift); | 3414 return MemOperand(scratch, key, SXTW, element_size_shift); |
3415 } | 3415 } |
3416 | 3416 |
3417 | 3417 |
3418 void LCodeGen::DoLoadKeyedExternal(LLoadKeyedExternal* instr) { | 3418 void LCodeGen::DoLoadKeyedExternal(LLoadKeyedExternal* instr) { |
3419 Register ext_ptr = ToRegister(instr->elements()); | 3419 Register ext_ptr = ToRegister(instr->elements()); |
3420 Register scratch; | 3420 Register scratch; |
3421 ElementsKind elements_kind = instr->elements_kind(); | 3421 ElementsKind elements_kind = instr->elements_kind(); |
3422 | 3422 |
3423 bool key_is_smi = instr->hydrogen()->key()->representation().IsSmi(); | 3423 bool key_is_smi = instr->hydrogen()->key()->representation().IsSmi(); |
3424 bool key_is_constant = instr->key()->IsConstantOperand(); | 3424 bool key_is_constant = instr->key()->IsConstantOperand(); |
3425 Register key = no_reg; | 3425 Register key = no_reg; |
3426 int constant_key = 0; | 3426 int constant_key = 0; |
3427 if (key_is_constant) { | 3427 if (key_is_constant) { |
3428 ASSERT(instr->temp() == NULL); | 3428 DCHECK(instr->temp() == NULL); |
3429 constant_key = ToInteger32(LConstantOperand::cast(instr->key())); | 3429 constant_key = ToInteger32(LConstantOperand::cast(instr->key())); |
3430 if (constant_key & 0xf0000000) { | 3430 if (constant_key & 0xf0000000) { |
3431 Abort(kArrayIndexConstantValueTooBig); | 3431 Abort(kArrayIndexConstantValueTooBig); |
3432 } | 3432 } |
3433 } else { | 3433 } else { |
3434 scratch = ToRegister(instr->temp()); | 3434 scratch = ToRegister(instr->temp()); |
3435 key = ToRegister(instr->key()); | 3435 key = ToRegister(instr->key()); |
3436 } | 3436 } |
3437 | 3437 |
3438 MemOperand mem_op = | 3438 MemOperand mem_op = |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3515 STATIC_ASSERT(kSmiTag == 0); | 3515 STATIC_ASSERT(kSmiTag == 0); |
3516 int element_size_shift = ElementsKindToShiftSize(elements_kind); | 3516 int element_size_shift = ElementsKindToShiftSize(elements_kind); |
3517 | 3517 |
3518 // Even though the HLoad/StoreKeyed instructions force the input | 3518 // Even though the HLoad/StoreKeyed instructions force the input |
3519 // representation for the key to be an integer, the input gets replaced during | 3519 // representation for the key to be an integer, the input gets replaced during |
3520 // bounds check elimination with the index argument to the bounds check, which | 3520 // bounds check elimination with the index argument to the bounds check, which |
3521 // can be tagged, so that case must be handled here, too. | 3521 // can be tagged, so that case must be handled here, too. |
3522 if (key_is_tagged) { | 3522 if (key_is_tagged) { |
3523 __ Add(base, elements, Operand::UntagSmiAndScale(key, element_size_shift)); | 3523 __ Add(base, elements, Operand::UntagSmiAndScale(key, element_size_shift)); |
3524 if (representation.IsInteger32()) { | 3524 if (representation.IsInteger32()) { |
3525 ASSERT(elements_kind == FAST_SMI_ELEMENTS); | 3525 DCHECK(elements_kind == FAST_SMI_ELEMENTS); |
3526 // Read or write only the smi payload in the case of fast smi arrays. | 3526 // Read or write only the smi payload in the case of fast smi arrays. |
3527 return UntagSmiMemOperand(base, base_offset); | 3527 return UntagSmiMemOperand(base, base_offset); |
3528 } else { | 3528 } else { |
3529 return MemOperand(base, base_offset); | 3529 return MemOperand(base, base_offset); |
3530 } | 3530 } |
3531 } else { | 3531 } else { |
3532 // Sign extend key because it could be a 32-bit negative value or contain | 3532 // Sign extend key because it could be a 32-bit negative value or contain |
3533 // garbage in the top 32-bits. The address computation happens in 64-bit. | 3533 // garbage in the top 32-bits. The address computation happens in 64-bit. |
3534 ASSERT((element_size_shift >= 0) && (element_size_shift <= 4)); | 3534 DCHECK((element_size_shift >= 0) && (element_size_shift <= 4)); |
3535 if (representation.IsInteger32()) { | 3535 if (representation.IsInteger32()) { |
3536 ASSERT(elements_kind == FAST_SMI_ELEMENTS); | 3536 DCHECK(elements_kind == FAST_SMI_ELEMENTS); |
3537 // Read or write only the smi payload in the case of fast smi arrays. | 3537 // Read or write only the smi payload in the case of fast smi arrays. |
3538 __ Add(base, elements, Operand(key, SXTW, element_size_shift)); | 3538 __ Add(base, elements, Operand(key, SXTW, element_size_shift)); |
3539 return UntagSmiMemOperand(base, base_offset); | 3539 return UntagSmiMemOperand(base, base_offset); |
3540 } else { | 3540 } else { |
3541 __ Add(base, elements, base_offset); | 3541 __ Add(base, elements, base_offset); |
3542 return MemOperand(base, key, SXTW, element_size_shift); | 3542 return MemOperand(base, key, SXTW, element_size_shift); |
3543 } | 3543 } |
3544 } | 3544 } |
3545 } | 3545 } |
3546 | 3546 |
3547 | 3547 |
3548 void LCodeGen::DoLoadKeyedFixedDouble(LLoadKeyedFixedDouble* instr) { | 3548 void LCodeGen::DoLoadKeyedFixedDouble(LLoadKeyedFixedDouble* instr) { |
3549 Register elements = ToRegister(instr->elements()); | 3549 Register elements = ToRegister(instr->elements()); |
3550 DoubleRegister result = ToDoubleRegister(instr->result()); | 3550 DoubleRegister result = ToDoubleRegister(instr->result()); |
3551 MemOperand mem_op; | 3551 MemOperand mem_op; |
3552 | 3552 |
3553 if (instr->key()->IsConstantOperand()) { | 3553 if (instr->key()->IsConstantOperand()) { |
3554 ASSERT(instr->hydrogen()->RequiresHoleCheck() || | 3554 DCHECK(instr->hydrogen()->RequiresHoleCheck() || |
3555 (instr->temp() == NULL)); | 3555 (instr->temp() == NULL)); |
3556 | 3556 |
3557 int constant_key = ToInteger32(LConstantOperand::cast(instr->key())); | 3557 int constant_key = ToInteger32(LConstantOperand::cast(instr->key())); |
3558 if (constant_key & 0xf0000000) { | 3558 if (constant_key & 0xf0000000) { |
3559 Abort(kArrayIndexConstantValueTooBig); | 3559 Abort(kArrayIndexConstantValueTooBig); |
3560 } | 3560 } |
3561 int offset = instr->base_offset() + constant_key * kDoubleSize; | 3561 int offset = instr->base_offset() + constant_key * kDoubleSize; |
3562 mem_op = MemOperand(elements, offset); | 3562 mem_op = MemOperand(elements, offset); |
3563 } else { | 3563 } else { |
3564 Register load_base = ToRegister(instr->temp()); | 3564 Register load_base = ToRegister(instr->temp()); |
(...skipping 19 matching lines...) Expand all Loading... |
3584 } | 3584 } |
3585 | 3585 |
3586 | 3586 |
3587 void LCodeGen::DoLoadKeyedFixed(LLoadKeyedFixed* instr) { | 3587 void LCodeGen::DoLoadKeyedFixed(LLoadKeyedFixed* instr) { |
3588 Register elements = ToRegister(instr->elements()); | 3588 Register elements = ToRegister(instr->elements()); |
3589 Register result = ToRegister(instr->result()); | 3589 Register result = ToRegister(instr->result()); |
3590 MemOperand mem_op; | 3590 MemOperand mem_op; |
3591 | 3591 |
3592 Representation representation = instr->hydrogen()->representation(); | 3592 Representation representation = instr->hydrogen()->representation(); |
3593 if (instr->key()->IsConstantOperand()) { | 3593 if (instr->key()->IsConstantOperand()) { |
3594 ASSERT(instr->temp() == NULL); | 3594 DCHECK(instr->temp() == NULL); |
3595 LConstantOperand* const_operand = LConstantOperand::cast(instr->key()); | 3595 LConstantOperand* const_operand = LConstantOperand::cast(instr->key()); |
3596 int offset = instr->base_offset() + | 3596 int offset = instr->base_offset() + |
3597 ToInteger32(const_operand) * kPointerSize; | 3597 ToInteger32(const_operand) * kPointerSize; |
3598 if (representation.IsInteger32()) { | 3598 if (representation.IsInteger32()) { |
3599 ASSERT(instr->hydrogen()->elements_kind() == FAST_SMI_ELEMENTS); | 3599 DCHECK(instr->hydrogen()->elements_kind() == FAST_SMI_ELEMENTS); |
3600 STATIC_ASSERT(static_cast<unsigned>(kSmiValueSize) == kWRegSizeInBits); | 3600 STATIC_ASSERT(static_cast<unsigned>(kSmiValueSize) == kWRegSizeInBits); |
3601 STATIC_ASSERT(kSmiTag == 0); | 3601 STATIC_ASSERT(kSmiTag == 0); |
3602 mem_op = UntagSmiMemOperand(elements, offset); | 3602 mem_op = UntagSmiMemOperand(elements, offset); |
3603 } else { | 3603 } else { |
3604 mem_op = MemOperand(elements, offset); | 3604 mem_op = MemOperand(elements, offset); |
3605 } | 3605 } |
3606 } else { | 3606 } else { |
3607 Register load_base = ToRegister(instr->temp()); | 3607 Register load_base = ToRegister(instr->temp()); |
3608 Register key = ToRegister(instr->key()); | 3608 Register key = ToRegister(instr->key()); |
3609 bool key_is_tagged = instr->hydrogen()->key()->representation().IsSmi(); | 3609 bool key_is_tagged = instr->hydrogen()->key()->representation().IsSmi(); |
(...skipping 10 matching lines...) Expand all Loading... |
3620 DeoptimizeIfNotSmi(result, instr->environment()); | 3620 DeoptimizeIfNotSmi(result, instr->environment()); |
3621 } else { | 3621 } else { |
3622 DeoptimizeIfRoot(result, Heap::kTheHoleValueRootIndex, | 3622 DeoptimizeIfRoot(result, Heap::kTheHoleValueRootIndex, |
3623 instr->environment()); | 3623 instr->environment()); |
3624 } | 3624 } |
3625 } | 3625 } |
3626 } | 3626 } |
3627 | 3627 |
3628 | 3628 |
3629 void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) { | 3629 void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) { |
3630 ASSERT(ToRegister(instr->context()).is(cp)); | 3630 DCHECK(ToRegister(instr->context()).is(cp)); |
3631 ASSERT(ToRegister(instr->object()).is(LoadIC::ReceiverRegister())); | 3631 DCHECK(ToRegister(instr->object()).is(LoadIC::ReceiverRegister())); |
3632 ASSERT(ToRegister(instr->key()).is(LoadIC::NameRegister())); | 3632 DCHECK(ToRegister(instr->key()).is(LoadIC::NameRegister())); |
3633 if (FLAG_vector_ics) { | 3633 if (FLAG_vector_ics) { |
3634 Register vector = ToRegister(instr->temp_vector()); | 3634 Register vector = ToRegister(instr->temp_vector()); |
3635 ASSERT(vector.is(LoadIC::VectorRegister())); | 3635 DCHECK(vector.is(LoadIC::VectorRegister())); |
3636 __ Mov(vector, instr->hydrogen()->feedback_vector()); | 3636 __ Mov(vector, instr->hydrogen()->feedback_vector()); |
3637 // No need to allocate this register. | 3637 // No need to allocate this register. |
3638 ASSERT(LoadIC::SlotRegister().is(x0)); | 3638 DCHECK(LoadIC::SlotRegister().is(x0)); |
3639 __ Mov(LoadIC::SlotRegister(), | 3639 __ Mov(LoadIC::SlotRegister(), |
3640 Smi::FromInt(instr->hydrogen()->slot())); | 3640 Smi::FromInt(instr->hydrogen()->slot())); |
3641 } | 3641 } |
3642 | 3642 |
3643 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); | 3643 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); |
3644 CallCode(ic, RelocInfo::CODE_TARGET, instr); | 3644 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
3645 | 3645 |
3646 ASSERT(ToRegister(instr->result()).Is(x0)); | 3646 DCHECK(ToRegister(instr->result()).Is(x0)); |
3647 } | 3647 } |
3648 | 3648 |
3649 | 3649 |
3650 void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) { | 3650 void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) { |
3651 HObjectAccess access = instr->hydrogen()->access(); | 3651 HObjectAccess access = instr->hydrogen()->access(); |
3652 int offset = access.offset(); | 3652 int offset = access.offset(); |
3653 Register object = ToRegister(instr->object()); | 3653 Register object = ToRegister(instr->object()); |
3654 | 3654 |
3655 if (access.IsExternalMemory()) { | 3655 if (access.IsExternalMemory()) { |
3656 Register result = ToRegister(instr->result()); | 3656 Register result = ToRegister(instr->result()); |
(...skipping 24 matching lines...) Expand all Loading... |
3681 STATIC_ASSERT(kSmiTag == 0); | 3681 STATIC_ASSERT(kSmiTag == 0); |
3682 __ Load(result, UntagSmiFieldMemOperand(source, offset), | 3682 __ Load(result, UntagSmiFieldMemOperand(source, offset), |
3683 Representation::Integer32()); | 3683 Representation::Integer32()); |
3684 } else { | 3684 } else { |
3685 __ Load(result, FieldMemOperand(source, offset), access.representation()); | 3685 __ Load(result, FieldMemOperand(source, offset), access.representation()); |
3686 } | 3686 } |
3687 } | 3687 } |
3688 | 3688 |
3689 | 3689 |
3690 void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) { | 3690 void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) { |
3691 ASSERT(ToRegister(instr->context()).is(cp)); | 3691 DCHECK(ToRegister(instr->context()).is(cp)); |
3692 // LoadIC expects name and receiver in registers. | 3692 // LoadIC expects name and receiver in registers. |
3693 ASSERT(ToRegister(instr->object()).is(LoadIC::ReceiverRegister())); | 3693 DCHECK(ToRegister(instr->object()).is(LoadIC::ReceiverRegister())); |
3694 __ Mov(LoadIC::NameRegister(), Operand(instr->name())); | 3694 __ Mov(LoadIC::NameRegister(), Operand(instr->name())); |
3695 if (FLAG_vector_ics) { | 3695 if (FLAG_vector_ics) { |
3696 Register vector = ToRegister(instr->temp_vector()); | 3696 Register vector = ToRegister(instr->temp_vector()); |
3697 ASSERT(vector.is(LoadIC::VectorRegister())); | 3697 DCHECK(vector.is(LoadIC::VectorRegister())); |
3698 __ Mov(vector, instr->hydrogen()->feedback_vector()); | 3698 __ Mov(vector, instr->hydrogen()->feedback_vector()); |
3699 // No need to allocate this register. | 3699 // No need to allocate this register. |
3700 ASSERT(LoadIC::SlotRegister().is(x0)); | 3700 DCHECK(LoadIC::SlotRegister().is(x0)); |
3701 __ Mov(LoadIC::SlotRegister(), | 3701 __ Mov(LoadIC::SlotRegister(), |
3702 Smi::FromInt(instr->hydrogen()->slot())); | 3702 Smi::FromInt(instr->hydrogen()->slot())); |
3703 } | 3703 } |
3704 | 3704 |
3705 Handle<Code> ic = LoadIC::initialize_stub(isolate(), NOT_CONTEXTUAL); | 3705 Handle<Code> ic = LoadIC::initialize_stub(isolate(), NOT_CONTEXTUAL); |
3706 CallCode(ic, RelocInfo::CODE_TARGET, instr); | 3706 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
3707 | 3707 |
3708 ASSERT(ToRegister(instr->result()).is(x0)); | 3708 DCHECK(ToRegister(instr->result()).is(x0)); |
3709 } | 3709 } |
3710 | 3710 |
3711 | 3711 |
3712 void LCodeGen::DoLoadRoot(LLoadRoot* instr) { | 3712 void LCodeGen::DoLoadRoot(LLoadRoot* instr) { |
3713 Register result = ToRegister(instr->result()); | 3713 Register result = ToRegister(instr->result()); |
3714 __ LoadRoot(result, instr->index()); | 3714 __ LoadRoot(result, instr->index()); |
3715 } | 3715 } |
3716 | 3716 |
3717 | 3717 |
3718 void LCodeGen::DoMapEnumLength(LMapEnumLength* instr) { | 3718 void LCodeGen::DoMapEnumLength(LMapEnumLength* instr) { |
(...skipping 25 matching lines...) Expand all Loading... |
3744 Label* allocation_entry) { | 3744 Label* allocation_entry) { |
3745 // Handle the tricky cases of MathAbsTagged: | 3745 // Handle the tricky cases of MathAbsTagged: |
3746 // - HeapNumber inputs. | 3746 // - HeapNumber inputs. |
3747 // - Negative inputs produce a positive result, so a new HeapNumber is | 3747 // - Negative inputs produce a positive result, so a new HeapNumber is |
3748 // allocated to hold it. | 3748 // allocated to hold it. |
3749 // - Positive inputs are returned as-is, since there is no need to allocate | 3749 // - Positive inputs are returned as-is, since there is no need to allocate |
3750 // a new HeapNumber for the result. | 3750 // a new HeapNumber for the result. |
3751 // - The (smi) input -0x80000000, produces +0x80000000, which does not fit | 3751 // - The (smi) input -0x80000000, produces +0x80000000, which does not fit |
3752 // a smi. In this case, the inline code sets the result and jumps directly | 3752 // a smi. In this case, the inline code sets the result and jumps directly |
3753 // to the allocation_entry label. | 3753 // to the allocation_entry label. |
3754 ASSERT(instr->context() != NULL); | 3754 DCHECK(instr->context() != NULL); |
3755 ASSERT(ToRegister(instr->context()).is(cp)); | 3755 DCHECK(ToRegister(instr->context()).is(cp)); |
3756 Register input = ToRegister(instr->value()); | 3756 Register input = ToRegister(instr->value()); |
3757 Register temp1 = ToRegister(instr->temp1()); | 3757 Register temp1 = ToRegister(instr->temp1()); |
3758 Register temp2 = ToRegister(instr->temp2()); | 3758 Register temp2 = ToRegister(instr->temp2()); |
3759 Register result_bits = ToRegister(instr->temp3()); | 3759 Register result_bits = ToRegister(instr->temp3()); |
3760 Register result = ToRegister(instr->result()); | 3760 Register result = ToRegister(instr->result()); |
3761 | 3761 |
3762 Label runtime_allocation; | 3762 Label runtime_allocation; |
3763 | 3763 |
3764 // Deoptimize if the input is not a HeapNumber. | 3764 // Deoptimize if the input is not a HeapNumber. |
3765 __ Ldr(temp1, FieldMemOperand(input, HeapObject::kMapOffset)); | 3765 __ Ldr(temp1, FieldMemOperand(input, HeapObject::kMapOffset)); |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3819 } | 3819 } |
3820 virtual LInstruction* instr() { return instr_; } | 3820 virtual LInstruction* instr() { return instr_; } |
3821 Label* allocation_entry() { return &allocation; } | 3821 Label* allocation_entry() { return &allocation; } |
3822 private: | 3822 private: |
3823 LMathAbsTagged* instr_; | 3823 LMathAbsTagged* instr_; |
3824 Label allocation; | 3824 Label allocation; |
3825 }; | 3825 }; |
3826 | 3826 |
3827 // TODO(jbramley): The early-exit mechanism would skip the new frame handling | 3827 // TODO(jbramley): The early-exit mechanism would skip the new frame handling |
3828 // in GenerateDeferredCode. Tidy this up. | 3828 // in GenerateDeferredCode. Tidy this up. |
3829 ASSERT(!NeedsDeferredFrame()); | 3829 DCHECK(!NeedsDeferredFrame()); |
3830 | 3830 |
3831 DeferredMathAbsTagged* deferred = | 3831 DeferredMathAbsTagged* deferred = |
3832 new(zone()) DeferredMathAbsTagged(this, instr); | 3832 new(zone()) DeferredMathAbsTagged(this, instr); |
3833 | 3833 |
3834 ASSERT(instr->hydrogen()->value()->representation().IsTagged() || | 3834 DCHECK(instr->hydrogen()->value()->representation().IsTagged() || |
3835 instr->hydrogen()->value()->representation().IsSmi()); | 3835 instr->hydrogen()->value()->representation().IsSmi()); |
3836 Register input = ToRegister(instr->value()); | 3836 Register input = ToRegister(instr->value()); |
3837 Register result_bits = ToRegister(instr->temp3()); | 3837 Register result_bits = ToRegister(instr->temp3()); |
3838 Register result = ToRegister(instr->result()); | 3838 Register result = ToRegister(instr->result()); |
3839 Label done; | 3839 Label done; |
3840 | 3840 |
3841 // Handle smis inline. | 3841 // Handle smis inline. |
3842 // We can treat smis as 64-bit integers, since the (low-order) tag bits will | 3842 // We can treat smis as 64-bit integers, since the (low-order) tag bits will |
3843 // never get set by the negation. This is therefore the same as the Integer32 | 3843 // never get set by the negation. This is therefore the same as the Integer32 |
3844 // case in DoMathAbs, except that it operates on 64-bit values. | 3844 // case in DoMathAbs, except that it operates on 64-bit values. |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3943 | 3943 |
3944 __ Asr(result, result, shift); | 3944 __ Asr(result, result, shift); |
3945 __ Csel(result, result, kMinInt / divisor, vc); | 3945 __ Csel(result, result, kMinInt / divisor, vc); |
3946 } | 3946 } |
3947 | 3947 |
3948 | 3948 |
3949 void LCodeGen::DoFlooringDivByConstI(LFlooringDivByConstI* instr) { | 3949 void LCodeGen::DoFlooringDivByConstI(LFlooringDivByConstI* instr) { |
3950 Register dividend = ToRegister32(instr->dividend()); | 3950 Register dividend = ToRegister32(instr->dividend()); |
3951 int32_t divisor = instr->divisor(); | 3951 int32_t divisor = instr->divisor(); |
3952 Register result = ToRegister32(instr->result()); | 3952 Register result = ToRegister32(instr->result()); |
3953 ASSERT(!AreAliased(dividend, result)); | 3953 DCHECK(!AreAliased(dividend, result)); |
3954 | 3954 |
3955 if (divisor == 0) { | 3955 if (divisor == 0) { |
3956 Deoptimize(instr->environment()); | 3956 Deoptimize(instr->environment()); |
3957 return; | 3957 return; |
3958 } | 3958 } |
3959 | 3959 |
3960 // Check for (0 / -x) that will produce negative zero. | 3960 // Check for (0 / -x) that will produce negative zero. |
3961 HMathFloorOfDiv* hdiv = instr->hydrogen(); | 3961 HMathFloorOfDiv* hdiv = instr->hydrogen(); |
3962 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) { | 3962 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) { |
3963 DeoptimizeIfZero(dividend, instr->environment()); | 3963 DeoptimizeIfZero(dividend, instr->environment()); |
3964 } | 3964 } |
3965 | 3965 |
3966 // Easy case: We need no dynamic check for the dividend and the flooring | 3966 // Easy case: We need no dynamic check for the dividend and the flooring |
3967 // division is the same as the truncating division. | 3967 // division is the same as the truncating division. |
3968 if ((divisor > 0 && !hdiv->CheckFlag(HValue::kLeftCanBeNegative)) || | 3968 if ((divisor > 0 && !hdiv->CheckFlag(HValue::kLeftCanBeNegative)) || |
3969 (divisor < 0 && !hdiv->CheckFlag(HValue::kLeftCanBePositive))) { | 3969 (divisor < 0 && !hdiv->CheckFlag(HValue::kLeftCanBePositive))) { |
3970 __ TruncatingDiv(result, dividend, Abs(divisor)); | 3970 __ TruncatingDiv(result, dividend, Abs(divisor)); |
3971 if (divisor < 0) __ Neg(result, result); | 3971 if (divisor < 0) __ Neg(result, result); |
3972 return; | 3972 return; |
3973 } | 3973 } |
3974 | 3974 |
3975 // In the general case we may need to adjust before and after the truncating | 3975 // In the general case we may need to adjust before and after the truncating |
3976 // division to get a flooring division. | 3976 // division to get a flooring division. |
3977 Register temp = ToRegister32(instr->temp()); | 3977 Register temp = ToRegister32(instr->temp()); |
3978 ASSERT(!AreAliased(temp, dividend, result)); | 3978 DCHECK(!AreAliased(temp, dividend, result)); |
3979 Label needs_adjustment, done; | 3979 Label needs_adjustment, done; |
3980 __ Cmp(dividend, 0); | 3980 __ Cmp(dividend, 0); |
3981 __ B(divisor > 0 ? lt : gt, &needs_adjustment); | 3981 __ B(divisor > 0 ? lt : gt, &needs_adjustment); |
3982 __ TruncatingDiv(result, dividend, Abs(divisor)); | 3982 __ TruncatingDiv(result, dividend, Abs(divisor)); |
3983 if (divisor < 0) __ Neg(result, result); | 3983 if (divisor < 0) __ Neg(result, result); |
3984 __ B(&done); | 3984 __ B(&done); |
3985 __ Bind(&needs_adjustment); | 3985 __ Bind(&needs_adjustment); |
3986 __ Add(temp, dividend, Operand(divisor > 0 ? 1 : -1)); | 3986 __ Add(temp, dividend, Operand(divisor > 0 ? 1 : -1)); |
3987 __ TruncatingDiv(result, temp, Abs(divisor)); | 3987 __ TruncatingDiv(result, temp, Abs(divisor)); |
3988 if (divisor < 0) __ Neg(result, result); | 3988 if (divisor < 0) __ Neg(result, result); |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4031 // Check if the result needs to be corrected. | 4031 // Check if the result needs to be corrected. |
4032 __ Msub(remainder, result, divisor, dividend); | 4032 __ Msub(remainder, result, divisor, dividend); |
4033 __ Cbz(remainder, &done); | 4033 __ Cbz(remainder, &done); |
4034 __ Sub(result, result, 1); | 4034 __ Sub(result, result, 1); |
4035 | 4035 |
4036 __ Bind(&done); | 4036 __ Bind(&done); |
4037 } | 4037 } |
4038 | 4038 |
4039 | 4039 |
4040 void LCodeGen::DoMathLog(LMathLog* instr) { | 4040 void LCodeGen::DoMathLog(LMathLog* instr) { |
4041 ASSERT(instr->IsMarkedAsCall()); | 4041 DCHECK(instr->IsMarkedAsCall()); |
4042 ASSERT(ToDoubleRegister(instr->value()).is(d0)); | 4042 DCHECK(ToDoubleRegister(instr->value()).is(d0)); |
4043 __ CallCFunction(ExternalReference::math_log_double_function(isolate()), | 4043 __ CallCFunction(ExternalReference::math_log_double_function(isolate()), |
4044 0, 1); | 4044 0, 1); |
4045 ASSERT(ToDoubleRegister(instr->result()).Is(d0)); | 4045 DCHECK(ToDoubleRegister(instr->result()).Is(d0)); |
4046 } | 4046 } |
4047 | 4047 |
4048 | 4048 |
4049 void LCodeGen::DoMathClz32(LMathClz32* instr) { | 4049 void LCodeGen::DoMathClz32(LMathClz32* instr) { |
4050 Register input = ToRegister32(instr->value()); | 4050 Register input = ToRegister32(instr->value()); |
4051 Register result = ToRegister32(instr->result()); | 4051 Register result = ToRegister32(instr->result()); |
4052 __ Clz(result, input); | 4052 __ Clz(result, input); |
4053 } | 4053 } |
4054 | 4054 |
4055 | 4055 |
(...skipping 18 matching lines...) Expand all Loading... |
4074 __ Fsqrt(result, double_scratch()); | 4074 __ Fsqrt(result, double_scratch()); |
4075 | 4075 |
4076 __ Bind(&done); | 4076 __ Bind(&done); |
4077 } | 4077 } |
4078 | 4078 |
4079 | 4079 |
4080 void LCodeGen::DoPower(LPower* instr) { | 4080 void LCodeGen::DoPower(LPower* instr) { |
4081 Representation exponent_type = instr->hydrogen()->right()->representation(); | 4081 Representation exponent_type = instr->hydrogen()->right()->representation(); |
4082 // Having marked this as a call, we can use any registers. | 4082 // Having marked this as a call, we can use any registers. |
4083 // Just make sure that the input/output registers are the expected ones. | 4083 // Just make sure that the input/output registers are the expected ones. |
4084 ASSERT(!instr->right()->IsDoubleRegister() || | 4084 DCHECK(!instr->right()->IsDoubleRegister() || |
4085 ToDoubleRegister(instr->right()).is(d1)); | 4085 ToDoubleRegister(instr->right()).is(d1)); |
4086 ASSERT(exponent_type.IsInteger32() || !instr->right()->IsRegister() || | 4086 DCHECK(exponent_type.IsInteger32() || !instr->right()->IsRegister() || |
4087 ToRegister(instr->right()).is(x11)); | 4087 ToRegister(instr->right()).is(x11)); |
4088 ASSERT(!exponent_type.IsInteger32() || ToRegister(instr->right()).is(x12)); | 4088 DCHECK(!exponent_type.IsInteger32() || ToRegister(instr->right()).is(x12)); |
4089 ASSERT(ToDoubleRegister(instr->left()).is(d0)); | 4089 DCHECK(ToDoubleRegister(instr->left()).is(d0)); |
4090 ASSERT(ToDoubleRegister(instr->result()).is(d0)); | 4090 DCHECK(ToDoubleRegister(instr->result()).is(d0)); |
4091 | 4091 |
4092 if (exponent_type.IsSmi()) { | 4092 if (exponent_type.IsSmi()) { |
4093 MathPowStub stub(isolate(), MathPowStub::TAGGED); | 4093 MathPowStub stub(isolate(), MathPowStub::TAGGED); |
4094 __ CallStub(&stub); | 4094 __ CallStub(&stub); |
4095 } else if (exponent_type.IsTagged()) { | 4095 } else if (exponent_type.IsTagged()) { |
4096 Label no_deopt; | 4096 Label no_deopt; |
4097 __ JumpIfSmi(x11, &no_deopt); | 4097 __ JumpIfSmi(x11, &no_deopt); |
4098 __ Ldr(x0, FieldMemOperand(x11, HeapObject::kMapOffset)); | 4098 __ Ldr(x0, FieldMemOperand(x11, HeapObject::kMapOffset)); |
4099 DeoptimizeIfNotRoot(x0, Heap::kHeapNumberMapRootIndex, | 4099 DeoptimizeIfNotRoot(x0, Heap::kHeapNumberMapRootIndex, |
4100 instr->environment()); | 4100 instr->environment()); |
4101 __ Bind(&no_deopt); | 4101 __ Bind(&no_deopt); |
4102 MathPowStub stub(isolate(), MathPowStub::TAGGED); | 4102 MathPowStub stub(isolate(), MathPowStub::TAGGED); |
4103 __ CallStub(&stub); | 4103 __ CallStub(&stub); |
4104 } else if (exponent_type.IsInteger32()) { | 4104 } else if (exponent_type.IsInteger32()) { |
4105 // Ensure integer exponent has no garbage in top 32-bits, as MathPowStub | 4105 // Ensure integer exponent has no garbage in top 32-bits, as MathPowStub |
4106 // supports large integer exponents. | 4106 // supports large integer exponents. |
4107 Register exponent = ToRegister(instr->right()); | 4107 Register exponent = ToRegister(instr->right()); |
4108 __ Sxtw(exponent, exponent); | 4108 __ Sxtw(exponent, exponent); |
4109 MathPowStub stub(isolate(), MathPowStub::INTEGER); | 4109 MathPowStub stub(isolate(), MathPowStub::INTEGER); |
4110 __ CallStub(&stub); | 4110 __ CallStub(&stub); |
4111 } else { | 4111 } else { |
4112 ASSERT(exponent_type.IsDouble()); | 4112 DCHECK(exponent_type.IsDouble()); |
4113 MathPowStub stub(isolate(), MathPowStub::DOUBLE); | 4113 MathPowStub stub(isolate(), MathPowStub::DOUBLE); |
4114 __ CallStub(&stub); | 4114 __ CallStub(&stub); |
4115 } | 4115 } |
4116 } | 4116 } |
4117 | 4117 |
4118 | 4118 |
4119 void LCodeGen::DoMathRoundD(LMathRoundD* instr) { | 4119 void LCodeGen::DoMathRoundD(LMathRoundD* instr) { |
4120 DoubleRegister input = ToDoubleRegister(instr->value()); | 4120 DoubleRegister input = ToDoubleRegister(instr->value()); |
4121 DoubleRegister result = ToDoubleRegister(instr->result()); | 4121 DoubleRegister result = ToDoubleRegister(instr->result()); |
4122 DoubleRegister scratch_d = double_scratch(); | 4122 DoubleRegister scratch_d = double_scratch(); |
4123 | 4123 |
4124 ASSERT(!AreAliased(input, result, scratch_d)); | 4124 DCHECK(!AreAliased(input, result, scratch_d)); |
4125 | 4125 |
4126 Label done; | 4126 Label done; |
4127 | 4127 |
4128 __ Frinta(result, input); | 4128 __ Frinta(result, input); |
4129 __ Fcmp(input, 0.0); | 4129 __ Fcmp(input, 0.0); |
4130 __ Fccmp(result, input, ZFlag, lt); | 4130 __ Fccmp(result, input, ZFlag, lt); |
4131 // The result is correct if the input was in [-0, +infinity], or was a | 4131 // The result is correct if the input was in [-0, +infinity], or was a |
4132 // negative integral value. | 4132 // negative integral value. |
4133 __ B(eq, &done); | 4133 __ B(eq, &done); |
4134 | 4134 |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4225 __ Cmp(left, right); | 4225 __ Cmp(left, right); |
4226 __ Csel(result, left, right, (op == HMathMinMax::kMathMax) ? ge : le); | 4226 __ Csel(result, left, right, (op == HMathMinMax::kMathMax) ? ge : le); |
4227 } else if (instr->hydrogen()->representation().IsSmi()) { | 4227 } else if (instr->hydrogen()->representation().IsSmi()) { |
4228 Register result = ToRegister(instr->result()); | 4228 Register result = ToRegister(instr->result()); |
4229 Register left = ToRegister(instr->left()); | 4229 Register left = ToRegister(instr->left()); |
4230 Operand right = ToOperand(instr->right()); | 4230 Operand right = ToOperand(instr->right()); |
4231 | 4231 |
4232 __ Cmp(left, right); | 4232 __ Cmp(left, right); |
4233 __ Csel(result, left, right, (op == HMathMinMax::kMathMax) ? ge : le); | 4233 __ Csel(result, left, right, (op == HMathMinMax::kMathMax) ? ge : le); |
4234 } else { | 4234 } else { |
4235 ASSERT(instr->hydrogen()->representation().IsDouble()); | 4235 DCHECK(instr->hydrogen()->representation().IsDouble()); |
4236 DoubleRegister result = ToDoubleRegister(instr->result()); | 4236 DoubleRegister result = ToDoubleRegister(instr->result()); |
4237 DoubleRegister left = ToDoubleRegister(instr->left()); | 4237 DoubleRegister left = ToDoubleRegister(instr->left()); |
4238 DoubleRegister right = ToDoubleRegister(instr->right()); | 4238 DoubleRegister right = ToDoubleRegister(instr->right()); |
4239 | 4239 |
4240 if (op == HMathMinMax::kMathMax) { | 4240 if (op == HMathMinMax::kMathMax) { |
4241 __ Fmax(result, left, right); | 4241 __ Fmax(result, left, right); |
4242 } else { | 4242 } else { |
4243 ASSERT(op == HMathMinMax::kMathMin); | 4243 DCHECK(op == HMathMinMax::kMathMin); |
4244 __ Fmin(result, left, right); | 4244 __ Fmin(result, left, right); |
4245 } | 4245 } |
4246 } | 4246 } |
4247 } | 4247 } |
4248 | 4248 |
4249 | 4249 |
4250 void LCodeGen::DoModByPowerOf2I(LModByPowerOf2I* instr) { | 4250 void LCodeGen::DoModByPowerOf2I(LModByPowerOf2I* instr) { |
4251 Register dividend = ToRegister32(instr->dividend()); | 4251 Register dividend = ToRegister32(instr->dividend()); |
4252 int32_t divisor = instr->divisor(); | 4252 int32_t divisor = instr->divisor(); |
4253 ASSERT(dividend.is(ToRegister32(instr->result()))); | 4253 DCHECK(dividend.is(ToRegister32(instr->result()))); |
4254 | 4254 |
4255 // Theoretically, a variation of the branch-free code for integer division by | 4255 // Theoretically, a variation of the branch-free code for integer division by |
4256 // a power of 2 (calculating the remainder via an additional multiplication | 4256 // a power of 2 (calculating the remainder via an additional multiplication |
4257 // (which gets simplified to an 'and') and subtraction) should be faster, and | 4257 // (which gets simplified to an 'and') and subtraction) should be faster, and |
4258 // this is exactly what GCC and clang emit. Nevertheless, benchmarks seem to | 4258 // this is exactly what GCC and clang emit. Nevertheless, benchmarks seem to |
4259 // indicate that positive dividends are heavily favored, so the branching | 4259 // indicate that positive dividends are heavily favored, so the branching |
4260 // version performs better. | 4260 // version performs better. |
4261 HMod* hmod = instr->hydrogen(); | 4261 HMod* hmod = instr->hydrogen(); |
4262 int32_t mask = divisor < 0 ? -(divisor + 1) : (divisor - 1); | 4262 int32_t mask = divisor < 0 ? -(divisor + 1) : (divisor - 1); |
4263 Label dividend_is_not_negative, done; | 4263 Label dividend_is_not_negative, done; |
(...skipping 13 matching lines...) Expand all Loading... |
4277 __ And(dividend, dividend, mask); | 4277 __ And(dividend, dividend, mask); |
4278 __ bind(&done); | 4278 __ bind(&done); |
4279 } | 4279 } |
4280 | 4280 |
4281 | 4281 |
4282 void LCodeGen::DoModByConstI(LModByConstI* instr) { | 4282 void LCodeGen::DoModByConstI(LModByConstI* instr) { |
4283 Register dividend = ToRegister32(instr->dividend()); | 4283 Register dividend = ToRegister32(instr->dividend()); |
4284 int32_t divisor = instr->divisor(); | 4284 int32_t divisor = instr->divisor(); |
4285 Register result = ToRegister32(instr->result()); | 4285 Register result = ToRegister32(instr->result()); |
4286 Register temp = ToRegister32(instr->temp()); | 4286 Register temp = ToRegister32(instr->temp()); |
4287 ASSERT(!AreAliased(dividend, result, temp)); | 4287 DCHECK(!AreAliased(dividend, result, temp)); |
4288 | 4288 |
4289 if (divisor == 0) { | 4289 if (divisor == 0) { |
4290 Deoptimize(instr->environment()); | 4290 Deoptimize(instr->environment()); |
4291 return; | 4291 return; |
4292 } | 4292 } |
4293 | 4293 |
4294 __ TruncatingDiv(result, dividend, Abs(divisor)); | 4294 __ TruncatingDiv(result, dividend, Abs(divisor)); |
4295 __ Sxtw(dividend.X(), dividend); | 4295 __ Sxtw(dividend.X(), dividend); |
4296 __ Mov(temp, Abs(divisor)); | 4296 __ Mov(temp, Abs(divisor)); |
4297 __ Smsubl(result.X(), result, temp, dividend.X()); | 4297 __ Smsubl(result.X(), result, temp, dividend.X()); |
(...skipping 23 matching lines...) Expand all Loading... |
4321 __ Msub(result, result, divisor, dividend); | 4321 __ Msub(result, result, divisor, dividend); |
4322 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 4322 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
4323 __ Cbnz(result, &done); | 4323 __ Cbnz(result, &done); |
4324 DeoptimizeIfNegative(dividend, instr->environment()); | 4324 DeoptimizeIfNegative(dividend, instr->environment()); |
4325 } | 4325 } |
4326 __ Bind(&done); | 4326 __ Bind(&done); |
4327 } | 4327 } |
4328 | 4328 |
4329 | 4329 |
4330 void LCodeGen::DoMulConstIS(LMulConstIS* instr) { | 4330 void LCodeGen::DoMulConstIS(LMulConstIS* instr) { |
4331 ASSERT(instr->hydrogen()->representation().IsSmiOrInteger32()); | 4331 DCHECK(instr->hydrogen()->representation().IsSmiOrInteger32()); |
4332 bool is_smi = instr->hydrogen()->representation().IsSmi(); | 4332 bool is_smi = instr->hydrogen()->representation().IsSmi(); |
4333 Register result = | 4333 Register result = |
4334 is_smi ? ToRegister(instr->result()) : ToRegister32(instr->result()); | 4334 is_smi ? ToRegister(instr->result()) : ToRegister32(instr->result()); |
4335 Register left = | 4335 Register left = |
4336 is_smi ? ToRegister(instr->left()) : ToRegister32(instr->left()) ; | 4336 is_smi ? ToRegister(instr->left()) : ToRegister32(instr->left()) ; |
4337 int32_t right = ToInteger32(instr->right()); | 4337 int32_t right = ToInteger32(instr->right()); |
4338 ASSERT((right > -kMaxInt) || (right < kMaxInt)); | 4338 DCHECK((right > -kMaxInt) || (right < kMaxInt)); |
4339 | 4339 |
4340 bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow); | 4340 bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow); |
4341 bool bailout_on_minus_zero = | 4341 bool bailout_on_minus_zero = |
4342 instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero); | 4342 instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero); |
4343 | 4343 |
4344 if (bailout_on_minus_zero) { | 4344 if (bailout_on_minus_zero) { |
4345 if (right < 0) { | 4345 if (right < 0) { |
4346 // The result is -0 if right is negative and left is zero. | 4346 // The result is -0 if right is negative and left is zero. |
4347 DeoptimizeIfZero(left, instr->environment()); | 4347 DeoptimizeIfZero(left, instr->environment()); |
4348 } else if (right == 0) { | 4348 } else if (right == 0) { |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4382 default: | 4382 default: |
4383 // Multiplication by constant powers of two (and some related values) | 4383 // Multiplication by constant powers of two (and some related values) |
4384 // can be done efficiently with shifted operands. | 4384 // can be done efficiently with shifted operands. |
4385 int32_t right_abs = Abs(right); | 4385 int32_t right_abs = Abs(right); |
4386 | 4386 |
4387 if (IsPowerOf2(right_abs)) { | 4387 if (IsPowerOf2(right_abs)) { |
4388 int right_log2 = WhichPowerOf2(right_abs); | 4388 int right_log2 = WhichPowerOf2(right_abs); |
4389 | 4389 |
4390 if (can_overflow) { | 4390 if (can_overflow) { |
4391 Register scratch = result; | 4391 Register scratch = result; |
4392 ASSERT(!AreAliased(scratch, left)); | 4392 DCHECK(!AreAliased(scratch, left)); |
4393 __ Cls(scratch, left); | 4393 __ Cls(scratch, left); |
4394 __ Cmp(scratch, right_log2); | 4394 __ Cmp(scratch, right_log2); |
4395 DeoptimizeIf(lt, instr->environment()); | 4395 DeoptimizeIf(lt, instr->environment()); |
4396 } | 4396 } |
4397 | 4397 |
4398 if (right >= 0) { | 4398 if (right >= 0) { |
4399 // result = left << log2(right) | 4399 // result = left << log2(right) |
4400 __ Lsl(result, left, right_log2); | 4400 __ Lsl(result, left, right_log2); |
4401 } else { | 4401 } else { |
4402 // result = -left << log2(-right) | 4402 // result = -left << log2(-right) |
4403 if (can_overflow) { | 4403 if (can_overflow) { |
4404 __ Negs(result, Operand(left, LSL, right_log2)); | 4404 __ Negs(result, Operand(left, LSL, right_log2)); |
4405 DeoptimizeIf(vs, instr->environment()); | 4405 DeoptimizeIf(vs, instr->environment()); |
4406 } else { | 4406 } else { |
4407 __ Neg(result, Operand(left, LSL, right_log2)); | 4407 __ Neg(result, Operand(left, LSL, right_log2)); |
4408 } | 4408 } |
4409 } | 4409 } |
4410 return; | 4410 return; |
4411 } | 4411 } |
4412 | 4412 |
4413 | 4413 |
4414 // For the following cases, we could perform a conservative overflow check | 4414 // For the following cases, we could perform a conservative overflow check |
4415 // with CLS as above. However the few cycles saved are likely not worth | 4415 // with CLS as above. However the few cycles saved are likely not worth |
4416 // the risk of deoptimizing more often than required. | 4416 // the risk of deoptimizing more often than required. |
4417 ASSERT(!can_overflow); | 4417 DCHECK(!can_overflow); |
4418 | 4418 |
4419 if (right >= 0) { | 4419 if (right >= 0) { |
4420 if (IsPowerOf2(right - 1)) { | 4420 if (IsPowerOf2(right - 1)) { |
4421 // result = left + left << log2(right - 1) | 4421 // result = left + left << log2(right - 1) |
4422 __ Add(result, left, Operand(left, LSL, WhichPowerOf2(right - 1))); | 4422 __ Add(result, left, Operand(left, LSL, WhichPowerOf2(right - 1))); |
4423 } else if (IsPowerOf2(right + 1)) { | 4423 } else if (IsPowerOf2(right + 1)) { |
4424 // result = -left + left << log2(right + 1) | 4424 // result = -left + left << log2(right + 1) |
4425 __ Sub(result, left, Operand(left, LSL, WhichPowerOf2(right + 1))); | 4425 __ Sub(result, left, Operand(left, LSL, WhichPowerOf2(right + 1))); |
4426 __ Neg(result, result); | 4426 __ Neg(result, result); |
4427 } else { | 4427 } else { |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4505 // multiply, giving a tagged result. | 4505 // multiply, giving a tagged result. |
4506 STATIC_ASSERT((kSmiShift % 2) == 0); | 4506 STATIC_ASSERT((kSmiShift % 2) == 0); |
4507 __ Asr(result, left, kSmiShift / 2); | 4507 __ Asr(result, left, kSmiShift / 2); |
4508 __ Mul(result, result, result); | 4508 __ Mul(result, result, result); |
4509 } else if (result.Is(left) && !left.Is(right)) { | 4509 } else if (result.Is(left) && !left.Is(right)) { |
4510 // Registers result and left alias, right is distinct: untag left into | 4510 // Registers result and left alias, right is distinct: untag left into |
4511 // result, and then multiply by right, giving a tagged result. | 4511 // result, and then multiply by right, giving a tagged result. |
4512 __ SmiUntag(result, left); | 4512 __ SmiUntag(result, left); |
4513 __ Mul(result, result, right); | 4513 __ Mul(result, result, right); |
4514 } else { | 4514 } else { |
4515 ASSERT(!left.Is(result)); | 4515 DCHECK(!left.Is(result)); |
4516 // Registers result and right alias, left is distinct, or all registers | 4516 // Registers result and right alias, left is distinct, or all registers |
4517 // are distinct: untag right into result, and then multiply by left, | 4517 // are distinct: untag right into result, and then multiply by left, |
4518 // giving a tagged result. | 4518 // giving a tagged result. |
4519 __ SmiUntag(result, right); | 4519 __ SmiUntag(result, right); |
4520 __ Mul(result, left, result); | 4520 __ Mul(result, left, result); |
4521 } | 4521 } |
4522 } | 4522 } |
4523 } | 4523 } |
4524 | 4524 |
4525 | 4525 |
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4685 __ Bind(&convert_undefined); | 4685 __ Bind(&convert_undefined); |
4686 DeoptimizeIfNotRoot(input, Heap::kUndefinedValueRootIndex, | 4686 DeoptimizeIfNotRoot(input, Heap::kUndefinedValueRootIndex, |
4687 instr->environment()); | 4687 instr->environment()); |
4688 | 4688 |
4689 __ LoadRoot(scratch, Heap::kNanValueRootIndex); | 4689 __ LoadRoot(scratch, Heap::kNanValueRootIndex); |
4690 __ Ldr(result, FieldMemOperand(scratch, HeapNumber::kValueOffset)); | 4690 __ Ldr(result, FieldMemOperand(scratch, HeapNumber::kValueOffset)); |
4691 __ B(&done); | 4691 __ B(&done); |
4692 } | 4692 } |
4693 | 4693 |
4694 } else { | 4694 } else { |
4695 ASSERT(mode == NUMBER_CANDIDATE_IS_SMI); | 4695 DCHECK(mode == NUMBER_CANDIDATE_IS_SMI); |
4696 // Fall through to load_smi. | 4696 // Fall through to load_smi. |
4697 } | 4697 } |
4698 | 4698 |
4699 // Smi to double register conversion. | 4699 // Smi to double register conversion. |
4700 __ Bind(&load_smi); | 4700 __ Bind(&load_smi); |
4701 __ SmiUntagToDouble(result, input); | 4701 __ SmiUntagToDouble(result, input); |
4702 | 4702 |
4703 __ Bind(&done); | 4703 __ Bind(&done); |
4704 } | 4704 } |
4705 | 4705 |
4706 | 4706 |
4707 void LCodeGen::DoOsrEntry(LOsrEntry* instr) { | 4707 void LCodeGen::DoOsrEntry(LOsrEntry* instr) { |
4708 // This is a pseudo-instruction that ensures that the environment here is | 4708 // This is a pseudo-instruction that ensures that the environment here is |
4709 // properly registered for deoptimization and records the assembler's PC | 4709 // properly registered for deoptimization and records the assembler's PC |
4710 // offset. | 4710 // offset. |
4711 LEnvironment* environment = instr->environment(); | 4711 LEnvironment* environment = instr->environment(); |
4712 | 4712 |
4713 // If the environment were already registered, we would have no way of | 4713 // If the environment were already registered, we would have no way of |
4714 // backpatching it with the spill slot operands. | 4714 // backpatching it with the spill slot operands. |
4715 ASSERT(!environment->HasBeenRegistered()); | 4715 DCHECK(!environment->HasBeenRegistered()); |
4716 RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt); | 4716 RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt); |
4717 | 4717 |
4718 GenerateOsrPrologue(); | 4718 GenerateOsrPrologue(); |
4719 } | 4719 } |
4720 | 4720 |
4721 | 4721 |
4722 void LCodeGen::DoParameter(LParameter* instr) { | 4722 void LCodeGen::DoParameter(LParameter* instr) { |
4723 // Nothing to do. | 4723 // Nothing to do. |
4724 } | 4724 } |
4725 | 4725 |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4844 } | 4844 } |
4845 | 4845 |
4846 | 4846 |
4847 void LCodeGen::DoSeqStringSetChar(LSeqStringSetChar* instr) { | 4847 void LCodeGen::DoSeqStringSetChar(LSeqStringSetChar* instr) { |
4848 String::Encoding encoding = instr->hydrogen()->encoding(); | 4848 String::Encoding encoding = instr->hydrogen()->encoding(); |
4849 Register string = ToRegister(instr->string()); | 4849 Register string = ToRegister(instr->string()); |
4850 Register value = ToRegister(instr->value()); | 4850 Register value = ToRegister(instr->value()); |
4851 Register temp = ToRegister(instr->temp()); | 4851 Register temp = ToRegister(instr->temp()); |
4852 | 4852 |
4853 if (FLAG_debug_code) { | 4853 if (FLAG_debug_code) { |
4854 ASSERT(ToRegister(instr->context()).is(cp)); | 4854 DCHECK(ToRegister(instr->context()).is(cp)); |
4855 Register index = ToRegister(instr->index()); | 4855 Register index = ToRegister(instr->index()); |
4856 static const uint32_t one_byte_seq_type = kSeqStringTag | kOneByteStringTag; | 4856 static const uint32_t one_byte_seq_type = kSeqStringTag | kOneByteStringTag; |
4857 static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag; | 4857 static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag; |
4858 int encoding_mask = | 4858 int encoding_mask = |
4859 instr->hydrogen()->encoding() == String::ONE_BYTE_ENCODING | 4859 instr->hydrogen()->encoding() == String::ONE_BYTE_ENCODING |
4860 ? one_byte_seq_type : two_byte_seq_type; | 4860 ? one_byte_seq_type : two_byte_seq_type; |
4861 __ EmitSeqStringSetCharCheck(string, index, kIndexIsInteger32, temp, | 4861 __ EmitSeqStringSetCharCheck(string, index, kIndexIsInteger32, temp, |
4862 encoding_mask); | 4862 encoding_mask); |
4863 } | 4863 } |
4864 MemOperand operand = | 4864 MemOperand operand = |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4914 Label right_not_zero; | 4914 Label right_not_zero; |
4915 __ Cbnz(right, &right_not_zero); | 4915 __ Cbnz(right, &right_not_zero); |
4916 DeoptimizeIfNegative(left, instr->environment()); | 4916 DeoptimizeIfNegative(left, instr->environment()); |
4917 __ Bind(&right_not_zero); | 4917 __ Bind(&right_not_zero); |
4918 } | 4918 } |
4919 __ Lsr(result, left, right); | 4919 __ Lsr(result, left, right); |
4920 break; | 4920 break; |
4921 default: UNREACHABLE(); | 4921 default: UNREACHABLE(); |
4922 } | 4922 } |
4923 } else { | 4923 } else { |
4924 ASSERT(right_op->IsConstantOperand()); | 4924 DCHECK(right_op->IsConstantOperand()); |
4925 int shift_count = JSShiftAmountFromLConstant(right_op); | 4925 int shift_count = JSShiftAmountFromLConstant(right_op); |
4926 if (shift_count == 0) { | 4926 if (shift_count == 0) { |
4927 if ((instr->op() == Token::SHR) && instr->can_deopt()) { | 4927 if ((instr->op() == Token::SHR) && instr->can_deopt()) { |
4928 DeoptimizeIfNegative(left, instr->environment()); | 4928 DeoptimizeIfNegative(left, instr->environment()); |
4929 } | 4929 } |
4930 __ Mov(result, left, kDiscardForSameWReg); | 4930 __ Mov(result, left, kDiscardForSameWReg); |
4931 } else { | 4931 } else { |
4932 switch (instr->op()) { | 4932 switch (instr->op()) { |
4933 case Token::ROR: __ Ror(result, left, shift_count); break; | 4933 case Token::ROR: __ Ror(result, left, shift_count); break; |
4934 case Token::SAR: __ Asr(result, left, shift_count); break; | 4934 case Token::SAR: __ Asr(result, left, shift_count); break; |
4935 case Token::SHL: __ Lsl(result, left, shift_count); break; | 4935 case Token::SHL: __ Lsl(result, left, shift_count); break; |
4936 case Token::SHR: __ Lsr(result, left, shift_count); break; | 4936 case Token::SHR: __ Lsr(result, left, shift_count); break; |
4937 default: UNREACHABLE(); | 4937 default: UNREACHABLE(); |
4938 } | 4938 } |
4939 } | 4939 } |
4940 } | 4940 } |
4941 } | 4941 } |
4942 | 4942 |
4943 | 4943 |
4944 void LCodeGen::DoShiftS(LShiftS* instr) { | 4944 void LCodeGen::DoShiftS(LShiftS* instr) { |
4945 LOperand* right_op = instr->right(); | 4945 LOperand* right_op = instr->right(); |
4946 Register left = ToRegister(instr->left()); | 4946 Register left = ToRegister(instr->left()); |
4947 Register result = ToRegister(instr->result()); | 4947 Register result = ToRegister(instr->result()); |
4948 | 4948 |
4949 // Only ROR by register needs a temp. | 4949 // Only ROR by register needs a temp. |
4950 ASSERT(((instr->op() == Token::ROR) && right_op->IsRegister()) || | 4950 DCHECK(((instr->op() == Token::ROR) && right_op->IsRegister()) || |
4951 (instr->temp() == NULL)); | 4951 (instr->temp() == NULL)); |
4952 | 4952 |
4953 if (right_op->IsRegister()) { | 4953 if (right_op->IsRegister()) { |
4954 Register right = ToRegister(instr->right()); | 4954 Register right = ToRegister(instr->right()); |
4955 switch (instr->op()) { | 4955 switch (instr->op()) { |
4956 case Token::ROR: { | 4956 case Token::ROR: { |
4957 Register temp = ToRegister(instr->temp()); | 4957 Register temp = ToRegister(instr->temp()); |
4958 __ Ubfx(temp, right, kSmiShift, 5); | 4958 __ Ubfx(temp, right, kSmiShift, 5); |
4959 __ SmiUntag(result, left); | 4959 __ SmiUntag(result, left); |
4960 __ Ror(result.W(), result.W(), temp.W()); | 4960 __ Ror(result.W(), result.W(), temp.W()); |
(...skipping 16 matching lines...) Expand all Loading... |
4977 DeoptimizeIfNegative(left, instr->environment()); | 4977 DeoptimizeIfNegative(left, instr->environment()); |
4978 __ Bind(&right_not_zero); | 4978 __ Bind(&right_not_zero); |
4979 } | 4979 } |
4980 __ Ubfx(result, right, kSmiShift, 5); | 4980 __ Ubfx(result, right, kSmiShift, 5); |
4981 __ Lsr(result, left, result); | 4981 __ Lsr(result, left, result); |
4982 __ Bic(result, result, kSmiShiftMask); | 4982 __ Bic(result, result, kSmiShiftMask); |
4983 break; | 4983 break; |
4984 default: UNREACHABLE(); | 4984 default: UNREACHABLE(); |
4985 } | 4985 } |
4986 } else { | 4986 } else { |
4987 ASSERT(right_op->IsConstantOperand()); | 4987 DCHECK(right_op->IsConstantOperand()); |
4988 int shift_count = JSShiftAmountFromLConstant(right_op); | 4988 int shift_count = JSShiftAmountFromLConstant(right_op); |
4989 if (shift_count == 0) { | 4989 if (shift_count == 0) { |
4990 if ((instr->op() == Token::SHR) && instr->can_deopt()) { | 4990 if ((instr->op() == Token::SHR) && instr->can_deopt()) { |
4991 DeoptimizeIfNegative(left, instr->environment()); | 4991 DeoptimizeIfNegative(left, instr->environment()); |
4992 } | 4992 } |
4993 __ Mov(result, left); | 4993 __ Mov(result, left); |
4994 } else { | 4994 } else { |
4995 switch (instr->op()) { | 4995 switch (instr->op()) { |
4996 case Token::ROR: | 4996 case Token::ROR: |
4997 __ SmiUntag(result, left); | 4997 __ SmiUntag(result, left); |
(...skipping 17 matching lines...) Expand all Loading... |
5015 } | 5015 } |
5016 } | 5016 } |
5017 | 5017 |
5018 | 5018 |
5019 void LCodeGen::DoDebugBreak(LDebugBreak* instr) { | 5019 void LCodeGen::DoDebugBreak(LDebugBreak* instr) { |
5020 __ Debug("LDebugBreak", 0, BREAK); | 5020 __ Debug("LDebugBreak", 0, BREAK); |
5021 } | 5021 } |
5022 | 5022 |
5023 | 5023 |
5024 void LCodeGen::DoDeclareGlobals(LDeclareGlobals* instr) { | 5024 void LCodeGen::DoDeclareGlobals(LDeclareGlobals* instr) { |
5025 ASSERT(ToRegister(instr->context()).is(cp)); | 5025 DCHECK(ToRegister(instr->context()).is(cp)); |
5026 Register scratch1 = x5; | 5026 Register scratch1 = x5; |
5027 Register scratch2 = x6; | 5027 Register scratch2 = x6; |
5028 ASSERT(instr->IsMarkedAsCall()); | 5028 DCHECK(instr->IsMarkedAsCall()); |
5029 | 5029 |
5030 ASM_UNIMPLEMENTED_BREAK("DoDeclareGlobals"); | 5030 ASM_UNIMPLEMENTED_BREAK("DoDeclareGlobals"); |
5031 // TODO(all): if Mov could handle object in new space then it could be used | 5031 // TODO(all): if Mov could handle object in new space then it could be used |
5032 // here. | 5032 // here. |
5033 __ LoadHeapObject(scratch1, instr->hydrogen()->pairs()); | 5033 __ LoadHeapObject(scratch1, instr->hydrogen()->pairs()); |
5034 __ Mov(scratch2, Smi::FromInt(instr->hydrogen()->flags())); | 5034 __ Mov(scratch2, Smi::FromInt(instr->hydrogen()->flags())); |
5035 __ Push(cp, scratch1, scratch2); // The context is the first argument. | 5035 __ Push(cp, scratch1, scratch2); // The context is the first argument. |
5036 CallRuntime(Runtime::kDeclareGlobals, 3, instr); | 5036 CallRuntime(Runtime::kDeclareGlobals, 3, instr); |
5037 } | 5037 } |
5038 | 5038 |
5039 | 5039 |
5040 void LCodeGen::DoDeferredStackCheck(LStackCheck* instr) { | 5040 void LCodeGen::DoDeferredStackCheck(LStackCheck* instr) { |
5041 PushSafepointRegistersScope scope(this); | 5041 PushSafepointRegistersScope scope(this); |
5042 LoadContextFromDeferred(instr->context()); | 5042 LoadContextFromDeferred(instr->context()); |
5043 __ CallRuntimeSaveDoubles(Runtime::kStackGuard); | 5043 __ CallRuntimeSaveDoubles(Runtime::kStackGuard); |
5044 RecordSafepointWithLazyDeopt( | 5044 RecordSafepointWithLazyDeopt( |
5045 instr, RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS); | 5045 instr, RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS); |
5046 ASSERT(instr->HasEnvironment()); | 5046 DCHECK(instr->HasEnvironment()); |
5047 LEnvironment* env = instr->environment(); | 5047 LEnvironment* env = instr->environment(); |
5048 safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index()); | 5048 safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index()); |
5049 } | 5049 } |
5050 | 5050 |
5051 | 5051 |
5052 void LCodeGen::DoStackCheck(LStackCheck* instr) { | 5052 void LCodeGen::DoStackCheck(LStackCheck* instr) { |
5053 class DeferredStackCheck: public LDeferredCode { | 5053 class DeferredStackCheck: public LDeferredCode { |
5054 public: | 5054 public: |
5055 DeferredStackCheck(LCodeGen* codegen, LStackCheck* instr) | 5055 DeferredStackCheck(LCodeGen* codegen, LStackCheck* instr) |
5056 : LDeferredCode(codegen), instr_(instr) { } | 5056 : LDeferredCode(codegen), instr_(instr) { } |
5057 virtual void Generate() { codegen()->DoDeferredStackCheck(instr_); } | 5057 virtual void Generate() { codegen()->DoDeferredStackCheck(instr_); } |
5058 virtual LInstruction* instr() { return instr_; } | 5058 virtual LInstruction* instr() { return instr_; } |
5059 private: | 5059 private: |
5060 LStackCheck* instr_; | 5060 LStackCheck* instr_; |
5061 }; | 5061 }; |
5062 | 5062 |
5063 ASSERT(instr->HasEnvironment()); | 5063 DCHECK(instr->HasEnvironment()); |
5064 LEnvironment* env = instr->environment(); | 5064 LEnvironment* env = instr->environment(); |
5065 // There is no LLazyBailout instruction for stack-checks. We have to | 5065 // There is no LLazyBailout instruction for stack-checks. We have to |
5066 // prepare for lazy deoptimization explicitly here. | 5066 // prepare for lazy deoptimization explicitly here. |
5067 if (instr->hydrogen()->is_function_entry()) { | 5067 if (instr->hydrogen()->is_function_entry()) { |
5068 // Perform stack overflow check. | 5068 // Perform stack overflow check. |
5069 Label done; | 5069 Label done; |
5070 __ CompareRoot(masm()->StackPointer(), Heap::kStackLimitRootIndex); | 5070 __ CompareRoot(masm()->StackPointer(), Heap::kStackLimitRootIndex); |
5071 __ B(hs, &done); | 5071 __ B(hs, &done); |
5072 | 5072 |
5073 PredictableCodeSizeScope predictable(masm_, | 5073 PredictableCodeSizeScope predictable(masm_, |
5074 Assembler::kCallSizeWithRelocation); | 5074 Assembler::kCallSizeWithRelocation); |
5075 ASSERT(instr->context()->IsRegister()); | 5075 DCHECK(instr->context()->IsRegister()); |
5076 ASSERT(ToRegister(instr->context()).is(cp)); | 5076 DCHECK(ToRegister(instr->context()).is(cp)); |
5077 CallCode(isolate()->builtins()->StackCheck(), | 5077 CallCode(isolate()->builtins()->StackCheck(), |
5078 RelocInfo::CODE_TARGET, | 5078 RelocInfo::CODE_TARGET, |
5079 instr); | 5079 instr); |
5080 __ Bind(&done); | 5080 __ Bind(&done); |
5081 } else { | 5081 } else { |
5082 ASSERT(instr->hydrogen()->is_backwards_branch()); | 5082 DCHECK(instr->hydrogen()->is_backwards_branch()); |
5083 // Perform stack overflow check if this goto needs it before jumping. | 5083 // Perform stack overflow check if this goto needs it before jumping. |
5084 DeferredStackCheck* deferred_stack_check = | 5084 DeferredStackCheck* deferred_stack_check = |
5085 new(zone()) DeferredStackCheck(this, instr); | 5085 new(zone()) DeferredStackCheck(this, instr); |
5086 __ CompareRoot(masm()->StackPointer(), Heap::kStackLimitRootIndex); | 5086 __ CompareRoot(masm()->StackPointer(), Heap::kStackLimitRootIndex); |
5087 __ B(lo, deferred_stack_check->entry()); | 5087 __ B(lo, deferred_stack_check->entry()); |
5088 | 5088 |
5089 EnsureSpaceForLazyDeopt(Deoptimizer::patch_size()); | 5089 EnsureSpaceForLazyDeopt(Deoptimizer::patch_size()); |
5090 __ Bind(instr->done_label()); | 5090 __ Bind(instr->done_label()); |
5091 deferred_stack_check->SetExit(instr->done_label()); | 5091 deferred_stack_check->SetExit(instr->done_label()); |
5092 RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt); | 5092 RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt); |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5169 void LCodeGen::DoStoreKeyedExternal(LStoreKeyedExternal* instr) { | 5169 void LCodeGen::DoStoreKeyedExternal(LStoreKeyedExternal* instr) { |
5170 Register ext_ptr = ToRegister(instr->elements()); | 5170 Register ext_ptr = ToRegister(instr->elements()); |
5171 Register key = no_reg; | 5171 Register key = no_reg; |
5172 Register scratch; | 5172 Register scratch; |
5173 ElementsKind elements_kind = instr->elements_kind(); | 5173 ElementsKind elements_kind = instr->elements_kind(); |
5174 | 5174 |
5175 bool key_is_smi = instr->hydrogen()->key()->representation().IsSmi(); | 5175 bool key_is_smi = instr->hydrogen()->key()->representation().IsSmi(); |
5176 bool key_is_constant = instr->key()->IsConstantOperand(); | 5176 bool key_is_constant = instr->key()->IsConstantOperand(); |
5177 int constant_key = 0; | 5177 int constant_key = 0; |
5178 if (key_is_constant) { | 5178 if (key_is_constant) { |
5179 ASSERT(instr->temp() == NULL); | 5179 DCHECK(instr->temp() == NULL); |
5180 constant_key = ToInteger32(LConstantOperand::cast(instr->key())); | 5180 constant_key = ToInteger32(LConstantOperand::cast(instr->key())); |
5181 if (constant_key & 0xf0000000) { | 5181 if (constant_key & 0xf0000000) { |
5182 Abort(kArrayIndexConstantValueTooBig); | 5182 Abort(kArrayIndexConstantValueTooBig); |
5183 } | 5183 } |
5184 } else { | 5184 } else { |
5185 key = ToRegister(instr->key()); | 5185 key = ToRegister(instr->key()); |
5186 scratch = ToRegister(instr->temp()); | 5186 scratch = ToRegister(instr->temp()); |
5187 } | 5187 } |
5188 | 5188 |
5189 MemOperand dst = | 5189 MemOperand dst = |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5289 scratch = ToRegister(instr->temp()); | 5289 scratch = ToRegister(instr->temp()); |
5290 } | 5290 } |
5291 | 5291 |
5292 Representation representation = instr->hydrogen()->value()->representation(); | 5292 Representation representation = instr->hydrogen()->value()->representation(); |
5293 if (instr->key()->IsConstantOperand()) { | 5293 if (instr->key()->IsConstantOperand()) { |
5294 LConstantOperand* const_operand = LConstantOperand::cast(instr->key()); | 5294 LConstantOperand* const_operand = LConstantOperand::cast(instr->key()); |
5295 int offset = instr->base_offset() + | 5295 int offset = instr->base_offset() + |
5296 ToInteger32(const_operand) * kPointerSize; | 5296 ToInteger32(const_operand) * kPointerSize; |
5297 store_base = elements; | 5297 store_base = elements; |
5298 if (representation.IsInteger32()) { | 5298 if (representation.IsInteger32()) { |
5299 ASSERT(instr->hydrogen()->store_mode() == STORE_TO_INITIALIZED_ENTRY); | 5299 DCHECK(instr->hydrogen()->store_mode() == STORE_TO_INITIALIZED_ENTRY); |
5300 ASSERT(instr->hydrogen()->elements_kind() == FAST_SMI_ELEMENTS); | 5300 DCHECK(instr->hydrogen()->elements_kind() == FAST_SMI_ELEMENTS); |
5301 STATIC_ASSERT(static_cast<unsigned>(kSmiValueSize) == kWRegSizeInBits); | 5301 STATIC_ASSERT(static_cast<unsigned>(kSmiValueSize) == kWRegSizeInBits); |
5302 STATIC_ASSERT(kSmiTag == 0); | 5302 STATIC_ASSERT(kSmiTag == 0); |
5303 mem_op = UntagSmiMemOperand(store_base, offset); | 5303 mem_op = UntagSmiMemOperand(store_base, offset); |
5304 } else { | 5304 } else { |
5305 mem_op = MemOperand(store_base, offset); | 5305 mem_op = MemOperand(store_base, offset); |
5306 } | 5306 } |
5307 } else { | 5307 } else { |
5308 store_base = scratch; | 5308 store_base = scratch; |
5309 key = ToRegister(instr->key()); | 5309 key = ToRegister(instr->key()); |
5310 bool key_is_tagged = instr->hydrogen()->key()->representation().IsSmi(); | 5310 bool key_is_tagged = instr->hydrogen()->key()->representation().IsSmi(); |
5311 | 5311 |
5312 mem_op = PrepareKeyedArrayOperand(store_base, elements, key, key_is_tagged, | 5312 mem_op = PrepareKeyedArrayOperand(store_base, elements, key, key_is_tagged, |
5313 instr->hydrogen()->elements_kind(), | 5313 instr->hydrogen()->elements_kind(), |
5314 representation, instr->base_offset()); | 5314 representation, instr->base_offset()); |
5315 } | 5315 } |
5316 | 5316 |
5317 __ Store(value, mem_op, representation); | 5317 __ Store(value, mem_op, representation); |
5318 | 5318 |
5319 if (instr->hydrogen()->NeedsWriteBarrier()) { | 5319 if (instr->hydrogen()->NeedsWriteBarrier()) { |
5320 ASSERT(representation.IsTagged()); | 5320 DCHECK(representation.IsTagged()); |
5321 // This assignment may cause element_addr to alias store_base. | 5321 // This assignment may cause element_addr to alias store_base. |
5322 Register element_addr = scratch; | 5322 Register element_addr = scratch; |
5323 SmiCheck check_needed = | 5323 SmiCheck check_needed = |
5324 instr->hydrogen()->value()->type().IsHeapObject() | 5324 instr->hydrogen()->value()->type().IsHeapObject() |
5325 ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; | 5325 ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; |
5326 // Compute address of modified element and store it into key register. | 5326 // Compute address of modified element and store it into key register. |
5327 __ Add(element_addr, mem_op.base(), mem_op.OffsetAsOperand()); | 5327 __ Add(element_addr, mem_op.base(), mem_op.OffsetAsOperand()); |
5328 __ RecordWrite(elements, element_addr, value, GetLinkRegisterState(), | 5328 __ RecordWrite(elements, element_addr, value, GetLinkRegisterState(), |
5329 kSaveFPRegs, EMIT_REMEMBERED_SET, check_needed, | 5329 kSaveFPRegs, EMIT_REMEMBERED_SET, check_needed, |
5330 instr->hydrogen()->PointersToHereCheckForValue()); | 5330 instr->hydrogen()->PointersToHereCheckForValue()); |
5331 } | 5331 } |
5332 } | 5332 } |
5333 | 5333 |
5334 | 5334 |
5335 void LCodeGen::DoStoreKeyedGeneric(LStoreKeyedGeneric* instr) { | 5335 void LCodeGen::DoStoreKeyedGeneric(LStoreKeyedGeneric* instr) { |
5336 ASSERT(ToRegister(instr->context()).is(cp)); | 5336 DCHECK(ToRegister(instr->context()).is(cp)); |
5337 ASSERT(ToRegister(instr->object()).is(KeyedStoreIC::ReceiverRegister())); | 5337 DCHECK(ToRegister(instr->object()).is(KeyedStoreIC::ReceiverRegister())); |
5338 ASSERT(ToRegister(instr->key()).is(KeyedStoreIC::NameRegister())); | 5338 DCHECK(ToRegister(instr->key()).is(KeyedStoreIC::NameRegister())); |
5339 ASSERT(ToRegister(instr->value()).is(KeyedStoreIC::ValueRegister())); | 5339 DCHECK(ToRegister(instr->value()).is(KeyedStoreIC::ValueRegister())); |
5340 | 5340 |
5341 Handle<Code> ic = instr->strict_mode() == STRICT | 5341 Handle<Code> ic = instr->strict_mode() == STRICT |
5342 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() | 5342 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() |
5343 : isolate()->builtins()->KeyedStoreIC_Initialize(); | 5343 : isolate()->builtins()->KeyedStoreIC_Initialize(); |
5344 CallCode(ic, RelocInfo::CODE_TARGET, instr); | 5344 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
5345 } | 5345 } |
5346 | 5346 |
5347 | 5347 |
5348 void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) { | 5348 void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) { |
5349 Representation representation = instr->representation(); | 5349 Representation representation = instr->representation(); |
5350 | 5350 |
5351 Register object = ToRegister(instr->object()); | 5351 Register object = ToRegister(instr->object()); |
5352 HObjectAccess access = instr->hydrogen()->access(); | 5352 HObjectAccess access = instr->hydrogen()->access(); |
5353 int offset = access.offset(); | 5353 int offset = access.offset(); |
5354 | 5354 |
5355 if (access.IsExternalMemory()) { | 5355 if (access.IsExternalMemory()) { |
5356 ASSERT(!instr->hydrogen()->has_transition()); | 5356 DCHECK(!instr->hydrogen()->has_transition()); |
5357 ASSERT(!instr->hydrogen()->NeedsWriteBarrier()); | 5357 DCHECK(!instr->hydrogen()->NeedsWriteBarrier()); |
5358 Register value = ToRegister(instr->value()); | 5358 Register value = ToRegister(instr->value()); |
5359 __ Store(value, MemOperand(object, offset), representation); | 5359 __ Store(value, MemOperand(object, offset), representation); |
5360 return; | 5360 return; |
5361 } | 5361 } |
5362 | 5362 |
5363 __ AssertNotSmi(object); | 5363 __ AssertNotSmi(object); |
5364 | 5364 |
5365 if (representation.IsDouble()) { | 5365 if (representation.IsDouble()) { |
5366 ASSERT(access.IsInobject()); | 5366 DCHECK(access.IsInobject()); |
5367 ASSERT(!instr->hydrogen()->has_transition()); | 5367 DCHECK(!instr->hydrogen()->has_transition()); |
5368 ASSERT(!instr->hydrogen()->NeedsWriteBarrier()); | 5368 DCHECK(!instr->hydrogen()->NeedsWriteBarrier()); |
5369 FPRegister value = ToDoubleRegister(instr->value()); | 5369 FPRegister value = ToDoubleRegister(instr->value()); |
5370 __ Str(value, FieldMemOperand(object, offset)); | 5370 __ Str(value, FieldMemOperand(object, offset)); |
5371 return; | 5371 return; |
5372 } | 5372 } |
5373 | 5373 |
5374 Register value = ToRegister(instr->value()); | 5374 Register value = ToRegister(instr->value()); |
5375 | 5375 |
5376 ASSERT(!representation.IsSmi() || | 5376 DCHECK(!representation.IsSmi() || |
5377 !instr->value()->IsConstantOperand() || | 5377 !instr->value()->IsConstantOperand() || |
5378 IsInteger32Constant(LConstantOperand::cast(instr->value()))); | 5378 IsInteger32Constant(LConstantOperand::cast(instr->value()))); |
5379 | 5379 |
5380 if (instr->hydrogen()->has_transition()) { | 5380 if (instr->hydrogen()->has_transition()) { |
5381 Handle<Map> transition = instr->hydrogen()->transition_map(); | 5381 Handle<Map> transition = instr->hydrogen()->transition_map(); |
5382 AddDeprecationDependency(transition); | 5382 AddDeprecationDependency(transition); |
5383 // Store the new map value. | 5383 // Store the new map value. |
5384 Register new_map_value = ToRegister(instr->temp0()); | 5384 Register new_map_value = ToRegister(instr->temp0()); |
5385 __ Mov(new_map_value, Operand(transition)); | 5385 __ Mov(new_map_value, Operand(transition)); |
5386 __ Str(new_map_value, FieldMemOperand(object, HeapObject::kMapOffset)); | 5386 __ Str(new_map_value, FieldMemOperand(object, HeapObject::kMapOffset)); |
(...skipping 12 matching lines...) Expand all Loading... |
5399 if (access.IsInobject()) { | 5399 if (access.IsInobject()) { |
5400 destination = object; | 5400 destination = object; |
5401 } else { | 5401 } else { |
5402 Register temp0 = ToRegister(instr->temp0()); | 5402 Register temp0 = ToRegister(instr->temp0()); |
5403 __ Ldr(temp0, FieldMemOperand(object, JSObject::kPropertiesOffset)); | 5403 __ Ldr(temp0, FieldMemOperand(object, JSObject::kPropertiesOffset)); |
5404 destination = temp0; | 5404 destination = temp0; |
5405 } | 5405 } |
5406 | 5406 |
5407 if (representation.IsSmi() && | 5407 if (representation.IsSmi() && |
5408 instr->hydrogen()->value()->representation().IsInteger32()) { | 5408 instr->hydrogen()->value()->representation().IsInteger32()) { |
5409 ASSERT(instr->hydrogen()->store_mode() == STORE_TO_INITIALIZED_ENTRY); | 5409 DCHECK(instr->hydrogen()->store_mode() == STORE_TO_INITIALIZED_ENTRY); |
5410 #ifdef DEBUG | 5410 #ifdef DEBUG |
5411 Register temp0 = ToRegister(instr->temp0()); | 5411 Register temp0 = ToRegister(instr->temp0()); |
5412 __ Ldr(temp0, FieldMemOperand(destination, offset)); | 5412 __ Ldr(temp0, FieldMemOperand(destination, offset)); |
5413 __ AssertSmi(temp0); | 5413 __ AssertSmi(temp0); |
5414 // If destination aliased temp0, restore it to the address calculated | 5414 // If destination aliased temp0, restore it to the address calculated |
5415 // earlier. | 5415 // earlier. |
5416 if (destination.Is(temp0)) { | 5416 if (destination.Is(temp0)) { |
5417 ASSERT(!access.IsInobject()); | 5417 DCHECK(!access.IsInobject()); |
5418 __ Ldr(destination, FieldMemOperand(object, JSObject::kPropertiesOffset)); | 5418 __ Ldr(destination, FieldMemOperand(object, JSObject::kPropertiesOffset)); |
5419 } | 5419 } |
5420 #endif | 5420 #endif |
5421 STATIC_ASSERT(static_cast<unsigned>(kSmiValueSize) == kWRegSizeInBits); | 5421 STATIC_ASSERT(static_cast<unsigned>(kSmiValueSize) == kWRegSizeInBits); |
5422 STATIC_ASSERT(kSmiTag == 0); | 5422 STATIC_ASSERT(kSmiTag == 0); |
5423 __ Store(value, UntagSmiFieldMemOperand(destination, offset), | 5423 __ Store(value, UntagSmiFieldMemOperand(destination, offset), |
5424 Representation::Integer32()); | 5424 Representation::Integer32()); |
5425 } else { | 5425 } else { |
5426 __ Store(value, FieldMemOperand(destination, offset), representation); | 5426 __ Store(value, FieldMemOperand(destination, offset), representation); |
5427 } | 5427 } |
5428 if (instr->hydrogen()->NeedsWriteBarrier()) { | 5428 if (instr->hydrogen()->NeedsWriteBarrier()) { |
5429 __ RecordWriteField(destination, | 5429 __ RecordWriteField(destination, |
5430 offset, | 5430 offset, |
5431 value, // Clobbered. | 5431 value, // Clobbered. |
5432 ToRegister(instr->temp1()), // Clobbered. | 5432 ToRegister(instr->temp1()), // Clobbered. |
5433 GetLinkRegisterState(), | 5433 GetLinkRegisterState(), |
5434 kSaveFPRegs, | 5434 kSaveFPRegs, |
5435 EMIT_REMEMBERED_SET, | 5435 EMIT_REMEMBERED_SET, |
5436 instr->hydrogen()->SmiCheckForWriteBarrier(), | 5436 instr->hydrogen()->SmiCheckForWriteBarrier(), |
5437 instr->hydrogen()->PointersToHereCheckForValue()); | 5437 instr->hydrogen()->PointersToHereCheckForValue()); |
5438 } | 5438 } |
5439 } | 5439 } |
5440 | 5440 |
5441 | 5441 |
5442 void LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) { | 5442 void LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) { |
5443 ASSERT(ToRegister(instr->context()).is(cp)); | 5443 DCHECK(ToRegister(instr->context()).is(cp)); |
5444 ASSERT(ToRegister(instr->object()).is(StoreIC::ReceiverRegister())); | 5444 DCHECK(ToRegister(instr->object()).is(StoreIC::ReceiverRegister())); |
5445 ASSERT(ToRegister(instr->value()).is(StoreIC::ValueRegister())); | 5445 DCHECK(ToRegister(instr->value()).is(StoreIC::ValueRegister())); |
5446 | 5446 |
5447 __ Mov(StoreIC::NameRegister(), Operand(instr->name())); | 5447 __ Mov(StoreIC::NameRegister(), Operand(instr->name())); |
5448 Handle<Code> ic = StoreIC::initialize_stub(isolate(), instr->strict_mode()); | 5448 Handle<Code> ic = StoreIC::initialize_stub(isolate(), instr->strict_mode()); |
5449 CallCode(ic, RelocInfo::CODE_TARGET, instr); | 5449 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
5450 } | 5450 } |
5451 | 5451 |
5452 | 5452 |
5453 void LCodeGen::DoStringAdd(LStringAdd* instr) { | 5453 void LCodeGen::DoStringAdd(LStringAdd* instr) { |
5454 ASSERT(ToRegister(instr->context()).is(cp)); | 5454 DCHECK(ToRegister(instr->context()).is(cp)); |
5455 ASSERT(ToRegister(instr->left()).Is(x1)); | 5455 DCHECK(ToRegister(instr->left()).Is(x1)); |
5456 ASSERT(ToRegister(instr->right()).Is(x0)); | 5456 DCHECK(ToRegister(instr->right()).Is(x0)); |
5457 StringAddStub stub(isolate(), | 5457 StringAddStub stub(isolate(), |
5458 instr->hydrogen()->flags(), | 5458 instr->hydrogen()->flags(), |
5459 instr->hydrogen()->pretenure_flag()); | 5459 instr->hydrogen()->pretenure_flag()); |
5460 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); | 5460 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
5461 } | 5461 } |
5462 | 5462 |
5463 | 5463 |
5464 void LCodeGen::DoStringCharCodeAt(LStringCharCodeAt* instr) { | 5464 void LCodeGen::DoStringCharCodeAt(LStringCharCodeAt* instr) { |
5465 class DeferredStringCharCodeAt: public LDeferredCode { | 5465 class DeferredStringCharCodeAt: public LDeferredCode { |
5466 public: | 5466 public: |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5515 : LDeferredCode(codegen), instr_(instr) { } | 5515 : LDeferredCode(codegen), instr_(instr) { } |
5516 virtual void Generate() { codegen()->DoDeferredStringCharFromCode(instr_); } | 5516 virtual void Generate() { codegen()->DoDeferredStringCharFromCode(instr_); } |
5517 virtual LInstruction* instr() { return instr_; } | 5517 virtual LInstruction* instr() { return instr_; } |
5518 private: | 5518 private: |
5519 LStringCharFromCode* instr_; | 5519 LStringCharFromCode* instr_; |
5520 }; | 5520 }; |
5521 | 5521 |
5522 DeferredStringCharFromCode* deferred = | 5522 DeferredStringCharFromCode* deferred = |
5523 new(zone()) DeferredStringCharFromCode(this, instr); | 5523 new(zone()) DeferredStringCharFromCode(this, instr); |
5524 | 5524 |
5525 ASSERT(instr->hydrogen()->value()->representation().IsInteger32()); | 5525 DCHECK(instr->hydrogen()->value()->representation().IsInteger32()); |
5526 Register char_code = ToRegister32(instr->char_code()); | 5526 Register char_code = ToRegister32(instr->char_code()); |
5527 Register result = ToRegister(instr->result()); | 5527 Register result = ToRegister(instr->result()); |
5528 | 5528 |
5529 __ Cmp(char_code, String::kMaxOneByteCharCode); | 5529 __ Cmp(char_code, String::kMaxOneByteCharCode); |
5530 __ B(hi, deferred->entry()); | 5530 __ B(hi, deferred->entry()); |
5531 __ LoadRoot(result, Heap::kSingleCharacterStringCacheRootIndex); | 5531 __ LoadRoot(result, Heap::kSingleCharacterStringCacheRootIndex); |
5532 __ Add(result, result, FixedArray::kHeaderSize - kHeapObjectTag); | 5532 __ Add(result, result, FixedArray::kHeaderSize - kHeapObjectTag); |
5533 __ Ldr(result, MemOperand(result, char_code, SXTW, kPointerSizeLog2)); | 5533 __ Ldr(result, MemOperand(result, char_code, SXTW, kPointerSizeLog2)); |
5534 __ CompareRoot(result, Heap::kUndefinedValueRootIndex); | 5534 __ CompareRoot(result, Heap::kUndefinedValueRootIndex); |
5535 __ B(eq, deferred->entry()); | 5535 __ B(eq, deferred->entry()); |
(...skipping 11 matching lines...) Expand all Loading... |
5547 __ Mov(result, 0); | 5547 __ Mov(result, 0); |
5548 | 5548 |
5549 PushSafepointRegistersScope scope(this); | 5549 PushSafepointRegistersScope scope(this); |
5550 __ SmiTagAndPush(char_code); | 5550 __ SmiTagAndPush(char_code); |
5551 CallRuntimeFromDeferred(Runtime::kCharFromCode, 1, instr, instr->context()); | 5551 CallRuntimeFromDeferred(Runtime::kCharFromCode, 1, instr, instr->context()); |
5552 __ StoreToSafepointRegisterSlot(x0, result); | 5552 __ StoreToSafepointRegisterSlot(x0, result); |
5553 } | 5553 } |
5554 | 5554 |
5555 | 5555 |
5556 void LCodeGen::DoStringCompareAndBranch(LStringCompareAndBranch* instr) { | 5556 void LCodeGen::DoStringCompareAndBranch(LStringCompareAndBranch* instr) { |
5557 ASSERT(ToRegister(instr->context()).is(cp)); | 5557 DCHECK(ToRegister(instr->context()).is(cp)); |
5558 Token::Value op = instr->op(); | 5558 Token::Value op = instr->op(); |
5559 | 5559 |
5560 Handle<Code> ic = CompareIC::GetUninitialized(isolate(), op); | 5560 Handle<Code> ic = CompareIC::GetUninitialized(isolate(), op); |
5561 CallCode(ic, RelocInfo::CODE_TARGET, instr); | 5561 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
5562 InlineSmiCheckInfo::EmitNotInlined(masm()); | 5562 InlineSmiCheckInfo::EmitNotInlined(masm()); |
5563 | 5563 |
5564 Condition condition = TokenToCondition(op, false); | 5564 Condition condition = TokenToCondition(op, false); |
5565 | 5565 |
5566 EmitCompareAndBranch(instr, condition, x0, 0); | 5566 EmitCompareAndBranch(instr, condition, x0, 0); |
5567 } | 5567 } |
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5690 } | 5690 } |
5691 | 5691 |
5692 | 5692 |
5693 void LCodeGen::DoThisFunction(LThisFunction* instr) { | 5693 void LCodeGen::DoThisFunction(LThisFunction* instr) { |
5694 Register result = ToRegister(instr->result()); | 5694 Register result = ToRegister(instr->result()); |
5695 __ Ldr(result, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); | 5695 __ Ldr(result, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); |
5696 } | 5696 } |
5697 | 5697 |
5698 | 5698 |
5699 void LCodeGen::DoToFastProperties(LToFastProperties* instr) { | 5699 void LCodeGen::DoToFastProperties(LToFastProperties* instr) { |
5700 ASSERT(ToRegister(instr->value()).Is(x0)); | 5700 DCHECK(ToRegister(instr->value()).Is(x0)); |
5701 ASSERT(ToRegister(instr->result()).Is(x0)); | 5701 DCHECK(ToRegister(instr->result()).Is(x0)); |
5702 __ Push(x0); | 5702 __ Push(x0); |
5703 CallRuntime(Runtime::kToFastProperties, 1, instr); | 5703 CallRuntime(Runtime::kToFastProperties, 1, instr); |
5704 } | 5704 } |
5705 | 5705 |
5706 | 5706 |
5707 void LCodeGen::DoRegExpLiteral(LRegExpLiteral* instr) { | 5707 void LCodeGen::DoRegExpLiteral(LRegExpLiteral* instr) { |
5708 ASSERT(ToRegister(instr->context()).is(cp)); | 5708 DCHECK(ToRegister(instr->context()).is(cp)); |
5709 Label materialized; | 5709 Label materialized; |
5710 // Registers will be used as follows: | 5710 // Registers will be used as follows: |
5711 // x7 = literals array. | 5711 // x7 = literals array. |
5712 // x1 = regexp literal. | 5712 // x1 = regexp literal. |
5713 // x0 = regexp literal clone. | 5713 // x0 = regexp literal clone. |
5714 // x10-x12 are used as temporaries. | 5714 // x10-x12 are used as temporaries. |
5715 int literal_offset = | 5715 int literal_offset = |
5716 FixedArray::OffsetOfElementAt(instr->hydrogen()->literal_index()); | 5716 FixedArray::OffsetOfElementAt(instr->hydrogen()->literal_index()); |
5717 __ LoadObject(x7, instr->hydrogen()->literals()); | 5717 __ LoadObject(x7, instr->hydrogen()->literals()); |
5718 __ Ldr(x1, FieldMemOperand(x7, literal_offset)); | 5718 __ Ldr(x1, FieldMemOperand(x7, literal_offset)); |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5766 __ RecordWriteForMap(object, new_map, temp1, GetLinkRegisterState(), | 5766 __ RecordWriteForMap(object, new_map, temp1, GetLinkRegisterState(), |
5767 kDontSaveFPRegs); | 5767 kDontSaveFPRegs); |
5768 } else { | 5768 } else { |
5769 { | 5769 { |
5770 UseScratchRegisterScope temps(masm()); | 5770 UseScratchRegisterScope temps(masm()); |
5771 // Use the temp register only in a restricted scope - the codegen checks | 5771 // Use the temp register only in a restricted scope - the codegen checks |
5772 // that we do not use any register across a call. | 5772 // that we do not use any register across a call. |
5773 __ CheckMap(object, temps.AcquireX(), from_map, ¬_applicable, | 5773 __ CheckMap(object, temps.AcquireX(), from_map, ¬_applicable, |
5774 DONT_DO_SMI_CHECK); | 5774 DONT_DO_SMI_CHECK); |
5775 } | 5775 } |
5776 ASSERT(object.is(x0)); | 5776 DCHECK(object.is(x0)); |
5777 ASSERT(ToRegister(instr->context()).is(cp)); | 5777 DCHECK(ToRegister(instr->context()).is(cp)); |
5778 PushSafepointRegistersScope scope(this); | 5778 PushSafepointRegistersScope scope(this); |
5779 __ Mov(x1, Operand(to_map)); | 5779 __ Mov(x1, Operand(to_map)); |
5780 bool is_js_array = from_map->instance_type() == JS_ARRAY_TYPE; | 5780 bool is_js_array = from_map->instance_type() == JS_ARRAY_TYPE; |
5781 TransitionElementsKindStub stub(isolate(), from_kind, to_kind, is_js_array); | 5781 TransitionElementsKindStub stub(isolate(), from_kind, to_kind, is_js_array); |
5782 __ CallStub(&stub); | 5782 __ CallStub(&stub); |
5783 RecordSafepointWithRegisters( | 5783 RecordSafepointWithRegisters( |
5784 instr->pointer_map(), 0, Safepoint::kLazyDeopt); | 5784 instr->pointer_map(), 0, Safepoint::kLazyDeopt); |
5785 } | 5785 } |
5786 __ Bind(¬_applicable); | 5786 __ Bind(¬_applicable); |
5787 } | 5787 } |
(...skipping 29 matching lines...) Expand all Loading... |
5817 | 5817 |
5818 | 5818 |
5819 void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) { | 5819 void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) { |
5820 Handle<String> type_name = instr->type_literal(); | 5820 Handle<String> type_name = instr->type_literal(); |
5821 Label* true_label = instr->TrueLabel(chunk_); | 5821 Label* true_label = instr->TrueLabel(chunk_); |
5822 Label* false_label = instr->FalseLabel(chunk_); | 5822 Label* false_label = instr->FalseLabel(chunk_); |
5823 Register value = ToRegister(instr->value()); | 5823 Register value = ToRegister(instr->value()); |
5824 | 5824 |
5825 Factory* factory = isolate()->factory(); | 5825 Factory* factory = isolate()->factory(); |
5826 if (String::Equals(type_name, factory->number_string())) { | 5826 if (String::Equals(type_name, factory->number_string())) { |
5827 ASSERT(instr->temp1() != NULL); | 5827 DCHECK(instr->temp1() != NULL); |
5828 Register map = ToRegister(instr->temp1()); | 5828 Register map = ToRegister(instr->temp1()); |
5829 | 5829 |
5830 __ JumpIfSmi(value, true_label); | 5830 __ JumpIfSmi(value, true_label); |
5831 __ Ldr(map, FieldMemOperand(value, HeapObject::kMapOffset)); | 5831 __ Ldr(map, FieldMemOperand(value, HeapObject::kMapOffset)); |
5832 __ CompareRoot(map, Heap::kHeapNumberMapRootIndex); | 5832 __ CompareRoot(map, Heap::kHeapNumberMapRootIndex); |
5833 EmitBranch(instr, eq); | 5833 EmitBranch(instr, eq); |
5834 | 5834 |
5835 } else if (String::Equals(type_name, factory->string_string())) { | 5835 } else if (String::Equals(type_name, factory->string_string())) { |
5836 ASSERT((instr->temp1() != NULL) && (instr->temp2() != NULL)); | 5836 DCHECK((instr->temp1() != NULL) && (instr->temp2() != NULL)); |
5837 Register map = ToRegister(instr->temp1()); | 5837 Register map = ToRegister(instr->temp1()); |
5838 Register scratch = ToRegister(instr->temp2()); | 5838 Register scratch = ToRegister(instr->temp2()); |
5839 | 5839 |
5840 __ JumpIfSmi(value, false_label); | 5840 __ JumpIfSmi(value, false_label); |
5841 __ JumpIfObjectType( | 5841 __ JumpIfObjectType( |
5842 value, map, scratch, FIRST_NONSTRING_TYPE, false_label, ge); | 5842 value, map, scratch, FIRST_NONSTRING_TYPE, false_label, ge); |
5843 __ Ldrb(scratch, FieldMemOperand(map, Map::kBitFieldOffset)); | 5843 __ Ldrb(scratch, FieldMemOperand(map, Map::kBitFieldOffset)); |
5844 EmitTestAndBranch(instr, eq, scratch, 1 << Map::kIsUndetectable); | 5844 EmitTestAndBranch(instr, eq, scratch, 1 << Map::kIsUndetectable); |
5845 | 5845 |
5846 } else if (String::Equals(type_name, factory->symbol_string())) { | 5846 } else if (String::Equals(type_name, factory->symbol_string())) { |
5847 ASSERT((instr->temp1() != NULL) && (instr->temp2() != NULL)); | 5847 DCHECK((instr->temp1() != NULL) && (instr->temp2() != NULL)); |
5848 Register map = ToRegister(instr->temp1()); | 5848 Register map = ToRegister(instr->temp1()); |
5849 Register scratch = ToRegister(instr->temp2()); | 5849 Register scratch = ToRegister(instr->temp2()); |
5850 | 5850 |
5851 __ JumpIfSmi(value, false_label); | 5851 __ JumpIfSmi(value, false_label); |
5852 __ CompareObjectType(value, map, scratch, SYMBOL_TYPE); | 5852 __ CompareObjectType(value, map, scratch, SYMBOL_TYPE); |
5853 EmitBranch(instr, eq); | 5853 EmitBranch(instr, eq); |
5854 | 5854 |
5855 } else if (String::Equals(type_name, factory->boolean_string())) { | 5855 } else if (String::Equals(type_name, factory->boolean_string())) { |
5856 __ JumpIfRoot(value, Heap::kTrueValueRootIndex, true_label); | 5856 __ JumpIfRoot(value, Heap::kTrueValueRootIndex, true_label); |
5857 __ CompareRoot(value, Heap::kFalseValueRootIndex); | 5857 __ CompareRoot(value, Heap::kFalseValueRootIndex); |
5858 EmitBranch(instr, eq); | 5858 EmitBranch(instr, eq); |
5859 | 5859 |
5860 } else if (String::Equals(type_name, factory->undefined_string())) { | 5860 } else if (String::Equals(type_name, factory->undefined_string())) { |
5861 ASSERT(instr->temp1() != NULL); | 5861 DCHECK(instr->temp1() != NULL); |
5862 Register scratch = ToRegister(instr->temp1()); | 5862 Register scratch = ToRegister(instr->temp1()); |
5863 | 5863 |
5864 __ JumpIfRoot(value, Heap::kUndefinedValueRootIndex, true_label); | 5864 __ JumpIfRoot(value, Heap::kUndefinedValueRootIndex, true_label); |
5865 __ JumpIfSmi(value, false_label); | 5865 __ JumpIfSmi(value, false_label); |
5866 // Check for undetectable objects and jump to the true branch in this case. | 5866 // Check for undetectable objects and jump to the true branch in this case. |
5867 __ Ldr(scratch, FieldMemOperand(value, HeapObject::kMapOffset)); | 5867 __ Ldr(scratch, FieldMemOperand(value, HeapObject::kMapOffset)); |
5868 __ Ldrb(scratch, FieldMemOperand(scratch, Map::kBitFieldOffset)); | 5868 __ Ldrb(scratch, FieldMemOperand(scratch, Map::kBitFieldOffset)); |
5869 EmitTestAndBranch(instr, ne, scratch, 1 << Map::kIsUndetectable); | 5869 EmitTestAndBranch(instr, ne, scratch, 1 << Map::kIsUndetectable); |
5870 | 5870 |
5871 } else if (String::Equals(type_name, factory->function_string())) { | 5871 } else if (String::Equals(type_name, factory->function_string())) { |
5872 STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2); | 5872 STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2); |
5873 ASSERT(instr->temp1() != NULL); | 5873 DCHECK(instr->temp1() != NULL); |
5874 Register type = ToRegister(instr->temp1()); | 5874 Register type = ToRegister(instr->temp1()); |
5875 | 5875 |
5876 __ JumpIfSmi(value, false_label); | 5876 __ JumpIfSmi(value, false_label); |
5877 __ JumpIfObjectType(value, type, type, JS_FUNCTION_TYPE, true_label); | 5877 __ JumpIfObjectType(value, type, type, JS_FUNCTION_TYPE, true_label); |
5878 // HeapObject's type has been loaded into type register by JumpIfObjectType. | 5878 // HeapObject's type has been loaded into type register by JumpIfObjectType. |
5879 EmitCompareAndBranch(instr, eq, type, JS_FUNCTION_PROXY_TYPE); | 5879 EmitCompareAndBranch(instr, eq, type, JS_FUNCTION_PROXY_TYPE); |
5880 | 5880 |
5881 } else if (String::Equals(type_name, factory->object_string())) { | 5881 } else if (String::Equals(type_name, factory->object_string())) { |
5882 ASSERT((instr->temp1() != NULL) && (instr->temp2() != NULL)); | 5882 DCHECK((instr->temp1() != NULL) && (instr->temp2() != NULL)); |
5883 Register map = ToRegister(instr->temp1()); | 5883 Register map = ToRegister(instr->temp1()); |
5884 Register scratch = ToRegister(instr->temp2()); | 5884 Register scratch = ToRegister(instr->temp2()); |
5885 | 5885 |
5886 __ JumpIfSmi(value, false_label); | 5886 __ JumpIfSmi(value, false_label); |
5887 __ JumpIfRoot(value, Heap::kNullValueRootIndex, true_label); | 5887 __ JumpIfRoot(value, Heap::kNullValueRootIndex, true_label); |
5888 __ JumpIfObjectType(value, map, scratch, | 5888 __ JumpIfObjectType(value, map, scratch, |
5889 FIRST_NONCALLABLE_SPEC_OBJECT_TYPE, false_label, lt); | 5889 FIRST_NONCALLABLE_SPEC_OBJECT_TYPE, false_label, lt); |
5890 __ CompareInstanceType(map, scratch, LAST_NONCALLABLE_SPEC_OBJECT_TYPE); | 5890 __ CompareInstanceType(map, scratch, LAST_NONCALLABLE_SPEC_OBJECT_TYPE); |
5891 __ B(gt, false_label); | 5891 __ B(gt, false_label); |
5892 // Check for undetectable objects => false. | 5892 // Check for undetectable objects => false. |
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6046 Handle<ScopeInfo> scope_info = instr->scope_info(); | 6046 Handle<ScopeInfo> scope_info = instr->scope_info(); |
6047 __ Push(scope_info); | 6047 __ Push(scope_info); |
6048 __ Push(ToRegister(instr->function())); | 6048 __ Push(ToRegister(instr->function())); |
6049 CallRuntime(Runtime::kPushBlockContext, 2, instr); | 6049 CallRuntime(Runtime::kPushBlockContext, 2, instr); |
6050 RecordSafepoint(Safepoint::kNoLazyDeopt); | 6050 RecordSafepoint(Safepoint::kNoLazyDeopt); |
6051 } | 6051 } |
6052 | 6052 |
6053 | 6053 |
6054 | 6054 |
6055 } } // namespace v8::internal | 6055 } } // namespace v8::internal |
OLD | NEW |