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

Side by Side Diff: src/x64/lithium-codegen-x64.cc

Issue 6697023: Merge 6800:7180 from the bleeding edge branch to the experimental/gc branch. (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/gc/
Patch Set: Created 9 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/x64/lithium-codegen-x64.h ('k') | src/x64/lithium-x64.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2011 the V8 project authors. All rights reserved. 1 // Copyright 2011 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 19 matching lines...) Expand all
30 #if defined(V8_TARGET_ARCH_X64) 30 #if defined(V8_TARGET_ARCH_X64)
31 31
32 #include "x64/lithium-codegen-x64.h" 32 #include "x64/lithium-codegen-x64.h"
33 #include "code-stubs.h" 33 #include "code-stubs.h"
34 #include "stub-cache.h" 34 #include "stub-cache.h"
35 35
36 namespace v8 { 36 namespace v8 {
37 namespace internal { 37 namespace internal {
38 38
39 39
40 // When invoking builtins, we need to record the safepoint in the middle of
41 // the invoke instruction sequence generated by the macro assembler.
42 class SafepointGenerator : public CallWrapper {
43 public:
44 SafepointGenerator(LCodeGen* codegen,
45 LPointerMap* pointers,
46 int deoptimization_index,
47 bool ensure_reloc_space = false)
48 : codegen_(codegen),
49 pointers_(pointers),
50 deoptimization_index_(deoptimization_index),
51 ensure_reloc_space_(ensure_reloc_space) { }
52 virtual ~SafepointGenerator() { }
53
54 virtual void BeforeCall(int call_size) {
55 ASSERT(call_size >= 0);
56 // Ensure that we have enough space after the previous safepoint position
57 // for the jump generated there.
58 int call_end = codegen_->masm()->pc_offset() + call_size;
59 int prev_jump_end = codegen_->LastSafepointEnd() + kMinSafepointSize;
60 if (call_end < prev_jump_end) {
61 int padding_size = prev_jump_end - call_end;
62 STATIC_ASSERT(kMinSafepointSize <= 9); // One multibyte nop is enough.
63 codegen_->masm()->nop(padding_size);
64 }
65 }
66
67 virtual void AfterCall() {
68 // Ensure that we have enough space in the reloc info to patch
69 // this with calls when doing deoptimization.
70 if (ensure_reloc_space_) {
71 codegen_->masm()->RecordComment(RelocInfo::kFillerCommentString, true);
72 }
73 codegen_->RecordSafepoint(pointers_, deoptimization_index_);
74 }
75
76 private:
77 static const int kMinSafepointSize =
78 MacroAssembler::kShortCallInstructionLength;
79 LCodeGen* codegen_;
80 LPointerMap* pointers_;
81 int deoptimization_index_;
82 bool ensure_reloc_space_;
83 };
84
85
40 #define __ masm()-> 86 #define __ masm()->
41 87
42 bool LCodeGen::GenerateCode() { 88 bool LCodeGen::GenerateCode() {
43 HPhase phase("Code generation", chunk()); 89 HPhase phase("Code generation", chunk());
44 ASSERT(is_unused()); 90 ASSERT(is_unused());
45 status_ = GENERATING; 91 status_ = GENERATING;
46 return GeneratePrologue() && 92 return GeneratePrologue() &&
47 GenerateBody() && 93 GenerateBody() &&
48 GenerateDeferredCode() && 94 GenerateDeferredCode() &&
95 GenerateJumpTable() &&
49 GenerateSafepointTable(); 96 GenerateSafepointTable();
50 } 97 }
51 98
52 99
53 void LCodeGen::FinishCode(Handle<Code> code) { 100 void LCodeGen::FinishCode(Handle<Code> code) {
54 ASSERT(is_done()); 101 ASSERT(is_done());
55 code->set_stack_slots(StackSlotCount()); 102 code->set_stack_slots(StackSlotCount());
56 code->set_safepoint_table_offset(safepoints_.GetCodeOffset()); 103 code->set_safepoint_table_offset(safepoints_.GetCodeOffset());
57 PopulateDeoptimizationData(code); 104 PopulateDeoptimizationData(code);
58 } 105 }
59 106
60 107
61 void LCodeGen::Abort(const char* format, ...) { 108 void LCodeGen::Abort(const char* format, ...) {
62 if (FLAG_trace_bailout) { 109 if (FLAG_trace_bailout) {
63 SmartPointer<char> debug_name = graph()->debug_name()->ToCString(); 110 SmartPointer<char> name(info()->shared_info()->DebugName()->ToCString());
64 PrintF("Aborting LCodeGen in @\"%s\": ", *debug_name); 111 PrintF("Aborting LCodeGen in @\"%s\": ", *name);
65 va_list arguments; 112 va_list arguments;
66 va_start(arguments, format); 113 va_start(arguments, format);
67 OS::VPrint(format, arguments); 114 OS::VPrint(format, arguments);
68 va_end(arguments); 115 va_end(arguments);
69 PrintF("\n"); 116 PrintF("\n");
70 } 117 }
71 status_ = ABORTED; 118 status_ = ABORTED;
72 } 119 }
73 120
74 121
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
125 const int kPageSize = 4 * KB; 172 const int kPageSize = 4 * KB;
126 for (int offset = slots * kPointerSize - kPageSize; 173 for (int offset = slots * kPointerSize - kPageSize;
127 offset > 0; 174 offset > 0;
128 offset -= kPageSize) { 175 offset -= kPageSize) {
129 __ movq(Operand(rsp, offset), rax); 176 __ movq(Operand(rsp, offset), rax);
130 } 177 }
131 #endif 178 #endif
132 } 179 }
133 } 180 }
134 181
182 // Possibly allocate a local context.
183 int heap_slots = scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
184 if (heap_slots > 0) {
185 Comment(";;; Allocate local context");
186 // Argument to NewContext is the function, which is still in rdi.
187 __ push(rdi);
188 if (heap_slots <= FastNewContextStub::kMaximumSlots) {
189 FastNewContextStub stub(heap_slots);
190 __ CallStub(&stub);
191 } else {
192 __ CallRuntime(Runtime::kNewContext, 1);
193 }
194 RecordSafepoint(Safepoint::kNoDeoptimizationIndex);
195 // Context is returned in both rax and rsi. It replaces the context
196 // passed to us. It's saved in the stack and kept live in rsi.
197 __ movq(Operand(rbp, StandardFrameConstants::kContextOffset), rsi);
198
199 // Copy any necessary parameters into the context.
200 int num_parameters = scope()->num_parameters();
201 for (int i = 0; i < num_parameters; i++) {
202 Slot* slot = scope()->parameter(i)->AsSlot();
203 if (slot != NULL && slot->type() == Slot::CONTEXT) {
204 int parameter_offset = StandardFrameConstants::kCallerSPOffset +
205 (num_parameters - 1 - i) * kPointerSize;
206 // Load parameter from stack.
207 __ movq(rax, Operand(rbp, parameter_offset));
208 // Store it in the context.
209 int context_offset = Context::SlotOffset(slot->index());
210 __ movq(Operand(rsi, context_offset), rax);
211 // Update the write barrier. This clobbers all involved
212 // registers, so we have use a third register to avoid
213 // clobbering rsi.
214 __ movq(rcx, rsi);
215 __ RecordWrite(rcx, context_offset, rax, rbx);
216 }
217 }
218 Comment(";;; End allocate local context");
219 }
220
135 // Trace the call. 221 // Trace the call.
136 if (FLAG_trace) { 222 if (FLAG_trace) {
137 __ CallRuntime(Runtime::kTraceEnter, 0); 223 __ CallRuntime(Runtime::kTraceEnter, 0);
138 } 224 }
139 return !is_aborted(); 225 return !is_aborted();
140 } 226 }
141 227
142 228
143 bool LCodeGen::GenerateBody() { 229 bool LCodeGen::GenerateBody() {
144 ASSERT(is_generating()); 230 ASSERT(is_generating());
(...skipping 18 matching lines...) Expand all
163 249
164 LInstruction* LCodeGen::GetNextInstruction() { 250 LInstruction* LCodeGen::GetNextInstruction() {
165 if (current_instruction_ < instructions_->length() - 1) { 251 if (current_instruction_ < instructions_->length() - 1) {
166 return instructions_->at(current_instruction_ + 1); 252 return instructions_->at(current_instruction_ + 1);
167 } else { 253 } else {
168 return NULL; 254 return NULL;
169 } 255 }
170 } 256 }
171 257
172 258
259 bool LCodeGen::GenerateJumpTable() {
260 for (int i = 0; i < jump_table_.length(); i++) {
261 __ bind(&jump_table_[i].label);
262 __ Jump(jump_table_[i].address, RelocInfo::RUNTIME_ENTRY);
263 }
264 return !is_aborted();
265 }
266
267
173 bool LCodeGen::GenerateDeferredCode() { 268 bool LCodeGen::GenerateDeferredCode() {
174 ASSERT(is_generating()); 269 ASSERT(is_generating());
175 for (int i = 0; !is_aborted() && i < deferred_.length(); i++) { 270 for (int i = 0; !is_aborted() && i < deferred_.length(); i++) {
176 LDeferredCode* code = deferred_[i]; 271 LDeferredCode* code = deferred_[i];
177 __ bind(code->entry()); 272 __ bind(code->entry());
178 code->Generate(); 273 code->Generate();
179 __ jmp(code->exit()); 274 __ jmp(code->exit());
180 } 275 }
181 276
182 // Deferred code is the last part of the instruction sequence. Mark 277 // Deferred code is the last part of the instruction sequence. Mark
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
245 Handle<Object> value = chunk_->LookupLiteral(op); 340 Handle<Object> value = chunk_->LookupLiteral(op);
246 ASSERT(chunk_->LookupLiteralRepresentation(op).IsInteger32()); 341 ASSERT(chunk_->LookupLiteralRepresentation(op).IsInteger32());
247 ASSERT(static_cast<double>(static_cast<int32_t>(value->Number())) == 342 ASSERT(static_cast<double>(static_cast<int32_t>(value->Number())) ==
248 value->Number()); 343 value->Number());
249 return static_cast<int32_t>(value->Number()); 344 return static_cast<int32_t>(value->Number());
250 } 345 }
251 346
252 347
253 Handle<Object> LCodeGen::ToHandle(LConstantOperand* op) const { 348 Handle<Object> LCodeGen::ToHandle(LConstantOperand* op) const {
254 Handle<Object> literal = chunk_->LookupLiteral(op); 349 Handle<Object> literal = chunk_->LookupLiteral(op);
255 Representation r = chunk_->LookupLiteralRepresentation(op); 350 ASSERT(chunk_->LookupLiteralRepresentation(op).IsTagged());
256 ASSERT(r.IsTagged());
257 return literal; 351 return literal;
258 } 352 }
259 353
260 354
261 Operand LCodeGen::ToOperand(LOperand* op) const { 355 Operand LCodeGen::ToOperand(LOperand* op) const {
262 // Does not handle registers. In X64 assembler, plain registers are not 356 // Does not handle registers. In X64 assembler, plain registers are not
263 // representable as an Operand. 357 // representable as an Operand.
264 ASSERT(op->IsStackSlot() || op->IsDoubleStackSlot()); 358 ASSERT(op->IsStackSlot() || op->IsDoubleStackSlot());
265 int index = op->index(); 359 int index = op->index();
266 if (index >= 0) { 360 if (index >= 0) {
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after
436 Address entry = Deoptimizer::GetDeoptimizationEntry(id, Deoptimizer::EAGER); 530 Address entry = Deoptimizer::GetDeoptimizationEntry(id, Deoptimizer::EAGER);
437 ASSERT(entry != NULL); 531 ASSERT(entry != NULL);
438 if (entry == NULL) { 532 if (entry == NULL) {
439 Abort("bailout was not prepared"); 533 Abort("bailout was not prepared");
440 return; 534 return;
441 } 535 }
442 536
443 if (cc == no_condition) { 537 if (cc == no_condition) {
444 __ Jump(entry, RelocInfo::RUNTIME_ENTRY); 538 __ Jump(entry, RelocInfo::RUNTIME_ENTRY);
445 } else { 539 } else {
446 NearLabel done; 540 // We often have several deopts to the same entry, reuse the last
447 __ j(NegateCondition(cc), &done); 541 // jump entry if this is the case.
448 __ Jump(entry, RelocInfo::RUNTIME_ENTRY); 542 if (jump_table_.is_empty() ||
449 __ bind(&done); 543 jump_table_.last().address != entry) {
544 jump_table_.Add(entry);
545 }
546 __ j(cc, &jump_table_.last().label);
450 } 547 }
451 } 548 }
452 549
453 550
454 void LCodeGen::PopulateDeoptimizationData(Handle<Code> code) { 551 void LCodeGen::PopulateDeoptimizationData(Handle<Code> code) {
455 int length = deoptimizations_.length(); 552 int length = deoptimizations_.length();
456 if (length == 0) return; 553 if (length == 0) return;
457 ASSERT(FLAG_deopt); 554 ASSERT(FLAG_deopt);
458 Handle<DeoptimizationInputData> data = 555 Handle<DeoptimizationInputData> data =
459 Factory::NewDeoptimizationInputData(length, TENURED); 556 Factory::NewDeoptimizationInputData(length, TENURED);
460 557
461 data->SetTranslationByteArray(*translations_.CreateByteArray()); 558 Handle<ByteArray> translations = translations_.CreateByteArray();
559 data->SetTranslationByteArray(*translations);
462 data->SetInlinedFunctionCount(Smi::FromInt(inlined_function_count_)); 560 data->SetInlinedFunctionCount(Smi::FromInt(inlined_function_count_));
463 561
464 Handle<FixedArray> literals = 562 Handle<FixedArray> literals =
465 Factory::NewFixedArray(deoptimization_literals_.length(), TENURED); 563 Factory::NewFixedArray(deoptimization_literals_.length(), TENURED);
466 for (int i = 0; i < deoptimization_literals_.length(); i++) { 564 for (int i = 0; i < deoptimization_literals_.length(); i++) {
467 literals->set(i, *deoptimization_literals_[i]); 565 literals->set(i, *deoptimization_literals_[i]);
468 } 566 }
469 data->SetLiteralArray(*literals); 567 data->SetLiteralArray(*literals);
470 568
471 data->SetOsrAstId(Smi::FromInt(info_->osr_ast_id())); 569 data->SetOsrAstId(Smi::FromInt(info_->osr_ast_id()));
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
532 } 630 }
533 } 631 }
534 632
535 633
536 void LCodeGen::RecordSafepoint(LPointerMap* pointers, 634 void LCodeGen::RecordSafepoint(LPointerMap* pointers,
537 int deoptimization_index) { 635 int deoptimization_index) {
538 RecordSafepoint(pointers, Safepoint::kSimple, 0, deoptimization_index); 636 RecordSafepoint(pointers, Safepoint::kSimple, 0, deoptimization_index);
539 } 637 }
540 638
541 639
640 void LCodeGen::RecordSafepoint(int deoptimization_index) {
641 LPointerMap empty_pointers(RelocInfo::kNoPosition);
642 RecordSafepoint(&empty_pointers, deoptimization_index);
643 }
644
645
542 void LCodeGen::RecordSafepointWithRegisters(LPointerMap* pointers, 646 void LCodeGen::RecordSafepointWithRegisters(LPointerMap* pointers,
543 int arguments, 647 int arguments,
544 int deoptimization_index) { 648 int deoptimization_index) {
545 RecordSafepoint(pointers, Safepoint::kWithRegisters, arguments, 649 RecordSafepoint(pointers, Safepoint::kWithRegisters, arguments,
546 deoptimization_index); 650 deoptimization_index);
547 } 651 }
548 652
549 653
550 void LCodeGen::RecordPosition(int position) { 654 void LCodeGen::RecordPosition(int position) {
551 if (!FLAG_debug_info || position == RelocInfo::kNoPosition) return; 655 if (!FLAG_debug_info || position == RelocInfo::kNoPosition) return;
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
603 case CodeStub::RegExpExec: { 707 case CodeStub::RegExpExec: {
604 RegExpExecStub stub; 708 RegExpExecStub stub;
605 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); 709 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
606 break; 710 break;
607 } 711 }
608 case CodeStub::SubString: { 712 case CodeStub::SubString: {
609 SubStringStub stub; 713 SubStringStub stub;
610 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); 714 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
611 break; 715 break;
612 } 716 }
613 case CodeStub::StringCharAt: {
614 // TODO(1116): Add StringCharAt stub to x64.
615 Abort("Unimplemented: %s", "StringCharAt Stub");
616 break;
617 }
618 case CodeStub::MathPow: {
619 // TODO(1115): Add MathPow stub to x64.
620 Abort("Unimplemented: %s", "MathPow Stub");
621 break;
622 }
623 case CodeStub::NumberToString: { 717 case CodeStub::NumberToString: {
624 NumberToStringStub stub; 718 NumberToStringStub stub;
625 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); 719 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
626 break; 720 break;
627 } 721 }
628 case CodeStub::StringAdd: { 722 case CodeStub::StringAdd: {
629 StringAddStub stub(NO_STRING_ADD_FLAGS); 723 StringAddStub stub(NO_STRING_ADD_FLAGS);
630 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); 724 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
631 break; 725 break;
632 } 726 }
633 case CodeStub::StringCompare: { 727 case CodeStub::StringCompare: {
634 StringCompareStub stub; 728 StringCompareStub stub;
635 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); 729 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
636 break; 730 break;
637 } 731 }
638 case CodeStub::TranscendentalCache: { 732 case CodeStub::TranscendentalCache: {
639 TranscendentalCacheStub stub(instr->transcendental_type()); 733 TranscendentalCacheStub stub(instr->transcendental_type(),
734 TranscendentalCacheStub::TAGGED);
640 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); 735 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
641 break; 736 break;
642 } 737 }
643 default: 738 default:
644 UNREACHABLE(); 739 UNREACHABLE();
645 } 740 }
646 } 741 }
647 742
648 743
649 void LCodeGen::DoUnknownOSRValue(LUnknownOSRValue* instr) { 744 void LCodeGen::DoUnknownOSRValue(LUnknownOSRValue* instr) {
650 // Nothing to do. 745 // Nothing to do.
651 } 746 }
652 747
653 748
654 void LCodeGen::DoModI(LModI* instr) { 749 void LCodeGen::DoModI(LModI* instr) {
655 Abort("Unimplemented: %s", "DoModI"); 750 if (instr->hydrogen()->HasPowerOf2Divisor()) {
751 Register dividend = ToRegister(instr->InputAt(0));
752
753 int32_t divisor =
754 HConstant::cast(instr->hydrogen()->right())->Integer32Value();
755
756 if (divisor < 0) divisor = -divisor;
757
758 NearLabel positive_dividend, done;
759 __ testl(dividend, dividend);
760 __ j(not_sign, &positive_dividend);
761 __ negl(dividend);
762 __ andl(dividend, Immediate(divisor - 1));
763 __ negl(dividend);
764 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
765 __ j(not_zero, &done);
766 DeoptimizeIf(no_condition, instr->environment());
767 }
768 __ bind(&positive_dividend);
769 __ andl(dividend, Immediate(divisor - 1));
770 __ bind(&done);
771 } else {
772 LOperand* right = instr->InputAt(1);
773 Register right_reg = ToRegister(right);
774
775 ASSERT(ToRegister(instr->result()).is(rdx));
776 ASSERT(ToRegister(instr->InputAt(0)).is(rax));
777 ASSERT(!right_reg.is(rax));
778 ASSERT(!right_reg.is(rdx));
779
780 // Check for x % 0.
781 if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) {
782 __ testl(right_reg, right_reg);
783 DeoptimizeIf(zero, instr->environment());
784 }
785
786 // Sign extend eax to edx.
787 // (We are using only the low 32 bits of the values.)
788 __ cdq();
789
790 // Check for (0 % -x) that will produce negative zero.
791 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
792 NearLabel positive_left;
793 NearLabel done;
794 __ testl(rax, rax);
795 __ j(not_sign, &positive_left);
796 __ idivl(right_reg);
797
798 // Test the remainder for 0, because then the result would be -0.
799 __ testl(rdx, rdx);
800 __ j(not_zero, &done);
801
802 DeoptimizeIf(no_condition, instr->environment());
803 __ bind(&positive_left);
804 __ idivl(right_reg);
805 __ bind(&done);
806 } else {
807 __ idivl(right_reg);
808 }
809 }
656 } 810 }
657 811
658 812
659 void LCodeGen::DoDivI(LDivI* instr) { 813 void LCodeGen::DoDivI(LDivI* instr) {
660 LOperand* right = instr->InputAt(1); 814 LOperand* right = instr->InputAt(1);
661 ASSERT(ToRegister(instr->result()).is(rax)); 815 ASSERT(ToRegister(instr->result()).is(rax));
662 ASSERT(ToRegister(instr->InputAt(0)).is(rax)); 816 ASSERT(ToRegister(instr->InputAt(0)).is(rax));
663 ASSERT(!ToRegister(instr->InputAt(1)).is(rax)); 817 ASSERT(!ToRegister(instr->InputAt(1)).is(rax));
664 ASSERT(!ToRegister(instr->InputAt(1)).is(rdx)); 818 ASSERT(!ToRegister(instr->InputAt(1)).is(rdx));
665 819
(...skipping 248 matching lines...) Expand 10 before | Expand all | Expand 10 after
914 } 1068 }
915 1069
916 1070
917 void LCodeGen::DoFixedArrayLength(LFixedArrayLength* instr) { 1071 void LCodeGen::DoFixedArrayLength(LFixedArrayLength* instr) {
918 Register result = ToRegister(instr->result()); 1072 Register result = ToRegister(instr->result());
919 Register array = ToRegister(instr->InputAt(0)); 1073 Register array = ToRegister(instr->InputAt(0));
920 __ movq(result, FieldOperand(array, FixedArray::kLengthOffset)); 1074 __ movq(result, FieldOperand(array, FixedArray::kLengthOffset));
921 } 1075 }
922 1076
923 1077
924 void LCodeGen::DoPixelArrayLength(LPixelArrayLength* instr) { 1078 void LCodeGen::DoExternalArrayLength(LExternalArrayLength* instr) {
925 Register result = ToRegister(instr->result()); 1079 Register result = ToRegister(instr->result());
926 Register array = ToRegister(instr->InputAt(0)); 1080 Register array = ToRegister(instr->InputAt(0));
927 __ movq(result, FieldOperand(array, PixelArray::kLengthOffset)); 1081 __ movl(result, FieldOperand(array, ExternalPixelArray::kLengthOffset));
928 } 1082 }
929 1083
930 1084
931 void LCodeGen::DoValueOf(LValueOf* instr) { 1085 void LCodeGen::DoValueOf(LValueOf* instr) {
932 Abort("Unimplemented: %s", "DoValueOf"); 1086 Register input = ToRegister(instr->InputAt(0));
1087 Register result = ToRegister(instr->result());
1088 ASSERT(input.is(result));
1089 NearLabel done;
1090 // If the object is a smi return the object.
1091 __ JumpIfSmi(input, &done);
1092
1093 // If the object is not a value type, return the object.
1094 __ CmpObjectType(input, JS_VALUE_TYPE, kScratchRegister);
1095 __ j(not_equal, &done);
1096 __ movq(result, FieldOperand(input, JSValue::kValueOffset));
1097
1098 __ bind(&done);
933 } 1099 }
934 1100
935 1101
936 void LCodeGen::DoBitNotI(LBitNotI* instr) { 1102 void LCodeGen::DoBitNotI(LBitNotI* instr) {
937 LOperand* input = instr->InputAt(0); 1103 LOperand* input = instr->InputAt(0);
938 ASSERT(input->Equals(instr->result())); 1104 ASSERT(input->Equals(instr->result()));
939 __ not_(ToRegister(input)); 1105 __ not_(ToRegister(input));
940 } 1106 }
941 1107
942 1108
(...skipping 22 matching lines...) Expand all
965 __ addl(ToRegister(left), ToOperand(right)); 1131 __ addl(ToRegister(left), ToOperand(right));
966 } 1132 }
967 1133
968 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { 1134 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) {
969 DeoptimizeIf(overflow, instr->environment()); 1135 DeoptimizeIf(overflow, instr->environment());
970 } 1136 }
971 } 1137 }
972 1138
973 1139
974 void LCodeGen::DoArithmeticD(LArithmeticD* instr) { 1140 void LCodeGen::DoArithmeticD(LArithmeticD* instr) {
975 LOperand* left = instr->InputAt(0); 1141 XMMRegister left = ToDoubleRegister(instr->InputAt(0));
976 LOperand* right = instr->InputAt(1); 1142 XMMRegister right = ToDoubleRegister(instr->InputAt(1));
1143 XMMRegister result = ToDoubleRegister(instr->result());
977 // All operations except MOD are computed in-place. 1144 // All operations except MOD are computed in-place.
978 ASSERT(instr->op() == Token::MOD || left->Equals(instr->result())); 1145 ASSERT(instr->op() == Token::MOD || left.is(result));
979 switch (instr->op()) { 1146 switch (instr->op()) {
980 case Token::ADD: 1147 case Token::ADD:
981 __ addsd(ToDoubleRegister(left), ToDoubleRegister(right)); 1148 __ addsd(left, right);
982 break; 1149 break;
983 case Token::SUB: 1150 case Token::SUB:
984 __ subsd(ToDoubleRegister(left), ToDoubleRegister(right)); 1151 __ subsd(left, right);
985 break; 1152 break;
986 case Token::MUL: 1153 case Token::MUL:
987 __ mulsd(ToDoubleRegister(left), ToDoubleRegister(right)); 1154 __ mulsd(left, right);
988 break; 1155 break;
989 case Token::DIV: 1156 case Token::DIV:
990 __ divsd(ToDoubleRegister(left), ToDoubleRegister(right)); 1157 __ divsd(left, right);
991 break; 1158 break;
992 case Token::MOD: 1159 case Token::MOD:
993 Abort("Unimplemented: %s", "DoArithmeticD MOD"); 1160 __ PrepareCallCFunction(2);
1161 __ movsd(xmm0, left);
1162 ASSERT(right.is(xmm1));
1163 __ CallCFunction(ExternalReference::double_fp_operation(Token::MOD), 2);
1164 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
1165 __ movsd(result, xmm0);
994 break; 1166 break;
995 default: 1167 default:
996 UNREACHABLE(); 1168 UNREACHABLE();
997 break; 1169 break;
998 } 1170 }
999 } 1171 }
1000 1172
1001 1173
1002 void LCodeGen::DoArithmeticT(LArithmeticT* instr) { 1174 void LCodeGen::DoArithmeticT(LArithmeticT* instr) {
1003 ASSERT(ToRegister(instr->InputAt(0)).is(rdx)); 1175 ASSERT(ToRegister(instr->InputAt(0)).is(rdx));
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
1050 } else if (r.IsDouble()) { 1222 } else if (r.IsDouble()) {
1051 XMMRegister reg = ToDoubleRegister(instr->InputAt(0)); 1223 XMMRegister reg = ToDoubleRegister(instr->InputAt(0));
1052 __ xorpd(xmm0, xmm0); 1224 __ xorpd(xmm0, xmm0);
1053 __ ucomisd(reg, xmm0); 1225 __ ucomisd(reg, xmm0);
1054 EmitBranch(true_block, false_block, not_equal); 1226 EmitBranch(true_block, false_block, not_equal);
1055 } else { 1227 } else {
1056 ASSERT(r.IsTagged()); 1228 ASSERT(r.IsTagged());
1057 Register reg = ToRegister(instr->InputAt(0)); 1229 Register reg = ToRegister(instr->InputAt(0));
1058 HType type = instr->hydrogen()->type(); 1230 HType type = instr->hydrogen()->type();
1059 if (type.IsBoolean()) { 1231 if (type.IsBoolean()) {
1060 __ Cmp(reg, Factory::true_value()); 1232 __ CompareRoot(reg, Heap::kTrueValueRootIndex);
1061 EmitBranch(true_block, false_block, equal); 1233 EmitBranch(true_block, false_block, equal);
1062 } else if (type.IsSmi()) { 1234 } else if (type.IsSmi()) {
1063 __ SmiCompare(reg, Smi::FromInt(0)); 1235 __ SmiCompare(reg, Smi::FromInt(0));
1064 EmitBranch(true_block, false_block, not_equal); 1236 EmitBranch(true_block, false_block, not_equal);
1065 } else { 1237 } else {
1066 Label* true_label = chunk_->GetAssemblyLabel(true_block); 1238 Label* true_label = chunk_->GetAssemblyLabel(true_block);
1067 Label* false_label = chunk_->GetAssemblyLabel(false_block); 1239 Label* false_label = chunk_->GetAssemblyLabel(false_block);
1068 1240
1069 __ CompareRoot(reg, Heap::kUndefinedValueRootIndex); 1241 __ CompareRoot(reg, Heap::kUndefinedValueRootIndex);
1070 __ j(equal, false_label); 1242 __ j(equal, false_label);
1071 __ CompareRoot(reg, Heap::kTrueValueRootIndex); 1243 __ CompareRoot(reg, Heap::kTrueValueRootIndex);
1072 __ j(equal, true_label); 1244 __ j(equal, true_label);
1073 __ CompareRoot(reg, Heap::kFalseValueRootIndex); 1245 __ CompareRoot(reg, Heap::kFalseValueRootIndex);
1074 __ j(equal, false_label); 1246 __ j(equal, false_label);
1075 __ SmiCompare(reg, Smi::FromInt(0)); 1247 __ Cmp(reg, Smi::FromInt(0));
1076 __ j(equal, false_label); 1248 __ j(equal, false_label);
1077 __ JumpIfSmi(reg, true_label); 1249 __ JumpIfSmi(reg, true_label);
1078 1250
1079 // Test for double values. Plus/minus zero and NaN are false. 1251 // Test for double values. Plus/minus zero and NaN are false.
1080 NearLabel call_stub; 1252 NearLabel call_stub;
1081 __ CompareRoot(FieldOperand(reg, HeapObject::kMapOffset), 1253 __ CompareRoot(FieldOperand(reg, HeapObject::kMapOffset),
1082 Heap::kHeapNumberMapRootIndex); 1254 Heap::kHeapNumberMapRootIndex);
1083 __ j(not_equal, &call_stub); 1255 __ j(not_equal, &call_stub);
1084 1256
1085 // HeapNumber => false iff +0, -0, or NaN. These three cases set the 1257 // HeapNumber => false iff +0, -0, or NaN. These three cases set the
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after
1277 return; 1449 return;
1278 } 1450 }
1279 1451
1280 __ CompareRoot(reg, Heap::kNullValueRootIndex); 1452 __ CompareRoot(reg, Heap::kNullValueRootIndex);
1281 if (instr->is_strict()) { 1453 if (instr->is_strict()) {
1282 __ movl(result, Immediate(Heap::kTrueValueRootIndex)); 1454 __ movl(result, Immediate(Heap::kTrueValueRootIndex));
1283 NearLabel load; 1455 NearLabel load;
1284 __ j(equal, &load); 1456 __ j(equal, &load);
1285 __ movl(result, Immediate(Heap::kFalseValueRootIndex)); 1457 __ movl(result, Immediate(Heap::kFalseValueRootIndex));
1286 __ bind(&load); 1458 __ bind(&load);
1287 __ movq(result, Operand(kRootRegister, result, times_pointer_size, 0)); 1459 __ LoadRootIndexed(result, result, 0);
1288 } else { 1460 } else {
1289 NearLabel true_value, false_value, done; 1461 NearLabel true_value, false_value, done;
1290 __ j(equal, &true_value); 1462 __ j(equal, &true_value);
1291 __ CompareRoot(reg, Heap::kUndefinedValueRootIndex); 1463 __ CompareRoot(reg, Heap::kUndefinedValueRootIndex);
1292 __ j(equal, &true_value); 1464 __ j(equal, &true_value);
1293 __ JumpIfSmi(reg, &false_value); 1465 __ JumpIfSmi(reg, &false_value);
1294 // Check for undetectable objects by looking in the bit field in 1466 // Check for undetectable objects by looking in the bit field in
1295 // the map. The object has already been smi checked. 1467 // the map. The object has already been smi checked.
1296 Register scratch = result; 1468 Register scratch = result;
1297 __ movq(scratch, FieldOperand(reg, HeapObject::kMapOffset)); 1469 __ movq(scratch, FieldOperand(reg, HeapObject::kMapOffset));
(...skipping 19 matching lines...) Expand all
1317 instr->hydrogen()->type().IsSmi()) { 1489 instr->hydrogen()->type().IsSmi()) {
1318 // If the expression is known to untagged or smi, then it's definitely 1490 // If the expression is known to untagged or smi, then it's definitely
1319 // not null, and it can't be a an undetectable object. 1491 // not null, and it can't be a an undetectable object.
1320 // Jump directly to the false block. 1492 // Jump directly to the false block.
1321 EmitGoto(false_block); 1493 EmitGoto(false_block);
1322 return; 1494 return;
1323 } 1495 }
1324 1496
1325 int true_block = chunk_->LookupDestination(instr->true_block_id()); 1497 int true_block = chunk_->LookupDestination(instr->true_block_id());
1326 1498
1327 __ Cmp(reg, Factory::null_value()); 1499 __ CompareRoot(reg, Heap::kNullValueRootIndex);
1328 if (instr->is_strict()) { 1500 if (instr->is_strict()) {
1329 EmitBranch(true_block, false_block, equal); 1501 EmitBranch(true_block, false_block, equal);
1330 } else { 1502 } else {
1331 Label* true_label = chunk_->GetAssemblyLabel(true_block); 1503 Label* true_label = chunk_->GetAssemblyLabel(true_block);
1332 Label* false_label = chunk_->GetAssemblyLabel(false_block); 1504 Label* false_label = chunk_->GetAssemblyLabel(false_block);
1333 __ j(equal, true_label); 1505 __ j(equal, true_label);
1334 __ Cmp(reg, Factory::undefined_value()); 1506 __ CompareRoot(reg, Heap::kUndefinedValueRootIndex);
1335 __ j(equal, true_label); 1507 __ j(equal, true_label);
1336 __ JumpIfSmi(reg, false_label); 1508 __ JumpIfSmi(reg, false_label);
1337 // Check for undetectable objects by looking in the bit field in 1509 // Check for undetectable objects by looking in the bit field in
1338 // the map. The object has already been smi checked. 1510 // the map. The object has already been smi checked.
1339 Register scratch = ToRegister(instr->TempAt(0)); 1511 Register scratch = ToRegister(instr->TempAt(0));
1340 __ movq(scratch, FieldOperand(reg, HeapObject::kMapOffset)); 1512 __ movq(scratch, FieldOperand(reg, HeapObject::kMapOffset));
1341 __ testb(FieldOperand(scratch, Map::kBitFieldOffset), 1513 __ testb(FieldOperand(scratch, Map::kBitFieldOffset),
1342 Immediate(1 << Map::kIsUndetectable)); 1514 Immediate(1 << Map::kIsUndetectable));
1343 EmitBranch(true_block, false_block, not_zero); 1515 EmitBranch(true_block, false_block, not_zero);
1344 } 1516 }
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
1408 Register result = ToRegister(instr->result()); 1580 Register result = ToRegister(instr->result());
1409 if (input_operand->IsRegister()) { 1581 if (input_operand->IsRegister()) {
1410 Register input = ToRegister(input_operand); 1582 Register input = ToRegister(input_operand);
1411 __ CheckSmiToIndicator(result, input); 1583 __ CheckSmiToIndicator(result, input);
1412 } else { 1584 } else {
1413 Operand input = ToOperand(instr->InputAt(0)); 1585 Operand input = ToOperand(instr->InputAt(0));
1414 __ CheckSmiToIndicator(result, input); 1586 __ CheckSmiToIndicator(result, input);
1415 } 1587 }
1416 // result is zero if input is a smi, and one otherwise. 1588 // result is zero if input is a smi, and one otherwise.
1417 ASSERT(Heap::kFalseValueRootIndex == Heap::kTrueValueRootIndex + 1); 1589 ASSERT(Heap::kFalseValueRootIndex == Heap::kTrueValueRootIndex + 1);
1418 __ movq(result, Operand(kRootRegister, result, times_pointer_size, 1590 __ LoadRootIndexed(result, result, Heap::kTrueValueRootIndex);
1419 Heap::kTrueValueRootIndex * kPointerSize));
1420 } 1591 }
1421 1592
1422 1593
1423 void LCodeGen::DoIsSmiAndBranch(LIsSmiAndBranch* instr) { 1594 void LCodeGen::DoIsSmiAndBranch(LIsSmiAndBranch* instr) {
1424 int true_block = chunk_->LookupDestination(instr->true_block_id()); 1595 int true_block = chunk_->LookupDestination(instr->true_block_id());
1425 int false_block = chunk_->LookupDestination(instr->false_block_id()); 1596 int false_block = chunk_->LookupDestination(instr->false_block_id());
1426 1597
1427 Condition is_smi; 1598 Condition is_smi;
1428 if (instr->InputAt(0)->IsRegister()) { 1599 if (instr->InputAt(0)->IsRegister()) {
1429 Register input = ToRegister(instr->InputAt(0)); 1600 Register input = ToRegister(instr->InputAt(0));
(...skipping 20 matching lines...) Expand all
1450 InstanceType to = instr->to(); 1621 InstanceType to = instr->to();
1451 if (from == to) return equal; 1622 if (from == to) return equal;
1452 if (to == LAST_TYPE) return above_equal; 1623 if (to == LAST_TYPE) return above_equal;
1453 if (from == FIRST_TYPE) return below_equal; 1624 if (from == FIRST_TYPE) return below_equal;
1454 UNREACHABLE(); 1625 UNREACHABLE();
1455 return equal; 1626 return equal;
1456 } 1627 }
1457 1628
1458 1629
1459 void LCodeGen::DoHasInstanceType(LHasInstanceType* instr) { 1630 void LCodeGen::DoHasInstanceType(LHasInstanceType* instr) {
1460 Abort("Unimplemented: %s", "DoHasInstanceType"); 1631 Register input = ToRegister(instr->InputAt(0));
1632 Register result = ToRegister(instr->result());
1633
1634 ASSERT(instr->hydrogen()->value()->representation().IsTagged());
1635 __ testl(input, Immediate(kSmiTagMask));
1636 NearLabel done, is_false;
1637 __ j(zero, &is_false);
1638 __ CmpObjectType(input, TestType(instr->hydrogen()), result);
1639 __ j(NegateCondition(BranchCondition(instr->hydrogen())), &is_false);
1640 __ LoadRoot(result, Heap::kTrueValueRootIndex);
1641 __ jmp(&done);
1642 __ bind(&is_false);
1643 __ LoadRoot(result, Heap::kFalseValueRootIndex);
1644 __ bind(&done);
1461 } 1645 }
1462 1646
1463 1647
1464 void LCodeGen::DoHasInstanceTypeAndBranch(LHasInstanceTypeAndBranch* instr) { 1648 void LCodeGen::DoHasInstanceTypeAndBranch(LHasInstanceTypeAndBranch* instr) {
1465 Register input = ToRegister(instr->InputAt(0)); 1649 Register input = ToRegister(instr->InputAt(0));
1466 1650
1467 int true_block = chunk_->LookupDestination(instr->true_block_id()); 1651 int true_block = chunk_->LookupDestination(instr->true_block_id());
1468 int false_block = chunk_->LookupDestination(instr->false_block_id()); 1652 int false_block = chunk_->LookupDestination(instr->false_block_id());
1469 1653
1470 Label* false_label = chunk_->GetAssemblyLabel(false_block); 1654 Label* false_label = chunk_->GetAssemblyLabel(false_block);
1471 1655
1472 __ JumpIfSmi(input, false_label); 1656 __ JumpIfSmi(input, false_label);
1473 1657
1474 __ CmpObjectType(input, TestType(instr->hydrogen()), kScratchRegister); 1658 __ CmpObjectType(input, TestType(instr->hydrogen()), kScratchRegister);
1475 EmitBranch(true_block, false_block, BranchCondition(instr->hydrogen())); 1659 EmitBranch(true_block, false_block, BranchCondition(instr->hydrogen()));
1476 } 1660 }
1477 1661
1478 1662
1663 void LCodeGen::DoGetCachedArrayIndex(LGetCachedArrayIndex* instr) {
1664 Register input = ToRegister(instr->InputAt(0));
1665 Register result = ToRegister(instr->result());
1666
1667 if (FLAG_debug_code) {
1668 __ AbortIfNotString(input);
1669 }
1670
1671 __ movl(result, FieldOperand(input, String::kHashFieldOffset));
1672 ASSERT(String::kHashShift >= kSmiTagSize);
1673 __ IndexFromHash(result, result);
1674 }
1675
1676
1479 void LCodeGen::DoHasCachedArrayIndex(LHasCachedArrayIndex* instr) { 1677 void LCodeGen::DoHasCachedArrayIndex(LHasCachedArrayIndex* instr) {
1480 Abort("Unimplemented: %s", "DoHasCachedArrayIndex"); 1678 Register input = ToRegister(instr->InputAt(0));
1679 Register result = ToRegister(instr->result());
1680
1681 ASSERT(instr->hydrogen()->value()->representation().IsTagged());
1682 __ LoadRoot(result, Heap::kTrueValueRootIndex);
1683 __ testl(FieldOperand(input, String::kHashFieldOffset),
1684 Immediate(String::kContainsCachedArrayIndexMask));
1685 NearLabel done;
1686 __ j(zero, &done);
1687 __ LoadRoot(result, Heap::kFalseValueRootIndex);
1688 __ bind(&done);
1481 } 1689 }
1482 1690
1483 1691
1484 void LCodeGen::DoHasCachedArrayIndexAndBranch( 1692 void LCodeGen::DoHasCachedArrayIndexAndBranch(
1485 LHasCachedArrayIndexAndBranch* instr) { 1693 LHasCachedArrayIndexAndBranch* instr) {
1486 Register input = ToRegister(instr->InputAt(0)); 1694 Register input = ToRegister(instr->InputAt(0));
1487 1695
1488 int true_block = chunk_->LookupDestination(instr->true_block_id()); 1696 int true_block = chunk_->LookupDestination(instr->true_block_id());
1489 int false_block = chunk_->LookupDestination(instr->false_block_id()); 1697 int false_block = chunk_->LookupDestination(instr->false_block_id());
1490 1698
1491 __ testl(FieldOperand(input, String::kHashFieldOffset), 1699 __ testl(FieldOperand(input, String::kHashFieldOffset),
1492 Immediate(String::kContainsCachedArrayIndexMask)); 1700 Immediate(String::kContainsCachedArrayIndexMask));
1493 EmitBranch(true_block, false_block, not_equal); 1701 EmitBranch(true_block, false_block, equal);
1494 } 1702 }
1495 1703
1496 1704
1497 // Branches to a label or falls through with the answer in the z flag. 1705 // Branches to a label or falls through with the answer in the z flag.
1498 // Trashes the temp register and possibly input (if it and temp are aliased). 1706 // Trashes the temp register and possibly input (if it and temp are aliased).
1499 void LCodeGen::EmitClassOfTest(Label* is_true, 1707 void LCodeGen::EmitClassOfTest(Label* is_true,
1500 Label* is_false, 1708 Label* is_false,
1501 Handle<String> class_name, 1709 Handle<String> class_name,
1502 Register input, 1710 Register input,
1503 Register temp) { 1711 Register temp) {
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
1592 Register reg = ToRegister(instr->InputAt(0)); 1800 Register reg = ToRegister(instr->InputAt(0));
1593 int true_block = instr->true_block_id(); 1801 int true_block = instr->true_block_id();
1594 int false_block = instr->false_block_id(); 1802 int false_block = instr->false_block_id();
1595 1803
1596 __ Cmp(FieldOperand(reg, HeapObject::kMapOffset), instr->map()); 1804 __ Cmp(FieldOperand(reg, HeapObject::kMapOffset), instr->map());
1597 EmitBranch(true_block, false_block, equal); 1805 EmitBranch(true_block, false_block, equal);
1598 } 1806 }
1599 1807
1600 1808
1601 void LCodeGen::DoInstanceOf(LInstanceOf* instr) { 1809 void LCodeGen::DoInstanceOf(LInstanceOf* instr) {
1602 Abort("Unimplemented: %s", "DoInstanceOf"); 1810 InstanceofStub stub(InstanceofStub::kNoFlags);
1811 __ push(ToRegister(instr->InputAt(0)));
1812 __ push(ToRegister(instr->InputAt(1)));
1813 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
1814 NearLabel true_value, done;
1815 __ testq(rax, rax);
1816 __ j(zero, &true_value);
1817 __ LoadRoot(ToRegister(instr->result()), Heap::kFalseValueRootIndex);
1818 __ jmp(&done);
1819 __ bind(&true_value);
1820 __ LoadRoot(ToRegister(instr->result()), Heap::kTrueValueRootIndex);
1821 __ bind(&done);
1603 } 1822 }
1604 1823
1605 1824
1606 void LCodeGen::DoInstanceOfAndBranch(LInstanceOfAndBranch* instr) { 1825 void LCodeGen::DoInstanceOfAndBranch(LInstanceOfAndBranch* instr) {
1607 int true_block = chunk_->LookupDestination(instr->true_block_id()); 1826 int true_block = chunk_->LookupDestination(instr->true_block_id());
1608 int false_block = chunk_->LookupDestination(instr->false_block_id()); 1827 int false_block = chunk_->LookupDestination(instr->false_block_id());
1609 1828
1610 InstanceofStub stub(InstanceofStub::kArgsInRegisters); 1829 InstanceofStub stub(InstanceofStub::kNoFlags);
1830 __ push(ToRegister(instr->InputAt(0)));
1831 __ push(ToRegister(instr->InputAt(1)));
1611 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); 1832 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
1612 __ testq(rax, rax); 1833 __ testq(rax, rax);
1613 EmitBranch(true_block, false_block, zero); 1834 EmitBranch(true_block, false_block, zero);
1614 } 1835 }
1615 1836
1616 1837
1617 void LCodeGen::DoInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr) { 1838 void LCodeGen::DoInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr) {
1618 Abort("Unimplemented: %s", "DoInstanceOfKnowGLobal"); 1839 class DeferredInstanceOfKnownGlobal: public LDeferredCode {
1840 public:
1841 DeferredInstanceOfKnownGlobal(LCodeGen* codegen,
1842 LInstanceOfKnownGlobal* instr)
1843 : LDeferredCode(codegen), instr_(instr) { }
1844 virtual void Generate() {
1845 codegen()->DoDeferredLInstanceOfKnownGlobal(instr_, &map_check_);
1846 }
1847
1848 Label* map_check() { return &map_check_; }
1849
1850 private:
1851 LInstanceOfKnownGlobal* instr_;
1852 Label map_check_;
1853 };
1854
1855
1856 DeferredInstanceOfKnownGlobal* deferred;
1857 deferred = new DeferredInstanceOfKnownGlobal(this, instr);
1858
1859 Label done, false_result;
1860 Register object = ToRegister(instr->InputAt(0));
1861
1862 // A Smi is not an instance of anything.
1863 __ JumpIfSmi(object, &false_result);
1864
1865 // This is the inlined call site instanceof cache. The two occurences of the
1866 // hole value will be patched to the last map/result pair generated by the
1867 // instanceof stub.
1868 NearLabel cache_miss;
1869 // Use a temp register to avoid memory operands with variable lengths.
1870 Register map = ToRegister(instr->TempAt(0));
1871 __ movq(map, FieldOperand(object, HeapObject::kMapOffset));
1872 __ bind(deferred->map_check()); // Label for calculating code patching.
1873 __ Move(kScratchRegister, Factory::the_hole_value());
1874 __ cmpq(map, kScratchRegister); // Patched to cached map.
1875 __ j(not_equal, &cache_miss);
1876 // Patched to load either true or false.
1877 __ LoadRoot(ToRegister(instr->result()), Heap::kTheHoleValueRootIndex);
1878 #ifdef DEBUG
1879 // Check that the code size between patch label and patch sites is invariant.
1880 Label end_of_patched_code;
1881 __ bind(&end_of_patched_code);
1882 ASSERT(true);
1883 #endif
1884 __ jmp(&done);
1885
1886 // The inlined call site cache did not match. Check for null and string
1887 // before calling the deferred code.
1888 __ bind(&cache_miss); // Null is not an instance of anything.
1889 __ CompareRoot(object, Heap::kNullValueRootIndex);
1890 __ j(equal, &false_result);
1891
1892 // String values are not instances of anything.
1893 __ JumpIfNotString(object, kScratchRegister, deferred->entry());
1894
1895 __ bind(&false_result);
1896 __ LoadRoot(ToRegister(instr->result()), Heap::kFalseValueRootIndex);
1897
1898 __ bind(deferred->exit());
1899 __ bind(&done);
1619 } 1900 }
1620 1901
1621 1902
1622 void LCodeGen::DoDeferredLInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr, 1903 void LCodeGen::DoDeferredLInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr,
1623 Label* map_check) { 1904 Label* map_check) {
1624 Abort("Unimplemented: %s", "DoDeferredLInstanceOfKnownGlobakl"); 1905 __ PushSafepointRegisters();
1906 InstanceofStub::Flags flags = static_cast<InstanceofStub::Flags>(
1907 InstanceofStub::kNoFlags | InstanceofStub::kCallSiteInlineCheck);
1908 InstanceofStub stub(flags);
1909
1910 __ push(ToRegister(instr->InputAt(0)));
1911 __ Push(instr->function());
1912 Register temp = ToRegister(instr->TempAt(0));
1913 ASSERT(temp.is(rdi));
1914 static const int kAdditionalDelta = 16;
1915 int delta =
1916 masm_->SizeOfCodeGeneratedSince(map_check) + kAdditionalDelta;
1917 __ movq(temp, Immediate(delta));
1918 __ push(temp);
1919 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
1920 __ movq(kScratchRegister, rax);
1921 __ PopSafepointRegisters();
1922 __ testq(kScratchRegister, kScratchRegister);
1923 Label load_false;
1924 Label done;
1925 __ j(not_zero, &load_false);
1926 __ LoadRoot(rax, Heap::kTrueValueRootIndex);
1927 __ jmp(&done);
1928 __ bind(&load_false);
1929 __ LoadRoot(rax, Heap::kFalseValueRootIndex);
1930 __ bind(&done);
1625 } 1931 }
1626 1932
1627 1933
1628 void LCodeGen::DoCmpT(LCmpT* instr) { 1934 void LCodeGen::DoCmpT(LCmpT* instr) {
1629 Token::Value op = instr->op(); 1935 Token::Value op = instr->op();
1630 1936
1631 Handle<Code> ic = CompareIC::GetUninitialized(op); 1937 Handle<Code> ic = CompareIC::GetUninitialized(op);
1632 CallCode(ic, RelocInfo::CODE_TARGET, instr); 1938 CallCode(ic, RelocInfo::CODE_TARGET, instr);
1633 1939
1634 Condition condition = TokenToCondition(op, false); 1940 Condition condition = TokenToCondition(op, false);
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
1711 __ movq(temp, instr->hydrogen()->cell(), RelocInfo::GLOBAL_PROPERTY_CELL); 2017 __ movq(temp, instr->hydrogen()->cell(), RelocInfo::GLOBAL_PROPERTY_CELL);
1712 if (check_hole) { 2018 if (check_hole) {
1713 __ CompareRoot(Operand(temp, 0), Heap::kTheHoleValueRootIndex); 2019 __ CompareRoot(Operand(temp, 0), Heap::kTheHoleValueRootIndex);
1714 DeoptimizeIf(equal, instr->environment()); 2020 DeoptimizeIf(equal, instr->environment());
1715 } 2021 }
1716 __ movq(Operand(temp, 0), value); 2022 __ movq(Operand(temp, 0), value);
1717 } 2023 }
1718 2024
1719 2025
1720 void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) { 2026 void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) {
1721 Abort("Unimplemented: %s", "DoLoadContextSlot"); 2027 Register context = ToRegister(instr->context());
2028 Register result = ToRegister(instr->result());
2029 __ movq(result, ContextOperand(context, instr->slot_index()));
2030 }
2031
2032
2033 void LCodeGen::DoStoreContextSlot(LStoreContextSlot* instr) {
2034 Register context = ToRegister(instr->context());
2035 Register value = ToRegister(instr->value());
2036 __ movq(ContextOperand(context, instr->slot_index()), value);
2037 if (instr->needs_write_barrier()) {
2038 int offset = Context::SlotOffset(instr->slot_index());
2039 Register scratch = ToRegister(instr->TempAt(0));
2040 __ RecordWrite(context, offset, value, scratch);
2041 }
1722 } 2042 }
1723 2043
1724 2044
1725 void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) { 2045 void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) {
1726 Register object = ToRegister(instr->InputAt(0)); 2046 Register object = ToRegister(instr->InputAt(0));
1727 Register result = ToRegister(instr->result()); 2047 Register result = ToRegister(instr->result());
1728 if (instr->hydrogen()->is_in_object()) { 2048 if (instr->hydrogen()->is_in_object()) {
1729 __ movq(result, FieldOperand(object, instr->hydrogen()->offset())); 2049 __ movq(result, FieldOperand(object, instr->hydrogen()->offset()));
1730 } else { 2050 } else {
1731 __ movq(result, FieldOperand(object, JSObject::kPropertiesOffset)); 2051 __ movq(result, FieldOperand(object, JSObject::kPropertiesOffset));
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
1784 __ bind(&done); 2104 __ bind(&done);
1785 } 2105 }
1786 2106
1787 2107
1788 void LCodeGen::DoLoadElements(LLoadElements* instr) { 2108 void LCodeGen::DoLoadElements(LLoadElements* instr) {
1789 Register result = ToRegister(instr->result()); 2109 Register result = ToRegister(instr->result());
1790 Register input = ToRegister(instr->InputAt(0)); 2110 Register input = ToRegister(instr->InputAt(0));
1791 __ movq(result, FieldOperand(input, JSObject::kElementsOffset)); 2111 __ movq(result, FieldOperand(input, JSObject::kElementsOffset));
1792 if (FLAG_debug_code) { 2112 if (FLAG_debug_code) {
1793 NearLabel done; 2113 NearLabel done;
1794 __ Cmp(FieldOperand(result, HeapObject::kMapOffset), 2114 __ CompareRoot(FieldOperand(result, HeapObject::kMapOffset),
1795 Factory::fixed_array_map()); 2115 Heap::kFixedArrayMapRootIndex);
1796 __ j(equal, &done); 2116 __ j(equal, &done);
1797 __ Cmp(FieldOperand(result, HeapObject::kMapOffset), 2117 __ CompareRoot(FieldOperand(result, HeapObject::kMapOffset),
1798 Factory::pixel_array_map()); 2118 Heap::kExternalPixelArrayMapRootIndex);
1799 __ j(equal, &done); 2119 __ j(equal, &done);
1800 __ Cmp(FieldOperand(result, HeapObject::kMapOffset), 2120 __ CompareRoot(FieldOperand(result, HeapObject::kMapOffset),
1801 Factory::fixed_cow_array_map()); 2121 Heap::kFixedCOWArrayMapRootIndex);
1802 __ Check(equal, "Check for fast elements failed."); 2122 __ Check(equal, "Check for fast elements failed.");
1803 __ bind(&done); 2123 __ bind(&done);
1804 } 2124 }
1805 } 2125 }
1806 2126
1807 2127
1808 void LCodeGen::DoLoadPixelArrayExternalPointer( 2128 void LCodeGen::DoLoadExternalArrayPointer(
1809 LLoadPixelArrayExternalPointer* instr) { 2129 LLoadExternalArrayPointer* instr) {
1810 Register result = ToRegister(instr->result()); 2130 Register result = ToRegister(instr->result());
1811 Register input = ToRegister(instr->InputAt(0)); 2131 Register input = ToRegister(instr->InputAt(0));
1812 __ movq(result, FieldOperand(input, PixelArray::kExternalPointerOffset)); 2132 __ movq(result, FieldOperand(input,
2133 ExternalPixelArray::kExternalPointerOffset));
1813 } 2134 }
1814 2135
1815 2136
1816 void LCodeGen::DoAccessArgumentsAt(LAccessArgumentsAt* instr) { 2137 void LCodeGen::DoAccessArgumentsAt(LAccessArgumentsAt* instr) {
1817 Register arguments = ToRegister(instr->arguments()); 2138 Register arguments = ToRegister(instr->arguments());
1818 Register length = ToRegister(instr->length()); 2139 Register length = ToRegister(instr->length());
1819 Register result = ToRegister(instr->result()); 2140 Register result = ToRegister(instr->result());
1820 2141
1821 if (instr->index()->IsRegister()) { 2142 if (instr->index()->IsRegister()) {
1822 __ subl(length, ToRegister(instr->index())); 2143 __ subl(length, ToRegister(instr->index()));
(...skipping 14 matching lines...) Expand all
1837 Register result = ToRegister(instr->result()); 2158 Register result = ToRegister(instr->result());
1838 ASSERT(result.is(elements)); 2159 ASSERT(result.is(elements));
1839 2160
1840 // Load the result. 2161 // Load the result.
1841 __ movq(result, FieldOperand(elements, 2162 __ movq(result, FieldOperand(elements,
1842 key, 2163 key,
1843 times_pointer_size, 2164 times_pointer_size,
1844 FixedArray::kHeaderSize)); 2165 FixedArray::kHeaderSize));
1845 2166
1846 // Check for the hole value. 2167 // Check for the hole value.
1847 __ Cmp(result, Factory::the_hole_value()); 2168 __ CompareRoot(result, Heap::kTheHoleValueRootIndex);
1848 DeoptimizeIf(equal, instr->environment()); 2169 DeoptimizeIf(equal, instr->environment());
1849 } 2170 }
1850 2171
1851 2172
1852 void LCodeGen::DoLoadPixelArrayElement(LLoadPixelArrayElement* instr) { 2173 void LCodeGen::DoLoadPixelArrayElement(LLoadPixelArrayElement* instr) {
1853 Register external_elements = ToRegister(instr->external_pointer()); 2174 Register external_elements = ToRegister(instr->external_pointer());
1854 Register key = ToRegister(instr->key()); 2175 Register key = ToRegister(instr->key());
1855 Register result = ToRegister(instr->result()); 2176 Register result = ToRegister(instr->result());
1856 ASSERT(result.is(external_elements)); 2177 ASSERT(result.is(external_elements));
1857 2178
1858 // Load the result. 2179 // Load the result.
1859 __ movzxbq(result, Operand(external_elements, key, times_1, 0)); 2180 __ movzxbq(result, Operand(external_elements, key, times_1, 0));
1860 } 2181 }
1861 2182
1862 2183
1863 void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) { 2184 void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) {
1864 Abort("Unimplemented: %s", "DoLoadKeyedGeneric"); 2185 ASSERT(ToRegister(instr->object()).is(rdx));
2186 ASSERT(ToRegister(instr->key()).is(rax));
2187
2188 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
2189 CallCode(ic, RelocInfo::CODE_TARGET, instr);
1865 } 2190 }
1866 2191
1867 2192
1868 void LCodeGen::DoArgumentsElements(LArgumentsElements* instr) { 2193 void LCodeGen::DoArgumentsElements(LArgumentsElements* instr) {
1869 Register result = ToRegister(instr->result()); 2194 Register result = ToRegister(instr->result());
1870 2195
1871 // Check for arguments adapter frame. 2196 // Check for arguments adapter frame.
1872 NearLabel done, adapted; 2197 NearLabel done, adapted;
1873 __ movq(result, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); 2198 __ movq(result, Operand(rbp, StandardFrameConstants::kCallerFPOffset));
1874 __ SmiCompare(Operand(result, StandardFrameConstants::kContextOffset), 2199 __ Cmp(Operand(result, StandardFrameConstants::kContextOffset),
1875 Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); 2200 Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
1876 __ j(equal, &adapted); 2201 __ j(equal, &adapted);
1877 2202
1878 // No arguments adaptor frame. 2203 // No arguments adaptor frame.
1879 __ movq(result, rbp); 2204 __ movq(result, rbp);
1880 __ jmp(&done); 2205 __ jmp(&done);
1881 2206
1882 // Arguments adaptor frame present. 2207 // Arguments adaptor frame present.
1883 __ bind(&adapted); 2208 __ bind(&adapted);
1884 __ movq(result, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); 2209 __ movq(result, Operand(rbp, StandardFrameConstants::kCallerFPOffset));
1885 2210
(...skipping 22 matching lines...) Expand all
1908 __ movq(result, Operand(result, 2233 __ movq(result, Operand(result,
1909 ArgumentsAdaptorFrameConstants::kLengthOffset)); 2234 ArgumentsAdaptorFrameConstants::kLengthOffset));
1910 __ SmiToInteger32(result, result); 2235 __ SmiToInteger32(result, result);
1911 2236
1912 // Argument length is in result register. 2237 // Argument length is in result register.
1913 __ bind(&done); 2238 __ bind(&done);
1914 } 2239 }
1915 2240
1916 2241
1917 void LCodeGen::DoApplyArguments(LApplyArguments* instr) { 2242 void LCodeGen::DoApplyArguments(LApplyArguments* instr) {
1918 Abort("Unimplemented: %s", "DoApplyArguments"); 2243 Register receiver = ToRegister(instr->receiver());
2244 Register function = ToRegister(instr->function());
2245 Register length = ToRegister(instr->length());
2246 Register elements = ToRegister(instr->elements());
2247 ASSERT(receiver.is(rax)); // Used for parameter count.
2248 ASSERT(function.is(rdi)); // Required by InvokeFunction.
2249 ASSERT(ToRegister(instr->result()).is(rax));
2250
2251 // If the receiver is null or undefined, we have to pass the global object
2252 // as a receiver.
2253 NearLabel global_object, receiver_ok;
2254 __ CompareRoot(receiver, Heap::kNullValueRootIndex);
2255 __ j(equal, &global_object);
2256 __ CompareRoot(receiver, Heap::kUndefinedValueRootIndex);
2257 __ j(equal, &global_object);
2258
2259 // The receiver should be a JS object.
2260 Condition is_smi = __ CheckSmi(receiver);
2261 DeoptimizeIf(is_smi, instr->environment());
2262 __ CmpObjectType(receiver, FIRST_JS_OBJECT_TYPE, kScratchRegister);
2263 DeoptimizeIf(below, instr->environment());
2264 __ jmp(&receiver_ok);
2265
2266 __ bind(&global_object);
2267 // TODO(kmillikin): We have a hydrogen value for the global object. See
2268 // if it's better to use it than to explicitly fetch it from the context
2269 // here.
2270 __ movq(receiver, Operand(rbp, StandardFrameConstants::kContextOffset));
2271 __ movq(receiver, ContextOperand(receiver, Context::GLOBAL_INDEX));
2272 __ bind(&receiver_ok);
2273
2274 // Copy the arguments to this function possibly from the
2275 // adaptor frame below it.
2276 const uint32_t kArgumentsLimit = 1 * KB;
2277 __ cmpq(length, Immediate(kArgumentsLimit));
2278 DeoptimizeIf(above, instr->environment());
2279
2280 __ push(receiver);
2281 __ movq(receiver, length);
2282
2283 // Loop through the arguments pushing them onto the execution
2284 // stack.
2285 NearLabel invoke, loop;
2286 // length is a small non-negative integer, due to the test above.
2287 __ testl(length, length);
2288 __ j(zero, &invoke);
2289 __ bind(&loop);
2290 __ push(Operand(elements, length, times_pointer_size, 1 * kPointerSize));
2291 __ decl(length);
2292 __ j(not_zero, &loop);
2293
2294 // Invoke the function.
2295 __ bind(&invoke);
2296 ASSERT(instr->HasPointerMap() && instr->HasDeoptimizationEnvironment());
2297 LPointerMap* pointers = instr->pointer_map();
2298 LEnvironment* env = instr->deoptimization_environment();
2299 RecordPosition(pointers->position());
2300 RegisterEnvironmentForDeoptimization(env);
2301 SafepointGenerator safepoint_generator(this,
2302 pointers,
2303 env->deoptimization_index(),
2304 true);
2305 v8::internal::ParameterCount actual(rax);
2306 __ InvokeFunction(function, actual, CALL_FUNCTION, &safepoint_generator);
1919 } 2307 }
1920 2308
1921 2309
1922 void LCodeGen::DoPushArgument(LPushArgument* instr) { 2310 void LCodeGen::DoPushArgument(LPushArgument* instr) {
1923 LOperand* argument = instr->InputAt(0); 2311 LOperand* argument = instr->InputAt(0);
1924 if (argument->IsConstantOperand()) { 2312 if (argument->IsConstantOperand()) {
1925 LConstantOperand* const_op = LConstantOperand::cast(argument); 2313 EmitPushConstantOperand(argument);
1926 Handle<Object> literal = chunk_->LookupLiteral(const_op);
1927 Representation r = chunk_->LookupLiteralRepresentation(const_op);
1928 if (r.IsInteger32()) {
1929 ASSERT(literal->IsNumber());
1930 __ push(Immediate(static_cast<int32_t>(literal->Number())));
1931 } else if (r.IsDouble()) {
1932 Abort("unsupported double immediate");
1933 } else {
1934 ASSERT(r.IsTagged());
1935 __ Push(literal);
1936 }
1937 } else if (argument->IsRegister()) { 2314 } else if (argument->IsRegister()) {
1938 __ push(ToRegister(argument)); 2315 __ push(ToRegister(argument));
1939 } else { 2316 } else {
1940 ASSERT(!argument->IsDoubleRegister()); 2317 ASSERT(!argument->IsDoubleRegister());
1941 __ push(ToOperand(argument)); 2318 __ push(ToOperand(argument));
1942 } 2319 }
1943 } 2320 }
1944 2321
1945 2322
1946 void LCodeGen::DoContext(LContext* instr) { 2323 void LCodeGen::DoContext(LContext* instr) {
1947 Register result = ToRegister(instr->result()); 2324 Register result = ToRegister(instr->result());
1948 __ movq(result, Operand(rbp, StandardFrameConstants::kContextOffset)); 2325 __ movq(result, Operand(rbp, StandardFrameConstants::kContextOffset));
1949 } 2326 }
1950 2327
1951 2328
2329 void LCodeGen::DoOuterContext(LOuterContext* instr) {
2330 Register context = ToRegister(instr->context());
2331 Register result = ToRegister(instr->result());
2332 __ movq(result,
2333 Operand(context, Context::SlotOffset(Context::CLOSURE_INDEX)));
2334 __ movq(result, FieldOperand(result, JSFunction::kContextOffset));
2335 }
2336
2337
1952 void LCodeGen::DoGlobalObject(LGlobalObject* instr) { 2338 void LCodeGen::DoGlobalObject(LGlobalObject* instr) {
1953 Register result = ToRegister(instr->result()); 2339 Register result = ToRegister(instr->result());
1954 __ movq(result, GlobalObjectOperand()); 2340 __ movq(result, GlobalObjectOperand());
1955 } 2341 }
1956 2342
1957 2343
1958 void LCodeGen::DoGlobalReceiver(LGlobalReceiver* instr) { 2344 void LCodeGen::DoGlobalReceiver(LGlobalReceiver* instr) {
1959 Register result = ToRegister(instr->result()); 2345 Register result = ToRegister(instr->result());
1960 __ movq(result, Operand(rsi, Context::SlotOffset(Context::GLOBAL_INDEX))); 2346 __ movq(result, Operand(rsi, Context::SlotOffset(Context::GLOBAL_INDEX)));
1961 __ movq(result, FieldOperand(result, GlobalObject::kGlobalReceiverOffset)); 2347 __ movq(result, FieldOperand(result, GlobalObject::kGlobalReceiverOffset));
1962 } 2348 }
1963 2349
1964 2350
1965 void LCodeGen::CallKnownFunction(Handle<JSFunction> function, 2351 void LCodeGen::CallKnownFunction(Handle<JSFunction> function,
1966 int arity, 2352 int arity,
1967 LInstruction* instr) { 2353 LInstruction* instr) {
1968 // Change context if needed. 2354 // Change context if needed.
1969 bool change_context = 2355 bool change_context =
1970 (graph()->info()->closure()->context() != function->context()) || 2356 (info()->closure()->context() != function->context()) ||
1971 scope()->contains_with() || 2357 scope()->contains_with() ||
1972 (scope()->num_heap_slots() > 0); 2358 (scope()->num_heap_slots() > 0);
1973 if (change_context) { 2359 if (change_context) {
1974 __ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset)); 2360 __ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset));
1975 } 2361 }
1976 2362
1977 // Set rax to arguments count if adaption is not needed. Assumes that rax 2363 // Set rax to arguments count if adaption is not needed. Assumes that rax
1978 // is available to write to at this point. 2364 // is available to write to at this point.
1979 if (!function->NeedsArgumentsAdaption()) { 2365 if (!function->NeedsArgumentsAdaption()) {
1980 __ Set(rax, arity); 2366 __ Set(rax, arity);
1981 } 2367 }
1982 2368
1983 LPointerMap* pointers = instr->pointer_map(); 2369 LPointerMap* pointers = instr->pointer_map();
1984 RecordPosition(pointers->position()); 2370 RecordPosition(pointers->position());
1985 2371
1986 // Invoke function. 2372 // Invoke function.
1987 if (*function == *graph()->info()->closure()) { 2373 if (*function == *info()->closure()) {
1988 __ CallSelf(); 2374 __ CallSelf();
1989 } else { 2375 } else {
1990 __ call(FieldOperand(rdi, JSFunction::kCodeEntryOffset)); 2376 __ call(FieldOperand(rdi, JSFunction::kCodeEntryOffset));
1991 } 2377 }
1992 2378
1993 // Setup deoptimization. 2379 // Setup deoptimization.
1994 RegisterLazyDeoptimization(instr); 2380 RegisterLazyDeoptimization(instr);
1995 2381
1996 // Restore context. 2382 // Restore context.
1997 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 2383 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
1998 } 2384 }
1999 2385
2000 2386
2001 void LCodeGen::DoCallConstantFunction(LCallConstantFunction* instr) { 2387 void LCodeGen::DoCallConstantFunction(LCallConstantFunction* instr) {
2002 ASSERT(ToRegister(instr->result()).is(rax)); 2388 ASSERT(ToRegister(instr->result()).is(rax));
2003 __ Move(rdi, instr->function()); 2389 __ Move(rdi, instr->function());
2004 CallKnownFunction(instr->function(), instr->arity(), instr); 2390 CallKnownFunction(instr->function(), instr->arity(), instr);
2005 } 2391 }
2006 2392
2007 2393
2008 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LUnaryMathOperation* instr) { 2394 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LUnaryMathOperation* instr) {
2009 Abort("Unimplemented: %s", "DoDeferredMathAbsTaggedHeapNumber"); 2395 Register input_reg = ToRegister(instr->InputAt(0));
2396 __ CompareRoot(FieldOperand(input_reg, HeapObject::kMapOffset),
2397 Heap::kHeapNumberMapRootIndex);
2398 DeoptimizeIf(not_equal, instr->environment());
2399
2400 Label done;
2401 Register tmp = input_reg.is(rax) ? rcx : rax;
2402 Register tmp2 = tmp.is(rcx) ? rdx : input_reg.is(rcx) ? rdx : rcx;
2403
2404 // Preserve the value of all registers.
2405 __ PushSafepointRegisters();
2406
2407 Label negative;
2408 __ movl(tmp, FieldOperand(input_reg, HeapNumber::kExponentOffset));
2409 // Check the sign of the argument. If the argument is positive, just
2410 // return it. We do not need to patch the stack since |input| and
2411 // |result| are the same register and |input| will be restored
2412 // unchanged by popping safepoint registers.
2413 __ testl(tmp, Immediate(HeapNumber::kSignMask));
2414 __ j(not_zero, &negative);
2415 __ jmp(&done);
2416
2417 __ bind(&negative);
2418
2419 Label allocated, slow;
2420 __ AllocateHeapNumber(tmp, tmp2, &slow);
2421 __ jmp(&allocated);
2422
2423 // Slow case: Call the runtime system to do the number allocation.
2424 __ bind(&slow);
2425
2426 __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber);
2427 RecordSafepointWithRegisters(
2428 instr->pointer_map(), 0, Safepoint::kNoDeoptimizationIndex);
2429 // Set the pointer to the new heap number in tmp.
2430 if (!tmp.is(rax)) {
2431 __ movq(tmp, rax);
2432 }
2433
2434 // Restore input_reg after call to runtime.
2435 __ LoadFromSafepointRegisterSlot(input_reg, input_reg);
2436
2437 __ bind(&allocated);
2438 __ movq(tmp2, FieldOperand(input_reg, HeapNumber::kValueOffset));
2439 __ shl(tmp2, Immediate(1));
2440 __ shr(tmp2, Immediate(1));
2441 __ movq(FieldOperand(tmp, HeapNumber::kValueOffset), tmp2);
2442 __ StoreToSafepointRegisterSlot(input_reg, tmp);
2443
2444 __ bind(&done);
2445 __ PopSafepointRegisters();
2446 }
2447
2448
2449 void LCodeGen::EmitIntegerMathAbs(LUnaryMathOperation* instr) {
2450 Register input_reg = ToRegister(instr->InputAt(0));
2451 __ testl(input_reg, input_reg);
2452 Label is_positive;
2453 __ j(not_sign, &is_positive);
2454 __ negl(input_reg); // Sets flags.
2455 DeoptimizeIf(negative, instr->environment());
2456 __ bind(&is_positive);
2010 } 2457 }
2011 2458
2012 2459
2013 void LCodeGen::DoMathAbs(LUnaryMathOperation* instr) { 2460 void LCodeGen::DoMathAbs(LUnaryMathOperation* instr) {
2014 Abort("Unimplemented: %s", "DoMathAbs"); 2461 // Class for deferred case.
2462 class DeferredMathAbsTaggedHeapNumber: public LDeferredCode {
2463 public:
2464 DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen,
2465 LUnaryMathOperation* instr)
2466 : LDeferredCode(codegen), instr_(instr) { }
2467 virtual void Generate() {
2468 codegen()->DoDeferredMathAbsTaggedHeapNumber(instr_);
2469 }
2470 private:
2471 LUnaryMathOperation* instr_;
2472 };
2473
2474 ASSERT(instr->InputAt(0)->Equals(instr->result()));
2475 Representation r = instr->hydrogen()->value()->representation();
2476
2477 if (r.IsDouble()) {
2478 XMMRegister scratch = xmm0;
2479 XMMRegister input_reg = ToDoubleRegister(instr->InputAt(0));
2480 __ xorpd(scratch, scratch);
2481 __ subsd(scratch, input_reg);
2482 __ andpd(input_reg, scratch);
2483 } else if (r.IsInteger32()) {
2484 EmitIntegerMathAbs(instr);
2485 } else { // Tagged case.
2486 DeferredMathAbsTaggedHeapNumber* deferred =
2487 new DeferredMathAbsTaggedHeapNumber(this, instr);
2488 Register input_reg = ToRegister(instr->InputAt(0));
2489 // Smi check.
2490 __ JumpIfNotSmi(input_reg, deferred->entry());
2491 EmitIntegerMathAbs(instr);
2492 __ bind(deferred->exit());
2493 }
2015 } 2494 }
2016 2495
2017 2496
2018 void LCodeGen::DoMathFloor(LUnaryMathOperation* instr) { 2497 void LCodeGen::DoMathFloor(LUnaryMathOperation* instr) {
2019 Abort("Unimplemented: %s", "DoMathFloor"); 2498 XMMRegister xmm_scratch = xmm0;
2499 Register output_reg = ToRegister(instr->result());
2500 XMMRegister input_reg = ToDoubleRegister(instr->InputAt(0));
2501 __ xorpd(xmm_scratch, xmm_scratch); // Zero the register.
2502 __ ucomisd(input_reg, xmm_scratch);
2503
2504 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
2505 DeoptimizeIf(below_equal, instr->environment());
2506 } else {
2507 DeoptimizeIf(below, instr->environment());
2508 }
2509
2510 // Use truncating instruction (OK because input is positive).
2511 __ cvttsd2si(output_reg, input_reg);
2512
2513 // Overflow is signalled with minint.
2514 __ cmpl(output_reg, Immediate(0x80000000));
2515 DeoptimizeIf(equal, instr->environment());
2020 } 2516 }
2021 2517
2022 2518
2023 void LCodeGen::DoMathRound(LUnaryMathOperation* instr) { 2519 void LCodeGen::DoMathRound(LUnaryMathOperation* instr) {
2024 Abort("Unimplemented: %s", "DoMathRound"); 2520 const XMMRegister xmm_scratch = xmm0;
2521 Register output_reg = ToRegister(instr->result());
2522 XMMRegister input_reg = ToDoubleRegister(instr->InputAt(0));
2523
2524 // xmm_scratch = 0.5
2525 __ movq(kScratchRegister, V8_INT64_C(0x3FE0000000000000), RelocInfo::NONE);
2526 __ movq(xmm_scratch, kScratchRegister);
2527
2528 // input = input + 0.5
2529 __ addsd(input_reg, xmm_scratch);
2530
2531 // We need to return -0 for the input range [-0.5, 0[, otherwise
2532 // compute Math.floor(value + 0.5).
2533 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
2534 __ ucomisd(input_reg, xmm_scratch);
2535 DeoptimizeIf(below_equal, instr->environment());
2536 } else {
2537 // If we don't need to bailout on -0, we check only bailout
2538 // on negative inputs.
2539 __ xorpd(xmm_scratch, xmm_scratch); // Zero the register.
2540 __ ucomisd(input_reg, xmm_scratch);
2541 DeoptimizeIf(below, instr->environment());
2542 }
2543
2544 // Compute Math.floor(value + 0.5).
2545 // Use truncating instruction (OK because input is positive).
2546 __ cvttsd2si(output_reg, input_reg);
2547
2548 // Overflow is signalled with minint.
2549 __ cmpl(output_reg, Immediate(0x80000000));
2550 DeoptimizeIf(equal, instr->environment());
2025 } 2551 }
2026 2552
2027 2553
2028 void LCodeGen::DoMathSqrt(LUnaryMathOperation* instr) { 2554 void LCodeGen::DoMathSqrt(LUnaryMathOperation* instr) {
2029 Abort("Unimplemented: %s", "DoMathSqrt"); 2555 XMMRegister input_reg = ToDoubleRegister(instr->InputAt(0));
2556 ASSERT(ToDoubleRegister(instr->result()).is(input_reg));
2557 __ sqrtsd(input_reg, input_reg);
2030 } 2558 }
2031 2559
2032 2560
2033 void LCodeGen::DoMathPowHalf(LUnaryMathOperation* instr) { 2561 void LCodeGen::DoMathPowHalf(LUnaryMathOperation* instr) {
2034 Abort("Unimplemented: %s", "DoMathPowHalf"); 2562 XMMRegister xmm_scratch = xmm0;
2563 XMMRegister input_reg = ToDoubleRegister(instr->InputAt(0));
2564 ASSERT(ToDoubleRegister(instr->result()).is(input_reg));
2565 __ xorpd(xmm_scratch, xmm_scratch);
2566 __ addsd(input_reg, xmm_scratch); // Convert -0 to +0.
2567 __ sqrtsd(input_reg, input_reg);
2035 } 2568 }
2036 2569
2037 2570
2038 void LCodeGen::DoPower(LPower* instr) { 2571 void LCodeGen::DoPower(LPower* instr) {
2039 Abort("Unimplemented: %s", "DoPower"); 2572 LOperand* left = instr->InputAt(0);
2573 XMMRegister left_reg = ToDoubleRegister(left);
2574 ASSERT(!left_reg.is(xmm1));
2575 LOperand* right = instr->InputAt(1);
2576 XMMRegister result_reg = ToDoubleRegister(instr->result());
2577 Representation exponent_type = instr->hydrogen()->right()->representation();
2578 if (exponent_type.IsDouble()) {
2579 __ PrepareCallCFunction(2);
2580 // Move arguments to correct registers
2581 __ movsd(xmm0, left_reg);
2582 ASSERT(ToDoubleRegister(right).is(xmm1));
2583 __ CallCFunction(ExternalReference::power_double_double_function(), 2);
2584 } else if (exponent_type.IsInteger32()) {
2585 __ PrepareCallCFunction(2);
2586 // Move arguments to correct registers: xmm0 and edi (not rdi).
2587 // On Windows, the registers are xmm0 and edx.
2588 __ movsd(xmm0, left_reg);
2589 #ifdef _WIN64
2590 ASSERT(ToRegister(right).is(rdx));
2591 #else
2592 ASSERT(ToRegister(right).is(rdi));
2593 #endif
2594 __ CallCFunction(ExternalReference::power_double_int_function(), 2);
2595 } else {
2596 ASSERT(exponent_type.IsTagged());
2597 CpuFeatures::Scope scope(SSE2);
2598 Register right_reg = ToRegister(right);
2599
2600 Label non_smi, call;
2601 __ JumpIfNotSmi(right_reg, &non_smi);
2602 __ SmiToInteger32(right_reg, right_reg);
2603 __ cvtlsi2sd(xmm1, right_reg);
2604 __ jmp(&call);
2605
2606 __ bind(&non_smi);
2607 __ CmpObjectType(right_reg, HEAP_NUMBER_TYPE , kScratchRegister);
2608 DeoptimizeIf(not_equal, instr->environment());
2609 __ movsd(xmm1, FieldOperand(right_reg, HeapNumber::kValueOffset));
2610
2611 __ bind(&call);
2612 __ PrepareCallCFunction(2);
2613 // Move arguments to correct registers xmm0 and xmm1.
2614 __ movsd(xmm0, left_reg);
2615 // Right argument is already in xmm1.
2616 __ CallCFunction(ExternalReference::power_double_double_function(), 2);
2617 }
2618 // Return value is in xmm0.
2619 __ movsd(result_reg, xmm0);
2620 // Restore context register.
2621 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
2040 } 2622 }
2041 2623
2042 2624
2043 void LCodeGen::DoMathLog(LUnaryMathOperation* instr) { 2625 void LCodeGen::DoMathLog(LUnaryMathOperation* instr) {
2044 Abort("Unimplemented: %s", "DoMathLog"); 2626 ASSERT(ToDoubleRegister(instr->result()).is(xmm1));
2627 TranscendentalCacheStub stub(TranscendentalCache::LOG,
2628 TranscendentalCacheStub::UNTAGGED);
2629 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
2045 } 2630 }
2046 2631
2047 2632
2048 void LCodeGen::DoMathCos(LUnaryMathOperation* instr) { 2633 void LCodeGen::DoMathCos(LUnaryMathOperation* instr) {
2049 Abort("Unimplemented: %s", "DoMathCos"); 2634 ASSERT(ToDoubleRegister(instr->result()).is(xmm1));
2635 TranscendentalCacheStub stub(TranscendentalCache::COS,
2636 TranscendentalCacheStub::UNTAGGED);
2637 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
2050 } 2638 }
2051 2639
2052 2640
2053 void LCodeGen::DoMathSin(LUnaryMathOperation* instr) { 2641 void LCodeGen::DoMathSin(LUnaryMathOperation* instr) {
2054 Abort("Unimplemented: %s", "DoMathSin"); 2642 ASSERT(ToDoubleRegister(instr->result()).is(xmm1));
2643 TranscendentalCacheStub stub(TranscendentalCache::SIN,
2644 TranscendentalCacheStub::UNTAGGED);
2645 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
2055 } 2646 }
2056 2647
2057 2648
2058 void LCodeGen::DoUnaryMathOperation(LUnaryMathOperation* instr) { 2649 void LCodeGen::DoUnaryMathOperation(LUnaryMathOperation* instr) {
2059 Abort("Unimplemented: %s", "DoUnaryMathOperation"); 2650 switch (instr->op()) {
2651 case kMathAbs:
2652 DoMathAbs(instr);
2653 break;
2654 case kMathFloor:
2655 DoMathFloor(instr);
2656 break;
2657 case kMathRound:
2658 DoMathRound(instr);
2659 break;
2660 case kMathSqrt:
2661 DoMathSqrt(instr);
2662 break;
2663 case kMathPowHalf:
2664 DoMathPowHalf(instr);
2665 break;
2666 case kMathCos:
2667 DoMathCos(instr);
2668 break;
2669 case kMathSin:
2670 DoMathSin(instr);
2671 break;
2672 case kMathLog:
2673 DoMathLog(instr);
2674 break;
2675
2676 default:
2677 UNREACHABLE();
2678 }
2060 } 2679 }
2061 2680
2062 2681
2063 void LCodeGen::DoCallKeyed(LCallKeyed* instr) { 2682 void LCodeGen::DoCallKeyed(LCallKeyed* instr) {
2064 Abort("Unimplemented: %s", "DoCallKeyed"); 2683 ASSERT(ToRegister(instr->key()).is(rcx));
2065 } 2684 ASSERT(ToRegister(instr->result()).is(rax));
2066 2685
2067 2686 int arity = instr->arity();
2687 Handle<Code> ic = StubCache::ComputeKeyedCallInitialize(arity, NOT_IN_LOOP);
2688 CallCode(ic, RelocInfo::CODE_TARGET, instr);
2689 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
2690 }
2691
2692
2068 void LCodeGen::DoCallNamed(LCallNamed* instr) { 2693 void LCodeGen::DoCallNamed(LCallNamed* instr) {
2069 ASSERT(ToRegister(instr->result()).is(rax)); 2694 ASSERT(ToRegister(instr->result()).is(rax));
2070 2695
2071 int arity = instr->arity(); 2696 int arity = instr->arity();
2072 Handle<Code> ic = StubCache::ComputeCallInitialize(arity, NOT_IN_LOOP); 2697 Handle<Code> ic = StubCache::ComputeCallInitialize(arity, NOT_IN_LOOP);
2073 __ Move(rcx, instr->name()); 2698 __ Move(rcx, instr->name());
2074 CallCode(ic, RelocInfo::CODE_TARGET, instr); 2699 CallCode(ic, RelocInfo::CODE_TARGET, instr);
2075 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 2700 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
2076 } 2701 }
2077 2702
2078 2703
2079 void LCodeGen::DoCallFunction(LCallFunction* instr) { 2704 void LCodeGen::DoCallFunction(LCallFunction* instr) {
2080 Abort("Unimplemented: %s", "DoCallFunction"); 2705 ASSERT(ToRegister(instr->result()).is(rax));
2706
2707 int arity = instr->arity();
2708 CallFunctionStub stub(arity, NOT_IN_LOOP, RECEIVER_MIGHT_BE_VALUE);
2709 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
2710 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
2711 __ Drop(1);
2081 } 2712 }
2082 2713
2083 2714
2084 void LCodeGen::DoCallGlobal(LCallGlobal* instr) { 2715 void LCodeGen::DoCallGlobal(LCallGlobal* instr) {
2085 ASSERT(ToRegister(instr->result()).is(rax)); 2716 ASSERT(ToRegister(instr->result()).is(rax));
2086 int arity = instr->arity(); 2717 int arity = instr->arity();
2087 Handle<Code> ic = StubCache::ComputeCallInitialize(arity, NOT_IN_LOOP); 2718 Handle<Code> ic = StubCache::ComputeCallInitialize(arity, NOT_IN_LOOP);
2088 __ Move(rcx, instr->name()); 2719 __ Move(rcx, instr->name());
2089 CallCode(ic, RelocInfo::CODE_TARGET_CONTEXT, instr); 2720 CallCode(ic, RelocInfo::CODE_TARGET_CONTEXT, instr);
2090 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 2721 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
2137 if (instr->needs_write_barrier()) { 2768 if (instr->needs_write_barrier()) {
2138 // Update the write barrier for the properties array. 2769 // Update the write barrier for the properties array.
2139 // object is used as a scratch register. 2770 // object is used as a scratch register.
2140 __ RecordWrite(temp, offset, value, object); 2771 __ RecordWrite(temp, offset, value, object);
2141 } 2772 }
2142 } 2773 }
2143 } 2774 }
2144 2775
2145 2776
2146 void LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) { 2777 void LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) {
2147 Abort("Unimplemented: %s", "DoStoreNamedGeneric"); 2778 ASSERT(ToRegister(instr->object()).is(rdx));
2779 ASSERT(ToRegister(instr->value()).is(rax));
2780
2781 __ Move(rcx, instr->hydrogen()->name());
2782 Handle<Code> ic(Builtins::builtin(
2783 info_->is_strict() ? Builtins::StoreIC_Initialize_Strict
2784 : Builtins::StoreIC_Initialize));
2785 CallCode(ic, RelocInfo::CODE_TARGET, instr);
2786 }
2787
2788
2789 void LCodeGen::DoStorePixelArrayElement(LStorePixelArrayElement* instr) {
2790 Register external_pointer = ToRegister(instr->external_pointer());
2791 Register key = ToRegister(instr->key());
2792 Register value = ToRegister(instr->value());
2793
2794 { // Clamp the value to [0..255].
2795 NearLabel done;
2796 __ testl(value, Immediate(0xFFFFFF00));
2797 __ j(zero, &done);
2798 __ setcc(negative, value); // 1 if negative, 0 if positive.
2799 __ decb(value); // 0 if negative, 255 if positive.
2800 __ bind(&done);
2801 }
2802
2803 __ movb(Operand(external_pointer, key, times_1, 0), value);
2148 } 2804 }
2149 2805
2150 2806
2151 void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) { 2807 void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) {
2152 if (instr->length()->IsRegister()) { 2808 if (instr->length()->IsRegister()) {
2153 __ cmpq(ToRegister(instr->index()), ToRegister(instr->length())); 2809 __ cmpq(ToRegister(instr->index()), ToRegister(instr->length()));
2154 } else { 2810 } else {
2155 __ cmpq(ToRegister(instr->index()), ToOperand(instr->length())); 2811 __ cmpq(ToRegister(instr->index()), ToOperand(instr->length()));
2156 } 2812 }
2157 DeoptimizeIf(above_equal, instr->environment()); 2813 DeoptimizeIf(above_equal, instr->environment());
(...skipping 25 matching lines...) Expand all
2183 __ lea(key, FieldOperand(elements, 2839 __ lea(key, FieldOperand(elements,
2184 key, 2840 key,
2185 times_pointer_size, 2841 times_pointer_size,
2186 FixedArray::kHeaderSize)); 2842 FixedArray::kHeaderSize));
2187 __ RecordWrite(elements, key, value); 2843 __ RecordWrite(elements, key, value);
2188 } 2844 }
2189 } 2845 }
2190 2846
2191 2847
2192 void LCodeGen::DoStoreKeyedGeneric(LStoreKeyedGeneric* instr) { 2848 void LCodeGen::DoStoreKeyedGeneric(LStoreKeyedGeneric* instr) {
2193 Abort("Unimplemented: %s", "DoStoreKeyedGeneric"); 2849 ASSERT(ToRegister(instr->object()).is(rdx));
2850 ASSERT(ToRegister(instr->key()).is(rcx));
2851 ASSERT(ToRegister(instr->value()).is(rax));
2852
2853 Handle<Code> ic(Builtins::builtin(
2854 info_->is_strict() ? Builtins::KeyedStoreIC_Initialize_Strict
2855 : Builtins::KeyedStoreIC_Initialize));
2856 CallCode(ic, RelocInfo::CODE_TARGET, instr);
2857 }
2858
2859
2860 void LCodeGen::DoStringCharCodeAt(LStringCharCodeAt* instr) {
2861 class DeferredStringCharCodeAt: public LDeferredCode {
2862 public:
2863 DeferredStringCharCodeAt(LCodeGen* codegen, LStringCharCodeAt* instr)
2864 : LDeferredCode(codegen), instr_(instr) { }
2865 virtual void Generate() { codegen()->DoDeferredStringCharCodeAt(instr_); }
2866 private:
2867 LStringCharCodeAt* instr_;
2868 };
2869
2870 Register string = ToRegister(instr->string());
2871 Register index = no_reg;
2872 int const_index = -1;
2873 if (instr->index()->IsConstantOperand()) {
2874 const_index = ToInteger32(LConstantOperand::cast(instr->index()));
2875 STATIC_ASSERT(String::kMaxLength <= Smi::kMaxValue);
2876 if (!Smi::IsValid(const_index)) {
2877 // Guaranteed to be out of bounds because of the assert above.
2878 // So the bounds check that must dominate this instruction must
2879 // have deoptimized already.
2880 if (FLAG_debug_code) {
2881 __ Abort("StringCharCodeAt: out of bounds index.");
2882 }
2883 // No code needs to be generated.
2884 return;
2885 }
2886 } else {
2887 index = ToRegister(instr->index());
2888 }
2889 Register result = ToRegister(instr->result());
2890
2891 DeferredStringCharCodeAt* deferred =
2892 new DeferredStringCharCodeAt(this, instr);
2893
2894 NearLabel flat_string, ascii_string, done;
2895
2896 // Fetch the instance type of the receiver into result register.
2897 __ movq(result, FieldOperand(string, HeapObject::kMapOffset));
2898 __ movzxbl(result, FieldOperand(result, Map::kInstanceTypeOffset));
2899
2900 // We need special handling for non-sequential strings.
2901 STATIC_ASSERT(kSeqStringTag == 0);
2902 __ testb(result, Immediate(kStringRepresentationMask));
2903 __ j(zero, &flat_string);
2904
2905 // Handle cons strings and go to deferred code for the rest.
2906 __ testb(result, Immediate(kIsConsStringMask));
2907 __ j(zero, deferred->entry());
2908
2909 // ConsString.
2910 // Check whether the right hand side is the empty string (i.e. if
2911 // this is really a flat string in a cons string). If that is not
2912 // the case we would rather go to the runtime system now to flatten
2913 // the string.
2914 __ CompareRoot(FieldOperand(string, ConsString::kSecondOffset),
2915 Heap::kEmptyStringRootIndex);
2916 __ j(not_equal, deferred->entry());
2917 // Get the first of the two strings and load its instance type.
2918 __ movq(string, FieldOperand(string, ConsString::kFirstOffset));
2919 __ movq(result, FieldOperand(string, HeapObject::kMapOffset));
2920 __ movzxbl(result, FieldOperand(result, Map::kInstanceTypeOffset));
2921 // If the first cons component is also non-flat, then go to runtime.
2922 STATIC_ASSERT(kSeqStringTag == 0);
2923 __ testb(result, Immediate(kStringRepresentationMask));
2924 __ j(not_zero, deferred->entry());
2925
2926 // Check for ASCII or two-byte string.
2927 __ bind(&flat_string);
2928 STATIC_ASSERT(kAsciiStringTag != 0);
2929 __ testb(result, Immediate(kStringEncodingMask));
2930 __ j(not_zero, &ascii_string);
2931
2932 // Two-byte string.
2933 // Load the two-byte character code into the result register.
2934 STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize == 1);
2935 if (instr->index()->IsConstantOperand()) {
2936 __ movzxwl(result,
2937 FieldOperand(string,
2938 SeqTwoByteString::kHeaderSize +
2939 (kUC16Size * const_index)));
2940 } else {
2941 __ movzxwl(result, FieldOperand(string,
2942 index,
2943 times_2,
2944 SeqTwoByteString::kHeaderSize));
2945 }
2946 __ jmp(&done);
2947
2948 // ASCII string.
2949 // Load the byte into the result register.
2950 __ bind(&ascii_string);
2951 if (instr->index()->IsConstantOperand()) {
2952 __ movzxbl(result, FieldOperand(string,
2953 SeqAsciiString::kHeaderSize + const_index));
2954 } else {
2955 __ movzxbl(result, FieldOperand(string,
2956 index,
2957 times_1,
2958 SeqAsciiString::kHeaderSize));
2959 }
2960 __ bind(&done);
2961 __ bind(deferred->exit());
2962 }
2963
2964
2965 void LCodeGen::DoDeferredStringCharCodeAt(LStringCharCodeAt* instr) {
2966 Register string = ToRegister(instr->string());
2967 Register result = ToRegister(instr->result());
2968
2969 // TODO(3095996): Get rid of this. For now, we need to make the
2970 // result register contain a valid pointer because it is already
2971 // contained in the register pointer map.
2972 __ Set(result, 0);
2973
2974 __ PushSafepointRegisters();
2975 __ push(string);
2976 // Push the index as a smi. This is safe because of the checks in
2977 // DoStringCharCodeAt above.
2978 STATIC_ASSERT(String::kMaxLength <= Smi::kMaxValue);
2979 if (instr->index()->IsConstantOperand()) {
2980 int const_index = ToInteger32(LConstantOperand::cast(instr->index()));
2981 __ Push(Smi::FromInt(const_index));
2982 } else {
2983 Register index = ToRegister(instr->index());
2984 __ Integer32ToSmi(index, index);
2985 __ push(index);
2986 }
2987 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
2988 __ CallRuntimeSaveDoubles(Runtime::kStringCharCodeAt);
2989 RecordSafepointWithRegisters(
2990 instr->pointer_map(), 2, Safepoint::kNoDeoptimizationIndex);
2991 if (FLAG_debug_code) {
2992 __ AbortIfNotSmi(rax);
2993 }
2994 __ SmiToInteger32(rax, rax);
2995 __ StoreToSafepointRegisterSlot(result, rax);
2996 __ PopSafepointRegisters();
2997 }
2998
2999
3000 void LCodeGen::DoStringCharFromCode(LStringCharFromCode* instr) {
3001 class DeferredStringCharFromCode: public LDeferredCode {
3002 public:
3003 DeferredStringCharFromCode(LCodeGen* codegen, LStringCharFromCode* instr)
3004 : LDeferredCode(codegen), instr_(instr) { }
3005 virtual void Generate() { codegen()->DoDeferredStringCharFromCode(instr_); }
3006 private:
3007 LStringCharFromCode* instr_;
3008 };
3009
3010 DeferredStringCharFromCode* deferred =
3011 new DeferredStringCharFromCode(this, instr);
3012
3013 ASSERT(instr->hydrogen()->value()->representation().IsInteger32());
3014 Register char_code = ToRegister(instr->char_code());
3015 Register result = ToRegister(instr->result());
3016 ASSERT(!char_code.is(result));
3017
3018 __ cmpl(char_code, Immediate(String::kMaxAsciiCharCode));
3019 __ j(above, deferred->entry());
3020 __ LoadRoot(result, Heap::kSingleCharacterStringCacheRootIndex);
3021 __ movq(result, FieldOperand(result,
3022 char_code, times_pointer_size,
3023 FixedArray::kHeaderSize));
3024 __ CompareRoot(result, Heap::kUndefinedValueRootIndex);
3025 __ j(equal, deferred->entry());
3026 __ bind(deferred->exit());
3027 }
3028
3029
3030 void LCodeGen::DoDeferredStringCharFromCode(LStringCharFromCode* instr) {
3031 Register char_code = ToRegister(instr->char_code());
3032 Register result = ToRegister(instr->result());
3033
3034 // TODO(3095996): Get rid of this. For now, we need to make the
3035 // result register contain a valid pointer because it is already
3036 // contained in the register pointer map.
3037 __ Set(result, 0);
3038
3039 __ PushSafepointRegisters();
3040 __ Integer32ToSmi(char_code, char_code);
3041 __ push(char_code);
3042 __ CallRuntimeSaveDoubles(Runtime::kCharFromCode);
3043 RecordSafepointWithRegisters(
3044 instr->pointer_map(), 1, Safepoint::kNoDeoptimizationIndex);
3045 __ StoreToSafepointRegisterSlot(result, rax);
3046 __ PopSafepointRegisters();
2194 } 3047 }
2195 3048
2196 3049
2197 void LCodeGen::DoStringLength(LStringLength* instr) { 3050 void LCodeGen::DoStringLength(LStringLength* instr) {
2198 Register string = ToRegister(instr->string()); 3051 Register string = ToRegister(instr->string());
2199 Register result = ToRegister(instr->result()); 3052 Register result = ToRegister(instr->result());
2200 __ movq(result, FieldOperand(string, String::kLengthOffset)); 3053 __ movq(result, FieldOperand(string, String::kLengthOffset));
2201 } 3054 }
2202 3055
2203 3056
(...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after
2396 ASSERT(result->IsDoubleRegister()); 3249 ASSERT(result->IsDoubleRegister());
2397 3250
2398 Register input_reg = ToRegister(input); 3251 Register input_reg = ToRegister(input);
2399 XMMRegister result_reg = ToDoubleRegister(result); 3252 XMMRegister result_reg = ToDoubleRegister(result);
2400 3253
2401 EmitNumberUntagD(input_reg, result_reg, instr->environment()); 3254 EmitNumberUntagD(input_reg, result_reg, instr->environment());
2402 } 3255 }
2403 3256
2404 3257
2405 void LCodeGen::DoDoubleToI(LDoubleToI* instr) { 3258 void LCodeGen::DoDoubleToI(LDoubleToI* instr) {
2406 Abort("Unimplemented: %s", "DoDoubleToI"); 3259 LOperand* input = instr->InputAt(0);
3260 ASSERT(input->IsDoubleRegister());
3261 LOperand* result = instr->result();
3262 ASSERT(result->IsRegister());
3263
3264 XMMRegister input_reg = ToDoubleRegister(input);
3265 Register result_reg = ToRegister(result);
3266
3267 if (instr->truncating()) {
3268 // Performs a truncating conversion of a floating point number as used by
3269 // the JS bitwise operations.
3270 __ cvttsd2siq(result_reg, input_reg);
3271 __ movq(kScratchRegister, V8_INT64_C(0x8000000000000000), RelocInfo::NONE);
3272 __ cmpl(result_reg, kScratchRegister);
3273 DeoptimizeIf(equal, instr->environment());
3274 } else {
3275 __ cvttsd2si(result_reg, input_reg);
3276 __ cvtlsi2sd(xmm0, result_reg);
3277 __ ucomisd(xmm0, input_reg);
3278 DeoptimizeIf(not_equal, instr->environment());
3279 DeoptimizeIf(parity_even, instr->environment()); // NaN.
3280 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
3281 NearLabel done;
3282 // The integer converted back is equal to the original. We
3283 // only have to test if we got -0 as an input.
3284 __ testl(result_reg, result_reg);
3285 __ j(not_zero, &done);
3286 __ movmskpd(result_reg, input_reg);
3287 // Bit 0 contains the sign of the double in input_reg.
3288 // If input was positive, we are ok and return 0, otherwise
3289 // deoptimize.
3290 __ andl(result_reg, Immediate(1));
3291 DeoptimizeIf(not_zero, instr->environment());
3292 __ bind(&done);
3293 }
3294 }
2407 } 3295 }
2408 3296
2409 3297
2410 void LCodeGen::DoCheckSmi(LCheckSmi* instr) { 3298 void LCodeGen::DoCheckSmi(LCheckSmi* instr) {
2411 LOperand* input = instr->InputAt(0); 3299 LOperand* input = instr->InputAt(0);
2412 ASSERT(input->IsRegister()); 3300 ASSERT(input->IsRegister());
2413 Condition cc = masm()->CheckSmi(ToRegister(input)); 3301 Condition cc = masm()->CheckSmi(ToRegister(input));
2414 if (instr->condition() != equal) { 3302 if (instr->condition() != equal) {
2415 cc = NegateCondition(cc); 3303 cc = NegateCondition(cc);
2416 } 3304 }
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after
2545 // Pick the right runtime function to call. 3433 // Pick the right runtime function to call.
2546 if (instr->hydrogen()->depth() > 1) { 3434 if (instr->hydrogen()->depth() > 1) {
2547 CallRuntime(Runtime::kCreateObjectLiteral, 4, instr); 3435 CallRuntime(Runtime::kCreateObjectLiteral, 4, instr);
2548 } else { 3436 } else {
2549 CallRuntime(Runtime::kCreateObjectLiteralShallow, 4, instr); 3437 CallRuntime(Runtime::kCreateObjectLiteralShallow, 4, instr);
2550 } 3438 }
2551 } 3439 }
2552 3440
2553 3441
2554 void LCodeGen::DoRegExpLiteral(LRegExpLiteral* instr) { 3442 void LCodeGen::DoRegExpLiteral(LRegExpLiteral* instr) {
2555 Abort("Unimplemented: %s", "DoRegExpLiteral"); 3443 NearLabel materialized;
3444 // Registers will be used as follows:
3445 // rdi = JS function.
3446 // rcx = literals array.
3447 // rbx = regexp literal.
3448 // rax = regexp literal clone.
3449 __ movq(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
3450 __ movq(rcx, FieldOperand(rdi, JSFunction::kLiteralsOffset));
3451 int literal_offset = FixedArray::kHeaderSize +
3452 instr->hydrogen()->literal_index() * kPointerSize;
3453 __ movq(rbx, FieldOperand(rcx, literal_offset));
3454 __ CompareRoot(rbx, Heap::kUndefinedValueRootIndex);
3455 __ j(not_equal, &materialized);
3456
3457 // Create regexp literal using runtime function
3458 // Result will be in rax.
3459 __ push(rcx);
3460 __ Push(Smi::FromInt(instr->hydrogen()->literal_index()));
3461 __ Push(instr->hydrogen()->pattern());
3462 __ Push(instr->hydrogen()->flags());
3463 CallRuntime(Runtime::kMaterializeRegExpLiteral, 4, instr);
3464 __ movq(rbx, rax);
3465
3466 __ bind(&materialized);
3467 int size = JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kPointerSize;
3468 Label allocated, runtime_allocate;
3469 __ AllocateInNewSpace(size, rax, rcx, rdx, &runtime_allocate, TAG_OBJECT);
3470 __ jmp(&allocated);
3471
3472 __ bind(&runtime_allocate);
3473 __ push(rbx);
3474 __ Push(Smi::FromInt(size));
3475 CallRuntime(Runtime::kAllocateInNewSpace, 1, instr);
3476 __ pop(rbx);
3477
3478 __ bind(&allocated);
3479 // Copy the content into the newly allocated memory.
3480 // (Unroll copy loop once for better throughput).
3481 for (int i = 0; i < size - kPointerSize; i += 2 * kPointerSize) {
3482 __ movq(rdx, FieldOperand(rbx, i));
3483 __ movq(rcx, FieldOperand(rbx, i + kPointerSize));
3484 __ movq(FieldOperand(rax, i), rdx);
3485 __ movq(FieldOperand(rax, i + kPointerSize), rcx);
3486 }
3487 if ((size % (2 * kPointerSize)) != 0) {
3488 __ movq(rdx, FieldOperand(rbx, size - kPointerSize));
3489 __ movq(FieldOperand(rax, size - kPointerSize), rdx);
3490 }
2556 } 3491 }
2557 3492
2558 3493
2559 void LCodeGen::DoFunctionLiteral(LFunctionLiteral* instr) { 3494 void LCodeGen::DoFunctionLiteral(LFunctionLiteral* instr) {
2560 // Use the fast case closure allocation code that allocates in new 3495 // Use the fast case closure allocation code that allocates in new
2561 // space for nested functions that don't need literals cloning. 3496 // space for nested functions that don't need literals cloning.
2562 Handle<SharedFunctionInfo> shared_info = instr->shared_info(); 3497 Handle<SharedFunctionInfo> shared_info = instr->shared_info();
2563 bool pretenure = instr->hydrogen()->pretenure(); 3498 bool pretenure = instr->hydrogen()->pretenure();
2564 if (shared_info->num_literals() == 0 && !pretenure) { 3499 if (shared_info->num_literals() == 0 && !pretenure) {
2565 FastNewClosureStub stub; 3500 FastNewClosureStub stub;
2566 __ Push(shared_info); 3501 __ Push(shared_info);
2567 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); 3502 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
2568 } else { 3503 } else {
2569 __ push(rsi); 3504 __ push(rsi);
2570 __ Push(shared_info); 3505 __ Push(shared_info);
2571 __ Push(pretenure ? Factory::true_value() : Factory::false_value()); 3506 __ PushRoot(pretenure ?
3507 Heap::kTrueValueRootIndex :
3508 Heap::kFalseValueRootIndex);
2572 CallRuntime(Runtime::kNewClosure, 3, instr); 3509 CallRuntime(Runtime::kNewClosure, 3, instr);
2573 } 3510 }
2574 } 3511 }
2575 3512
2576 3513
2577 void LCodeGen::DoTypeof(LTypeof* instr) { 3514 void LCodeGen::DoTypeof(LTypeof* instr) {
2578 Abort("Unimplemented: %s", "DoTypeof"); 3515 LOperand* input = instr->InputAt(0);
3516 if (input->IsConstantOperand()) {
3517 __ Push(ToHandle(LConstantOperand::cast(input)));
3518 } else if (input->IsRegister()) {
3519 __ push(ToRegister(input));
3520 } else {
3521 ASSERT(input->IsStackSlot());
3522 __ push(ToOperand(input));
3523 }
3524 CallRuntime(Runtime::kTypeof, 1, instr);
2579 } 3525 }
2580 3526
2581 3527
2582 void LCodeGen::DoTypeofIs(LTypeofIs* instr) { 3528 void LCodeGen::DoTypeofIs(LTypeofIs* instr) {
2583 Abort("Unimplemented: %s", "DoTypeofIs"); 3529 Register input = ToRegister(instr->InputAt(0));
2584 }
2585
2586
2587 void LCodeGen::DoIsConstructCall(LIsConstructCall* instr) {
2588 Register result = ToRegister(instr->result()); 3530 Register result = ToRegister(instr->result());
2589 NearLabel true_label; 3531 Label true_label;
2590 NearLabel false_label; 3532 Label false_label;
2591 NearLabel done; 3533 NearLabel done;
2592 3534
2593 EmitIsConstructCall(result); 3535 Condition final_branch_condition = EmitTypeofIs(&true_label,
2594 __ j(equal, &true_label); 3536 &false_label,
2595 3537 input,
3538 instr->type_literal());
3539 __ j(final_branch_condition, &true_label);
3540 __ bind(&false_label);
2596 __ LoadRoot(result, Heap::kFalseValueRootIndex); 3541 __ LoadRoot(result, Heap::kFalseValueRootIndex);
2597 __ jmp(&done); 3542 __ jmp(&done);
2598 3543
2599 __ bind(&true_label); 3544 __ bind(&true_label);
2600 __ LoadRoot(result, Heap::kTrueValueRootIndex); 3545 __ LoadRoot(result, Heap::kTrueValueRootIndex);
2601 3546
2602
2603 __ bind(&done); 3547 __ bind(&done);
2604 } 3548 }
2605 3549
2606 3550
2607 void LCodeGen::DoIsConstructCallAndBranch(LIsConstructCallAndBranch* instr) { 3551 void LCodeGen::EmitPushConstantOperand(LOperand* operand) {
2608 Register temp = ToRegister(instr->TempAt(0)); 3552 ASSERT(operand->IsConstantOperand());
2609 int true_block = chunk_->LookupDestination(instr->true_block_id()); 3553 LConstantOperand* const_op = LConstantOperand::cast(operand);
2610 int false_block = chunk_->LookupDestination(instr->false_block_id()); 3554 Handle<Object> literal = chunk_->LookupLiteral(const_op);
2611 3555 Representation r = chunk_->LookupLiteralRepresentation(const_op);
2612 EmitIsConstructCall(temp); 3556 if (r.IsInteger32()) {
2613 EmitBranch(true_block, false_block, equal); 3557 ASSERT(literal->IsNumber());
2614 } 3558 __ push(Immediate(static_cast<int32_t>(literal->Number())));
2615 3559 } else if (r.IsDouble()) {
2616 3560 Abort("unsupported double immediate");
2617 void LCodeGen::EmitIsConstructCall(Register temp) { 3561 } else {
2618 // Get the frame pointer for the calling frame. 3562 ASSERT(r.IsTagged());
2619 __ movq(temp, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); 3563 __ Push(literal);
2620 3564 }
2621 // Skip the arguments adaptor frame if it exists.
2622 NearLabel check_frame_marker;
2623 __ SmiCompare(Operand(temp, StandardFrameConstants::kContextOffset),
2624 Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
2625 __ j(not_equal, &check_frame_marker);
2626 __ movq(temp, Operand(rax, StandardFrameConstants::kCallerFPOffset));
2627
2628 // Check the marker in the calling frame.
2629 __ bind(&check_frame_marker);
2630 __ SmiCompare(Operand(temp, StandardFrameConstants::kMarkerOffset),
2631 Smi::FromInt(StackFrame::CONSTRUCT));
2632 } 3565 }
2633 3566
2634 3567
2635 void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) { 3568 void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) {
2636 Register input = ToRegister(instr->InputAt(0)); 3569 Register input = ToRegister(instr->InputAt(0));
2637 int true_block = chunk_->LookupDestination(instr->true_block_id()); 3570 int true_block = chunk_->LookupDestination(instr->true_block_id());
2638 int false_block = chunk_->LookupDestination(instr->false_block_id()); 3571 int false_block = chunk_->LookupDestination(instr->false_block_id());
2639 Label* true_label = chunk_->GetAssemblyLabel(true_block); 3572 Label* true_label = chunk_->GetAssemblyLabel(true_block);
2640 Label* false_label = chunk_->GetAssemblyLabel(false_block); 3573 Label* false_label = chunk_->GetAssemblyLabel(false_block);
2641 3574
2642 Condition final_branch_condition = EmitTypeofIs(true_label, 3575 Condition final_branch_condition = EmitTypeofIs(true_label,
2643 false_label, 3576 false_label,
2644 input, 3577 input,
2645 instr->type_literal()); 3578 instr->type_literal());
2646 3579
2647 EmitBranch(true_block, false_block, final_branch_condition); 3580 EmitBranch(true_block, false_block, final_branch_condition);
2648 } 3581 }
2649 3582
2650 3583
2651 Condition LCodeGen::EmitTypeofIs(Label* true_label, 3584 Condition LCodeGen::EmitTypeofIs(Label* true_label,
2652 Label* false_label, 3585 Label* false_label,
2653 Register input, 3586 Register input,
2654 Handle<String> type_name) { 3587 Handle<String> type_name) {
2655 Condition final_branch_condition = no_condition; 3588 Condition final_branch_condition = no_condition;
2656 if (type_name->Equals(Heap::number_symbol())) { 3589 if (type_name->Equals(Heap::number_symbol())) {
2657 __ JumpIfSmi(input, true_label); 3590 __ JumpIfSmi(input, true_label);
2658 __ Cmp(FieldOperand(input, HeapObject::kMapOffset), 3591 __ CompareRoot(FieldOperand(input, HeapObject::kMapOffset),
2659 Factory::heap_number_map()); 3592 Heap::kHeapNumberMapRootIndex);
3593
2660 final_branch_condition = equal; 3594 final_branch_condition = equal;
2661 3595
2662 } else if (type_name->Equals(Heap::string_symbol())) { 3596 } else if (type_name->Equals(Heap::string_symbol())) {
2663 __ JumpIfSmi(input, false_label); 3597 __ JumpIfSmi(input, false_label);
2664 __ movq(input, FieldOperand(input, HeapObject::kMapOffset)); 3598 __ CmpObjectType(input, FIRST_NONSTRING_TYPE, input);
3599 __ j(above_equal, false_label);
2665 __ testb(FieldOperand(input, Map::kBitFieldOffset), 3600 __ testb(FieldOperand(input, Map::kBitFieldOffset),
2666 Immediate(1 << Map::kIsUndetectable)); 3601 Immediate(1 << Map::kIsUndetectable));
2667 __ j(not_zero, false_label); 3602 final_branch_condition = zero;
2668 __ CmpInstanceType(input, FIRST_NONSTRING_TYPE);
2669 final_branch_condition = below;
2670 3603
2671 } else if (type_name->Equals(Heap::boolean_symbol())) { 3604 } else if (type_name->Equals(Heap::boolean_symbol())) {
2672 __ CompareRoot(input, Heap::kTrueValueRootIndex); 3605 __ CompareRoot(input, Heap::kTrueValueRootIndex);
2673 __ j(equal, true_label); 3606 __ j(equal, true_label);
2674 __ CompareRoot(input, Heap::kFalseValueRootIndex); 3607 __ CompareRoot(input, Heap::kFalseValueRootIndex);
2675 final_branch_condition = equal; 3608 final_branch_condition = equal;
2676 3609
2677 } else if (type_name->Equals(Heap::undefined_symbol())) { 3610 } else if (type_name->Equals(Heap::undefined_symbol())) {
2678 __ CompareRoot(input, Heap::kUndefinedValueRootIndex); 3611 __ CompareRoot(input, Heap::kUndefinedValueRootIndex);
2679 __ j(equal, true_label); 3612 __ j(equal, true_label);
2680 __ JumpIfSmi(input, false_label); 3613 __ JumpIfSmi(input, false_label);
2681 // Check for undetectable objects => true. 3614 // Check for undetectable objects => true.
2682 __ movq(input, FieldOperand(input, HeapObject::kMapOffset)); 3615 __ movq(input, FieldOperand(input, HeapObject::kMapOffset));
2683 __ testb(FieldOperand(input, Map::kBitFieldOffset), 3616 __ testb(FieldOperand(input, Map::kBitFieldOffset),
2684 Immediate(1 << Map::kIsUndetectable)); 3617 Immediate(1 << Map::kIsUndetectable));
2685 final_branch_condition = not_zero; 3618 final_branch_condition = not_zero;
2686 3619
2687 } else if (type_name->Equals(Heap::function_symbol())) { 3620 } else if (type_name->Equals(Heap::function_symbol())) {
2688 __ JumpIfSmi(input, false_label); 3621 __ JumpIfSmi(input, false_label);
2689 __ CmpObjectType(input, FIRST_FUNCTION_CLASS_TYPE, input); 3622 __ CmpObjectType(input, FIRST_FUNCTION_CLASS_TYPE, input);
2690 final_branch_condition = above_equal; 3623 final_branch_condition = above_equal;
2691 3624
2692 } else if (type_name->Equals(Heap::object_symbol())) { 3625 } else if (type_name->Equals(Heap::object_symbol())) {
2693 __ JumpIfSmi(input, false_label); 3626 __ JumpIfSmi(input, false_label);
2694 __ Cmp(input, Factory::null_value()); 3627 __ CompareRoot(input, Heap::kNullValueRootIndex);
2695 __ j(equal, true_label); 3628 __ j(equal, true_label);
3629 __ CmpObjectType(input, FIRST_JS_OBJECT_TYPE, input);
3630 __ j(below, false_label);
3631 __ CmpInstanceType(input, FIRST_FUNCTION_CLASS_TYPE);
3632 __ j(above_equal, false_label);
2696 // Check for undetectable objects => false. 3633 // Check for undetectable objects => false.
2697 __ testb(FieldOperand(input, Map::kBitFieldOffset), 3634 __ testb(FieldOperand(input, Map::kBitFieldOffset),
2698 Immediate(1 << Map::kIsUndetectable)); 3635 Immediate(1 << Map::kIsUndetectable));
2699 __ j(not_zero, false_label); 3636 final_branch_condition = zero;
2700 // Check for JS objects that are not RegExp or Function => true.
2701 __ CmpInstanceType(input, FIRST_JS_OBJECT_TYPE);
2702 __ j(below, false_label);
2703 __ CmpInstanceType(input, FIRST_FUNCTION_CLASS_TYPE);
2704 final_branch_condition = below_equal;
2705 3637
2706 } else { 3638 } else {
2707 final_branch_condition = never; 3639 final_branch_condition = never;
2708 __ jmp(false_label); 3640 __ jmp(false_label);
2709 } 3641 }
2710 3642
2711 return final_branch_condition; 3643 return final_branch_condition;
2712 } 3644 }
2713 3645
2714 3646
3647 void LCodeGen::DoIsConstructCall(LIsConstructCall* instr) {
3648 Register result = ToRegister(instr->result());
3649 NearLabel true_label;
3650 NearLabel false_label;
3651 NearLabel done;
3652
3653 EmitIsConstructCall(result);
3654 __ j(equal, &true_label);
3655
3656 __ LoadRoot(result, Heap::kFalseValueRootIndex);
3657 __ jmp(&done);
3658
3659 __ bind(&true_label);
3660 __ LoadRoot(result, Heap::kTrueValueRootIndex);
3661
3662
3663 __ bind(&done);
3664 }
3665
3666
3667 void LCodeGen::DoIsConstructCallAndBranch(LIsConstructCallAndBranch* instr) {
3668 Register temp = ToRegister(instr->TempAt(0));
3669 int true_block = chunk_->LookupDestination(instr->true_block_id());
3670 int false_block = chunk_->LookupDestination(instr->false_block_id());
3671
3672 EmitIsConstructCall(temp);
3673 EmitBranch(true_block, false_block, equal);
3674 }
3675
3676
3677 void LCodeGen::EmitIsConstructCall(Register temp) {
3678 // Get the frame pointer for the calling frame.
3679 __ movq(temp, Operand(rbp, StandardFrameConstants::kCallerFPOffset));
3680
3681 // Skip the arguments adaptor frame if it exists.
3682 NearLabel check_frame_marker;
3683 __ Cmp(Operand(temp, StandardFrameConstants::kContextOffset),
3684 Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
3685 __ j(not_equal, &check_frame_marker);
3686 __ movq(temp, Operand(rax, StandardFrameConstants::kCallerFPOffset));
3687
3688 // Check the marker in the calling frame.
3689 __ bind(&check_frame_marker);
3690 __ Cmp(Operand(temp, StandardFrameConstants::kMarkerOffset),
3691 Smi::FromInt(StackFrame::CONSTRUCT));
3692 }
3693
3694
2715 void LCodeGen::DoLazyBailout(LLazyBailout* instr) { 3695 void LCodeGen::DoLazyBailout(LLazyBailout* instr) {
2716 // No code for lazy bailout instruction. Used to capture environment after a 3696 // No code for lazy bailout instruction. Used to capture environment after a
2717 // call for populating the safepoint data with deoptimization data. 3697 // call for populating the safepoint data with deoptimization data.
2718 } 3698 }
2719 3699
2720 3700
2721 void LCodeGen::DoDeoptimize(LDeoptimize* instr) { 3701 void LCodeGen::DoDeoptimize(LDeoptimize* instr) {
2722 DeoptimizeIf(no_condition, instr->environment()); 3702 DeoptimizeIf(no_condition, instr->environment());
2723 } 3703 }
2724 3704
2725 3705
2726 void LCodeGen::DoDeleteProperty(LDeleteProperty* instr) { 3706 void LCodeGen::DoDeleteProperty(LDeleteProperty* instr) {
2727 Abort("Unimplemented: %s", "DoDeleteProperty"); 3707 LOperand* obj = instr->object();
3708 LOperand* key = instr->key();
3709 // Push object.
3710 if (obj->IsRegister()) {
3711 __ push(ToRegister(obj));
3712 } else {
3713 __ push(ToOperand(obj));
3714 }
3715 // Push key.
3716 if (key->IsConstantOperand()) {
3717 EmitPushConstantOperand(key);
3718 } else if (key->IsRegister()) {
3719 __ push(ToRegister(key));
3720 } else {
3721 __ push(ToOperand(key));
3722 }
3723 ASSERT(instr->HasPointerMap() && instr->HasDeoptimizationEnvironment());
3724 LPointerMap* pointers = instr->pointer_map();
3725 LEnvironment* env = instr->deoptimization_environment();
3726 RecordPosition(pointers->position());
3727 RegisterEnvironmentForDeoptimization(env);
3728 // Create safepoint generator that will also ensure enough space in the
3729 // reloc info for patching in deoptimization (since this is invoking a
3730 // builtin)
3731 SafepointGenerator safepoint_generator(this,
3732 pointers,
3733 env->deoptimization_index(),
3734 true);
3735 __ Push(Smi::FromInt(strict_mode_flag()));
3736 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION, &safepoint_generator);
2728 } 3737 }
2729 3738
2730 3739
2731 void LCodeGen::DoStackCheck(LStackCheck* instr) { 3740 void LCodeGen::DoStackCheck(LStackCheck* instr) {
2732 // Perform stack overflow check. 3741 // Perform stack overflow check.
2733 NearLabel done; 3742 NearLabel done;
2734 __ CompareRoot(rsp, Heap::kStackLimitRootIndex); 3743 __ CompareRoot(rsp, Heap::kStackLimitRootIndex);
2735 __ j(above_equal, &done); 3744 __ j(above_equal, &done);
2736 3745
2737 StackCheckStub stub; 3746 StackCheckStub stub;
(...skipping 16 matching lines...) Expand all
2754 RegisterEnvironmentForDeoptimization(environment); 3763 RegisterEnvironmentForDeoptimization(environment);
2755 ASSERT(osr_pc_offset_ == -1); 3764 ASSERT(osr_pc_offset_ == -1);
2756 osr_pc_offset_ = masm()->pc_offset(); 3765 osr_pc_offset_ = masm()->pc_offset();
2757 } 3766 }
2758 3767
2759 #undef __ 3768 #undef __
2760 3769
2761 } } // namespace v8::internal 3770 } } // namespace v8::internal
2762 3771
2763 #endif // V8_TARGET_ARCH_X64 3772 #endif // V8_TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « src/x64/lithium-codegen-x64.h ('k') | src/x64/lithium-x64.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698