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

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

Issue 110573004: Merge bleeding_edge 17696:18016. (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/parser
Patch Set: Created 7 years 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
OLDNEW
1 // Copyright 2013 the V8 project authors. All rights reserved. 1 // Copyright 2013 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 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
104 #ifdef _MSC_VER 104 #ifdef _MSC_VER
105 void LCodeGen::MakeSureStackPagesMapped(int offset) { 105 void LCodeGen::MakeSureStackPagesMapped(int offset) {
106 const int kPageSize = 4 * KB; 106 const int kPageSize = 4 * KB;
107 for (offset -= kPageSize; offset > 0; offset -= kPageSize) { 107 for (offset -= kPageSize; offset > 0; offset -= kPageSize) {
108 __ movq(Operand(rsp, offset), rax); 108 __ movq(Operand(rsp, offset), rax);
109 } 109 }
110 } 110 }
111 #endif 111 #endif
112 112
113 113
114 void LCodeGen::SaveCallerDoubles() {
115 ASSERT(info()->saves_caller_doubles());
116 ASSERT(NeedsEagerFrame());
117 Comment(";;; Save clobbered callee double registers");
118 int count = 0;
119 BitVector* doubles = chunk()->allocated_double_registers();
120 BitVector::Iterator save_iterator(doubles);
121 while (!save_iterator.Done()) {
122 __ movsd(MemOperand(rsp, count * kDoubleSize),
123 XMMRegister::FromAllocationIndex(save_iterator.Current()));
124 save_iterator.Advance();
125 count++;
126 }
127 }
128
129
130 void LCodeGen::RestoreCallerDoubles() {
131 ASSERT(info()->saves_caller_doubles());
132 ASSERT(NeedsEagerFrame());
133 Comment(";;; Restore clobbered callee double registers");
134 BitVector* doubles = chunk()->allocated_double_registers();
135 BitVector::Iterator save_iterator(doubles);
136 int count = 0;
137 while (!save_iterator.Done()) {
138 __ movsd(XMMRegister::FromAllocationIndex(save_iterator.Current()),
139 MemOperand(rsp, count * kDoubleSize));
140 save_iterator.Advance();
141 count++;
142 }
143 }
144
145
114 bool LCodeGen::GeneratePrologue() { 146 bool LCodeGen::GeneratePrologue() {
115 ASSERT(is_generating()); 147 ASSERT(is_generating());
116 148
117 if (info()->IsOptimizing()) { 149 if (info()->IsOptimizing()) {
118 ProfileEntryHookStub::MaybeCallEntryHook(masm_); 150 ProfileEntryHookStub::MaybeCallEntryHook(masm_);
119 151
120 #ifdef DEBUG 152 #ifdef DEBUG
121 if (strlen(FLAG_stop_at) > 0 && 153 if (strlen(FLAG_stop_at) > 0 &&
122 info_->function()->name()->IsUtf8EqualTo(CStrVector(FLAG_stop_at))) { 154 info_->function()->name()->IsUtf8EqualTo(CStrVector(FLAG_stop_at))) {
123 __ int3(); 155 __ int3();
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
166 __ j(not_zero, &loop); 198 __ j(not_zero, &loop);
167 __ pop(rax); 199 __ pop(rax);
168 } else { 200 } else {
169 __ subq(rsp, Immediate(slots * kPointerSize)); 201 __ subq(rsp, Immediate(slots * kPointerSize));
170 #ifdef _MSC_VER 202 #ifdef _MSC_VER
171 MakeSureStackPagesMapped(slots * kPointerSize); 203 MakeSureStackPagesMapped(slots * kPointerSize);
172 #endif 204 #endif
173 } 205 }
174 206
175 if (info()->saves_caller_doubles()) { 207 if (info()->saves_caller_doubles()) {
176 Comment(";;; Save clobbered callee double registers"); 208 SaveCallerDoubles();
177 int count = 0;
178 BitVector* doubles = chunk()->allocated_double_registers();
179 BitVector::Iterator save_iterator(doubles);
180 while (!save_iterator.Done()) {
181 __ movsd(MemOperand(rsp, count * kDoubleSize),
182 XMMRegister::FromAllocationIndex(save_iterator.Current()));
183 save_iterator.Advance();
184 count++;
185 }
186 } 209 }
187 } 210 }
188 211
189 // Possibly allocate a local context. 212 // Possibly allocate a local context.
190 int heap_slots = info_->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; 213 int heap_slots = info_->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
191 if (heap_slots > 0) { 214 if (heap_slots > 0) {
192 Comment(";;; Allocate local context"); 215 Comment(";;; Allocate local context");
193 // Argument to NewContext is the function, which is still in rdi. 216 // Argument to NewContext is the function, which is still in rdi.
194 __ push(rdi); 217 __ push(rdi);
195 if (heap_slots <= FastNewContextStub::kMaximumSlots) { 218 if (heap_slots <= FastNewContextStub::kMaximumSlots) {
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
254 __ bind(&jump_table_[i].label); 277 __ bind(&jump_table_[i].label);
255 Address entry = jump_table_[i].address; 278 Address entry = jump_table_[i].address;
256 Deoptimizer::BailoutType type = jump_table_[i].bailout_type; 279 Deoptimizer::BailoutType type = jump_table_[i].bailout_type;
257 int id = Deoptimizer::GetDeoptimizationId(isolate(), entry, type); 280 int id = Deoptimizer::GetDeoptimizationId(isolate(), entry, type);
258 if (id == Deoptimizer::kNotDeoptimizationEntry) { 281 if (id == Deoptimizer::kNotDeoptimizationEntry) {
259 Comment(";;; jump table entry %d.", i); 282 Comment(";;; jump table entry %d.", i);
260 } else { 283 } else {
261 Comment(";;; jump table entry %d: deoptimization bailout %d.", i, id); 284 Comment(";;; jump table entry %d: deoptimization bailout %d.", i, id);
262 } 285 }
263 if (jump_table_[i].needs_frame) { 286 if (jump_table_[i].needs_frame) {
287 ASSERT(!info()->saves_caller_doubles());
264 __ Move(kScratchRegister, ExternalReference::ForDeoptEntry(entry)); 288 __ Move(kScratchRegister, ExternalReference::ForDeoptEntry(entry));
265 if (needs_frame.is_bound()) { 289 if (needs_frame.is_bound()) {
266 __ jmp(&needs_frame); 290 __ jmp(&needs_frame);
267 } else { 291 } else {
268 __ bind(&needs_frame); 292 __ bind(&needs_frame);
269 __ movq(rsi, MemOperand(rbp, StandardFrameConstants::kContextOffset)); 293 __ movq(rsi, MemOperand(rbp, StandardFrameConstants::kContextOffset));
270 __ push(rbp); 294 __ push(rbp);
271 __ movq(rbp, rsp); 295 __ movq(rbp, rsp);
272 __ push(rsi); 296 __ push(rsi);
273 // This variant of deopt can only be used with stubs. Since we don't 297 // This variant of deopt can only be used with stubs. Since we don't
274 // have a function pointer to install in the stack frame that we're 298 // have a function pointer to install in the stack frame that we're
275 // building, install a special marker there instead. 299 // building, install a special marker there instead.
276 ASSERT(info()->IsStub()); 300 ASSERT(info()->IsStub());
277 __ Move(rsi, Smi::FromInt(StackFrame::STUB)); 301 __ Move(rsi, Smi::FromInt(StackFrame::STUB));
278 __ push(rsi); 302 __ push(rsi);
279 __ movq(rsi, MemOperand(rsp, kPointerSize)); 303 __ movq(rsi, MemOperand(rsp, kPointerSize));
280 __ call(kScratchRegister); 304 __ call(kScratchRegister);
281 } 305 }
282 } else { 306 } else {
307 if (info()->saves_caller_doubles()) {
308 ASSERT(info()->IsStub());
309 RestoreCallerDoubles();
310 }
283 __ call(entry, RelocInfo::RUNTIME_ENTRY); 311 __ call(entry, RelocInfo::RUNTIME_ENTRY);
284 } 312 }
285 } 313 }
286 return !is_aborted(); 314 return !is_aborted();
287 } 315 }
288 316
289 317
290 bool LCodeGen::GenerateDeferredCode() { 318 bool LCodeGen::GenerateDeferredCode() {
291 ASSERT(is_generating()); 319 ASSERT(is_generating());
292 if (deferred_.length() > 0) { 320 if (deferred_.length() > 0) {
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after
408 } 436 }
409 437
410 438
411 Handle<Object> LCodeGen::ToHandle(LConstantOperand* op) const { 439 Handle<Object> LCodeGen::ToHandle(LConstantOperand* op) const {
412 HConstant* constant = chunk_->LookupConstant(op); 440 HConstant* constant = chunk_->LookupConstant(op);
413 ASSERT(chunk_->LookupLiteralRepresentation(op).IsSmiOrTagged()); 441 ASSERT(chunk_->LookupLiteralRepresentation(op).IsSmiOrTagged());
414 return constant->handle(isolate()); 442 return constant->handle(isolate());
415 } 443 }
416 444
417 445
446 static int ArgumentsOffsetWithoutFrame(int index) {
447 ASSERT(index < 0);
448 return -(index + 1) * kPointerSize + kPCOnStackSize;
449 }
450
451
418 Operand LCodeGen::ToOperand(LOperand* op) const { 452 Operand LCodeGen::ToOperand(LOperand* op) const {
419 // Does not handle registers. In X64 assembler, plain registers are not 453 // Does not handle registers. In X64 assembler, plain registers are not
420 // representable as an Operand. 454 // representable as an Operand.
421 ASSERT(op->IsStackSlot() || op->IsDoubleStackSlot()); 455 ASSERT(op->IsStackSlot() || op->IsDoubleStackSlot());
422 return Operand(rbp, StackSlotOffset(op->index())); 456 if (NeedsEagerFrame()) {
457 return Operand(rbp, StackSlotOffset(op->index()));
458 } else {
459 // Retrieve parameter without eager stack-frame relative to the
460 // stack-pointer.
461 return Operand(rsp, ArgumentsOffsetWithoutFrame(op->index()));
462 }
423 } 463 }
424 464
425 465
426 void LCodeGen::WriteTranslation(LEnvironment* environment, 466 void LCodeGen::WriteTranslation(LEnvironment* environment,
427 Translation* translation) { 467 Translation* translation) {
428 if (environment == NULL) return; 468 if (environment == NULL) return;
429 469
430 // The translation includes one command per value in the environment. 470 // The translation includes one command per value in the environment.
431 int translation_size = environment->translation_size(); 471 int translation_size = environment->translation_size();
432 // The output frame height does not include the parameters. 472 // The output frame height does not include the parameters.
(...skipping 262 matching lines...) Expand 10 before | Expand all | Expand 10 after
695 if (info()->ShouldTrapOnDeopt()) { 735 if (info()->ShouldTrapOnDeopt()) {
696 Label done; 736 Label done;
697 if (cc != no_condition) { 737 if (cc != no_condition) {
698 __ j(NegateCondition(cc), &done, Label::kNear); 738 __ j(NegateCondition(cc), &done, Label::kNear);
699 } 739 }
700 __ int3(); 740 __ int3();
701 __ bind(&done); 741 __ bind(&done);
702 } 742 }
703 743
704 ASSERT(info()->IsStub() || frame_is_built_); 744 ASSERT(info()->IsStub() || frame_is_built_);
705 if (cc == no_condition && frame_is_built_) { 745 // Go through jump table if we need to handle condition, build frame, or
746 // restore caller doubles.
747 if (cc == no_condition && frame_is_built_ &&
748 !info()->saves_caller_doubles()) {
706 __ call(entry, RelocInfo::RUNTIME_ENTRY); 749 __ call(entry, RelocInfo::RUNTIME_ENTRY);
707 } else { 750 } else {
708 // We often have several deopts to the same entry, reuse the last 751 // We often have several deopts to the same entry, reuse the last
709 // jump entry if this is the case. 752 // jump entry if this is the case.
710 if (jump_table_.is_empty() || 753 if (jump_table_.is_empty() ||
711 jump_table_.last().address != entry || 754 jump_table_.last().address != entry ||
712 jump_table_.last().needs_frame != !frame_is_built_ || 755 jump_table_.last().needs_frame != !frame_is_built_ ||
713 jump_table_.last().bailout_type != bailout_type) { 756 jump_table_.last().bailout_type != bailout_type) {
714 Deoptimizer::JumpTableEntry table_entry(entry, 757 Deoptimizer::JumpTableEntry table_entry(entry,
715 bailout_type, 758 bailout_type,
(...skipping 278 matching lines...) Expand 10 before | Expand all | Expand 10 after
994 __ negl(left_reg); 1037 __ negl(left_reg);
995 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { 1038 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
996 DeoptimizeIf(zero, instr->environment()); 1039 DeoptimizeIf(zero, instr->environment());
997 } 1040 }
998 __ jmp(&done, Label::kNear); 1041 __ jmp(&done, Label::kNear);
999 } 1042 }
1000 1043
1001 __ bind(&left_is_not_negative); 1044 __ bind(&left_is_not_negative);
1002 __ andl(left_reg, Immediate(divisor - 1)); 1045 __ andl(left_reg, Immediate(divisor - 1));
1003 __ bind(&done); 1046 __ bind(&done);
1004
1005 } else if (hmod->fixed_right_arg().has_value) {
1006 Register left_reg = ToRegister(instr->left());
1007 ASSERT(left_reg.is(ToRegister(instr->result())));
1008 Register right_reg = ToRegister(instr->right());
1009
1010 int32_t divisor = hmod->fixed_right_arg().value;
1011 ASSERT(IsPowerOf2(divisor));
1012
1013 // Check if our assumption of a fixed right operand still holds.
1014 __ cmpl(right_reg, Immediate(divisor));
1015 DeoptimizeIf(not_equal, instr->environment());
1016
1017 Label left_is_not_negative, done;
1018 if (left->CanBeNegative()) {
1019 __ testl(left_reg, left_reg);
1020 __ j(not_sign, &left_is_not_negative, Label::kNear);
1021 __ negl(left_reg);
1022 __ andl(left_reg, Immediate(divisor - 1));
1023 __ negl(left_reg);
1024 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
1025 DeoptimizeIf(zero, instr->environment());
1026 }
1027 __ jmp(&done, Label::kNear);
1028 }
1029
1030 __ bind(&left_is_not_negative);
1031 __ andl(left_reg, Immediate(divisor - 1));
1032 __ bind(&done);
1033
1034 } else { 1047 } else {
1035 Register left_reg = ToRegister(instr->left()); 1048 Register left_reg = ToRegister(instr->left());
1036 ASSERT(left_reg.is(rax)); 1049 ASSERT(left_reg.is(rax));
1037 Register right_reg = ToRegister(instr->right()); 1050 Register right_reg = ToRegister(instr->right());
1038 ASSERT(!right_reg.is(rax)); 1051 ASSERT(!right_reg.is(rax));
1039 ASSERT(!right_reg.is(rdx)); 1052 ASSERT(!right_reg.is(rdx));
1040 Register result_reg = ToRegister(instr->result()); 1053 Register result_reg = ToRegister(instr->result());
1041 ASSERT(result_reg.is(rdx)); 1054 ASSERT(result_reg.is(rdx));
1042 1055
1043 Label done; 1056 Label done;
(...skipping 669 matching lines...) Expand 10 before | Expand all | Expand 10 after
1713 __ movzxwl(result, operand); 1726 __ movzxwl(result, operand);
1714 } 1727 }
1715 } 1728 }
1716 1729
1717 1730
1718 void LCodeGen::DoSeqStringSetChar(LSeqStringSetChar* instr) { 1731 void LCodeGen::DoSeqStringSetChar(LSeqStringSetChar* instr) {
1719 String::Encoding encoding = instr->hydrogen()->encoding(); 1732 String::Encoding encoding = instr->hydrogen()->encoding();
1720 Register string = ToRegister(instr->string()); 1733 Register string = ToRegister(instr->string());
1721 1734
1722 if (FLAG_debug_code) { 1735 if (FLAG_debug_code) {
1723 __ push(string); 1736 Register value = ToRegister(instr->value());
1724 __ movq(string, FieldOperand(string, HeapObject::kMapOffset)); 1737 Register index = ToRegister(instr->index());
1725 __ movzxbq(string, FieldOperand(string, Map::kInstanceTypeOffset));
1726
1727 __ andb(string, Immediate(kStringRepresentationMask | kStringEncodingMask));
1728 static const uint32_t one_byte_seq_type = kSeqStringTag | kOneByteStringTag; 1738 static const uint32_t one_byte_seq_type = kSeqStringTag | kOneByteStringTag;
1729 static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag; 1739 static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag;
1730 __ cmpq(string, Immediate(encoding == String::ONE_BYTE_ENCODING 1740 int encoding_mask =
1731 ? one_byte_seq_type : two_byte_seq_type)); 1741 instr->hydrogen()->encoding() == String::ONE_BYTE_ENCODING
1732 __ Check(equal, kUnexpectedStringType); 1742 ? one_byte_seq_type : two_byte_seq_type;
1733 __ pop(string); 1743 __ EmitSeqStringSetCharCheck(string, index, value, encoding_mask);
1734 } 1744 }
1735 1745
1736 Operand operand = BuildSeqStringOperand(string, instr->index(), encoding); 1746 Operand operand = BuildSeqStringOperand(string, instr->index(), encoding);
1737 if (instr->value()->IsConstantOperand()) { 1747 if (instr->value()->IsConstantOperand()) {
1738 int value = ToInteger32(LConstantOperand::cast(instr->value())); 1748 int value = ToInteger32(LConstantOperand::cast(instr->value()));
1739 ASSERT_LE(0, value); 1749 ASSERT_LE(0, value);
1740 if (encoding == String::ONE_BYTE_ENCODING) { 1750 if (encoding == String::ONE_BYTE_ENCODING) {
1741 ASSERT_LE(value, String::kMaxOneByteCharCode); 1751 ASSERT_LE(value, String::kMaxOneByteCharCode);
1742 __ movb(operand, Immediate(value)); 1752 __ movb(operand, Immediate(value));
1743 } else { 1753 } else {
(...skipping 927 matching lines...) Expand 10 before | Expand all | Expand 10 after
2671 if (FLAG_trace && info()->IsOptimizing()) { 2681 if (FLAG_trace && info()->IsOptimizing()) {
2672 // Preserve the return value on the stack and rely on the runtime call 2682 // Preserve the return value on the stack and rely on the runtime call
2673 // to return the value in the same register. We're leaving the code 2683 // to return the value in the same register. We're leaving the code
2674 // managed by the register allocator and tearing down the frame, it's 2684 // managed by the register allocator and tearing down the frame, it's
2675 // safe to write to the context register. 2685 // safe to write to the context register.
2676 __ push(rax); 2686 __ push(rax);
2677 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 2687 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
2678 __ CallRuntime(Runtime::kTraceExit, 1); 2688 __ CallRuntime(Runtime::kTraceExit, 1);
2679 } 2689 }
2680 if (info()->saves_caller_doubles()) { 2690 if (info()->saves_caller_doubles()) {
2681 ASSERT(NeedsEagerFrame()); 2691 RestoreCallerDoubles();
2682 BitVector* doubles = chunk()->allocated_double_registers();
2683 BitVector::Iterator save_iterator(doubles);
2684 int count = 0;
2685 while (!save_iterator.Done()) {
2686 __ movsd(XMMRegister::FromAllocationIndex(save_iterator.Current()),
2687 MemOperand(rsp, count * kDoubleSize));
2688 save_iterator.Advance();
2689 count++;
2690 }
2691 } 2692 }
2692 int no_frame_start = -1; 2693 int no_frame_start = -1;
2693 if (NeedsEagerFrame()) { 2694 if (NeedsEagerFrame()) {
2694 __ movq(rsp, rbp); 2695 __ movq(rsp, rbp);
2695 __ pop(rbp); 2696 __ pop(rbp);
2696 no_frame_start = masm_->pc_offset(); 2697 no_frame_start = masm_->pc_offset();
2697 } 2698 }
2698 if (instr->has_constant_parameter_count()) { 2699 if (instr->has_constant_parameter_count()) {
2699 __ Ret((ToInteger32(instr->constant_parameter_count()) + 1) * kPointerSize, 2700 __ Ret((ToInteger32(instr->constant_parameter_count()) + 1) * kPointerSize,
2700 rcx); 2701 rcx);
(...skipping 1011 matching lines...) Expand 10 before | Expand all | Expand 10 after
3712 MathPowStub stub(MathPowStub::INTEGER); 3713 MathPowStub stub(MathPowStub::INTEGER);
3713 __ CallStub(&stub); 3714 __ CallStub(&stub);
3714 } else { 3715 } else {
3715 ASSERT(exponent_type.IsDouble()); 3716 ASSERT(exponent_type.IsDouble());
3716 MathPowStub stub(MathPowStub::DOUBLE); 3717 MathPowStub stub(MathPowStub::DOUBLE);
3717 __ CallStub(&stub); 3718 __ CallStub(&stub);
3718 } 3719 }
3719 } 3720 }
3720 3721
3721 3722
3722 void LCodeGen::DoRandom(LRandom* instr) {
3723 // Assert that register size is twice the size of each seed.
3724 static const int kSeedSize = sizeof(uint32_t);
3725 STATIC_ASSERT(kPointerSize == 2 * kSeedSize);
3726
3727 // Load native context
3728 Register global_object = ToRegister(instr->global_object());
3729 Register native_context = global_object;
3730 __ movq(native_context, FieldOperand(
3731 global_object, GlobalObject::kNativeContextOffset));
3732
3733 // Load state (FixedArray of the native context's random seeds)
3734 static const int kRandomSeedOffset =
3735 FixedArray::kHeaderSize + Context::RANDOM_SEED_INDEX * kPointerSize;
3736 Register state = native_context;
3737 __ movq(state, FieldOperand(native_context, kRandomSeedOffset));
3738
3739 // Load state[0].
3740 Register state0 = ToRegister(instr->scratch());
3741 __ movl(state0, FieldOperand(state, ByteArray::kHeaderSize));
3742 // Load state[1].
3743 Register state1 = ToRegister(instr->scratch2());
3744 __ movl(state1, FieldOperand(state, ByteArray::kHeaderSize + kSeedSize));
3745
3746 // state[0] = 18273 * (state[0] & 0xFFFF) + (state[0] >> 16)
3747 Register scratch3 = ToRegister(instr->scratch3());
3748 __ movzxwl(scratch3, state0);
3749 __ imull(scratch3, scratch3, Immediate(18273));
3750 __ shrl(state0, Immediate(16));
3751 __ addl(state0, scratch3);
3752 // Save state[0].
3753 __ movl(FieldOperand(state, ByteArray::kHeaderSize), state0);
3754
3755 // state[1] = 36969 * (state[1] & 0xFFFF) + (state[1] >> 16)
3756 __ movzxwl(scratch3, state1);
3757 __ imull(scratch3, scratch3, Immediate(36969));
3758 __ shrl(state1, Immediate(16));
3759 __ addl(state1, scratch3);
3760 // Save state[1].
3761 __ movl(FieldOperand(state, ByteArray::kHeaderSize + kSeedSize), state1);
3762
3763 // Random bit pattern = (state[0] << 14) + (state[1] & 0x3FFFF)
3764 Register random = state0;
3765 __ shll(random, Immediate(14));
3766 __ andl(state1, Immediate(0x3FFFF));
3767 __ addl(random, state1);
3768
3769 // Convert 32 random bits in rax to 0.(32 random bits) in a double
3770 // by computing:
3771 // ( 1.(20 0s)(32 random bits) x 2^20 ) - (1.0 x 2^20)).
3772 XMMRegister result = ToDoubleRegister(instr->result());
3773 XMMRegister scratch4 = double_scratch0();
3774 __ movq(scratch3, V8_INT64_C(0x4130000000000000)); // 1.0 x 2^20 as double
3775 __ movq(scratch4, scratch3);
3776 __ movd(result, random);
3777 __ xorps(result, scratch4);
3778 __ subsd(result, scratch4);
3779 }
3780
3781
3782 void LCodeGen::DoMathExp(LMathExp* instr) { 3723 void LCodeGen::DoMathExp(LMathExp* instr) {
3783 XMMRegister input = ToDoubleRegister(instr->value()); 3724 XMMRegister input = ToDoubleRegister(instr->value());
3784 XMMRegister result = ToDoubleRegister(instr->result()); 3725 XMMRegister result = ToDoubleRegister(instr->result());
3785 XMMRegister temp0 = double_scratch0(); 3726 XMMRegister temp0 = double_scratch0();
3786 Register temp1 = ToRegister(instr->temp1()); 3727 Register temp1 = ToRegister(instr->temp1());
3787 Register temp2 = ToRegister(instr->temp2()); 3728 Register temp2 = ToRegister(instr->temp2());
3788 3729
3789 MathExpGenerator::EmitMathExp(masm(), input, result, temp0, temp1, temp2); 3730 MathExpGenerator::EmitMathExp(masm(), input, result, temp0, temp1, temp2);
3790 } 3731 }
3791 3732
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
3903 } 3844 }
3904 3845
3905 3846
3906 void LCodeGen::DoCallFunction(LCallFunction* instr) { 3847 void LCodeGen::DoCallFunction(LCallFunction* instr) {
3907 ASSERT(ToRegister(instr->context()).is(rsi)); 3848 ASSERT(ToRegister(instr->context()).is(rsi));
3908 ASSERT(ToRegister(instr->function()).is(rdi)); 3849 ASSERT(ToRegister(instr->function()).is(rdi));
3909 ASSERT(ToRegister(instr->result()).is(rax)); 3850 ASSERT(ToRegister(instr->result()).is(rax));
3910 3851
3911 int arity = instr->arity(); 3852 int arity = instr->arity();
3912 CallFunctionStub stub(arity, NO_CALL_FUNCTION_FLAGS); 3853 CallFunctionStub stub(arity, NO_CALL_FUNCTION_FLAGS);
3913 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); 3854 if (instr->hydrogen()->IsTailCall()) {
3855 if (NeedsEagerFrame()) __ leave();
3856 __ jmp(stub.GetCode(isolate()), RelocInfo::CODE_TARGET);
3857 } else {
3858 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr);
3859 }
3914 } 3860 }
3915 3861
3916 3862
3917 void LCodeGen::DoCallGlobal(LCallGlobal* instr) { 3863 void LCodeGen::DoCallGlobal(LCallGlobal* instr) {
3918 ASSERT(ToRegister(instr->context()).is(rsi)); 3864 ASSERT(ToRegister(instr->context()).is(rsi));
3919 ASSERT(ToRegister(instr->result()).is(rax)); 3865 ASSERT(ToRegister(instr->result()).is(rax));
3920 int arity = instr->arity(); 3866 int arity = instr->arity();
3921 RelocInfo::Mode mode = RelocInfo::CODE_TARGET_CONTEXT; 3867 RelocInfo::Mode mode = RelocInfo::CODE_TARGET_CONTEXT;
3922 Handle<Code> ic = 3868 Handle<Code> ic =
3923 isolate()->stub_cache()->ComputeCallInitialize(arity, mode); 3869 isolate()->stub_cache()->ComputeCallInitialize(arity, mode);
(...skipping 1300 matching lines...) Expand 10 before | Expand all | Expand 10 after
5224 if (instr->size()->IsRegister()) { 5170 if (instr->size()->IsRegister()) {
5225 Register size = ToRegister(instr->size()); 5171 Register size = ToRegister(instr->size());
5226 ASSERT(!size.is(result)); 5172 ASSERT(!size.is(result));
5227 __ Integer32ToSmi(size, size); 5173 __ Integer32ToSmi(size, size);
5228 __ push(size); 5174 __ push(size);
5229 } else { 5175 } else {
5230 int32_t size = ToInteger32(LConstantOperand::cast(instr->size())); 5176 int32_t size = ToInteger32(LConstantOperand::cast(instr->size()));
5231 __ Push(Smi::FromInt(size)); 5177 __ Push(Smi::FromInt(size));
5232 } 5178 }
5233 5179
5180 int flags = 0;
5234 if (instr->hydrogen()->IsOldPointerSpaceAllocation()) { 5181 if (instr->hydrogen()->IsOldPointerSpaceAllocation()) {
5235 ASSERT(!instr->hydrogen()->IsOldDataSpaceAllocation()); 5182 ASSERT(!instr->hydrogen()->IsOldDataSpaceAllocation());
5236 ASSERT(!instr->hydrogen()->IsNewSpaceAllocation()); 5183 ASSERT(!instr->hydrogen()->IsNewSpaceAllocation());
5237 CallRuntimeFromDeferred( 5184 flags = AllocateTargetSpace::update(flags, OLD_POINTER_SPACE);
5238 Runtime::kAllocateInOldPointerSpace, 1, instr, instr->context());
5239 } else if (instr->hydrogen()->IsOldDataSpaceAllocation()) { 5185 } else if (instr->hydrogen()->IsOldDataSpaceAllocation()) {
5240 ASSERT(!instr->hydrogen()->IsNewSpaceAllocation()); 5186 ASSERT(!instr->hydrogen()->IsNewSpaceAllocation());
5241 CallRuntimeFromDeferred( 5187 flags = AllocateTargetSpace::update(flags, OLD_DATA_SPACE);
5242 Runtime::kAllocateInOldDataSpace, 1, instr, instr->context());
5243 } else { 5188 } else {
5244 CallRuntimeFromDeferred( 5189 flags = AllocateTargetSpace::update(flags, NEW_SPACE);
5245 Runtime::kAllocateInNewSpace, 1, instr, instr->context());
5246 } 5190 }
5191 __ Push(Smi::FromInt(flags));
5192
5193 CallRuntimeFromDeferred(
5194 Runtime::kAllocateInTargetSpace, 2, instr, instr->context());
5247 __ StoreToSafepointRegisterSlot(result, rax); 5195 __ StoreToSafepointRegisterSlot(result, rax);
5248 } 5196 }
5249 5197
5250 5198
5251 void LCodeGen::DoToFastProperties(LToFastProperties* instr) { 5199 void LCodeGen::DoToFastProperties(LToFastProperties* instr) {
5252 ASSERT(ToRegister(instr->value()).is(rax)); 5200 ASSERT(ToRegister(instr->value()).is(rax));
5253 __ push(rax); 5201 __ push(rax);
5254 CallRuntime(Runtime::kToFastProperties, 1, instr); 5202 CallRuntime(Runtime::kToFastProperties, 1, instr);
5255 } 5203 }
5256 5204
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
5341 } else if (operand->IsRegister()) { 5289 } else if (operand->IsRegister()) {
5342 __ push(ToRegister(operand)); 5290 __ push(ToRegister(operand));
5343 } else { 5291 } else {
5344 __ push(ToOperand(operand)); 5292 __ push(ToOperand(operand));
5345 } 5293 }
5346 } 5294 }
5347 5295
5348 5296
5349 void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) { 5297 void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) {
5350 Register input = ToRegister(instr->value()); 5298 Register input = ToRegister(instr->value());
5351 5299 Condition final_branch_condition = EmitTypeofIs(instr, input);
5352 Condition final_branch_condition =
5353 EmitTypeofIs(instr->TrueLabel(chunk_),
5354 instr->FalseLabel(chunk_), input, instr->type_literal());
5355 if (final_branch_condition != no_condition) { 5300 if (final_branch_condition != no_condition) {
5356 EmitBranch(instr, final_branch_condition); 5301 EmitBranch(instr, final_branch_condition);
5357 } 5302 }
5358 } 5303 }
5359 5304
5360 5305
5361 Condition LCodeGen::EmitTypeofIs(Label* true_label, 5306 Condition LCodeGen::EmitTypeofIs(LTypeofIsAndBranch* instr, Register input) {
5362 Label* false_label, 5307 Label* true_label = instr->TrueLabel(chunk_);
5363 Register input, 5308 Label* false_label = instr->FalseLabel(chunk_);
5364 Handle<String> type_name) { 5309 Handle<String> type_name = instr->type_literal();
5310 int left_block = instr->TrueDestination(chunk_);
5311 int right_block = instr->FalseDestination(chunk_);
5312 int next_block = GetNextEmittedBlock();
5313
5314 Label::Distance true_distance = left_block == next_block ? Label::kNear
5315 : Label::kFar;
5316 Label::Distance false_distance = right_block == next_block ? Label::kNear
5317 : Label::kFar;
5365 Condition final_branch_condition = no_condition; 5318 Condition final_branch_condition = no_condition;
5366 if (type_name->Equals(heap()->number_string())) { 5319 if (type_name->Equals(heap()->number_string())) {
5367 __ JumpIfSmi(input, true_label); 5320 __ JumpIfSmi(input, true_label, true_distance);
5368 __ CompareRoot(FieldOperand(input, HeapObject::kMapOffset), 5321 __ CompareRoot(FieldOperand(input, HeapObject::kMapOffset),
5369 Heap::kHeapNumberMapRootIndex); 5322 Heap::kHeapNumberMapRootIndex);
5370 5323
5371 final_branch_condition = equal; 5324 final_branch_condition = equal;
5372 5325
5373 } else if (type_name->Equals(heap()->string_string())) { 5326 } else if (type_name->Equals(heap()->string_string())) {
5374 __ JumpIfSmi(input, false_label); 5327 __ JumpIfSmi(input, false_label, false_distance);
5375 __ CmpObjectType(input, FIRST_NONSTRING_TYPE, input); 5328 __ CmpObjectType(input, FIRST_NONSTRING_TYPE, input);
5376 __ j(above_equal, false_label); 5329 __ j(above_equal, false_label, false_distance);
5377 __ testb(FieldOperand(input, Map::kBitFieldOffset), 5330 __ testb(FieldOperand(input, Map::kBitFieldOffset),
5378 Immediate(1 << Map::kIsUndetectable)); 5331 Immediate(1 << Map::kIsUndetectable));
5379 final_branch_condition = zero; 5332 final_branch_condition = zero;
5380 5333
5381 } else if (type_name->Equals(heap()->symbol_string())) { 5334 } else if (type_name->Equals(heap()->symbol_string())) {
5382 __ JumpIfSmi(input, false_label); 5335 __ JumpIfSmi(input, false_label, false_distance);
5383 __ CmpObjectType(input, SYMBOL_TYPE, input); 5336 __ CmpObjectType(input, SYMBOL_TYPE, input);
5384 final_branch_condition = equal; 5337 final_branch_condition = equal;
5385 5338
5386 } else if (type_name->Equals(heap()->boolean_string())) { 5339 } else if (type_name->Equals(heap()->boolean_string())) {
5387 __ CompareRoot(input, Heap::kTrueValueRootIndex); 5340 __ CompareRoot(input, Heap::kTrueValueRootIndex);
5388 __ j(equal, true_label); 5341 __ j(equal, true_label, true_distance);
5389 __ CompareRoot(input, Heap::kFalseValueRootIndex); 5342 __ CompareRoot(input, Heap::kFalseValueRootIndex);
5390 final_branch_condition = equal; 5343 final_branch_condition = equal;
5391 5344
5392 } else if (FLAG_harmony_typeof && type_name->Equals(heap()->null_string())) { 5345 } else if (FLAG_harmony_typeof && type_name->Equals(heap()->null_string())) {
5393 __ CompareRoot(input, Heap::kNullValueRootIndex); 5346 __ CompareRoot(input, Heap::kNullValueRootIndex);
5394 final_branch_condition = equal; 5347 final_branch_condition = equal;
5395 5348
5396 } else if (type_name->Equals(heap()->undefined_string())) { 5349 } else if (type_name->Equals(heap()->undefined_string())) {
5397 __ CompareRoot(input, Heap::kUndefinedValueRootIndex); 5350 __ CompareRoot(input, Heap::kUndefinedValueRootIndex);
5398 __ j(equal, true_label); 5351 __ j(equal, true_label, true_distance);
5399 __ JumpIfSmi(input, false_label); 5352 __ JumpIfSmi(input, false_label, false_distance);
5400 // Check for undetectable objects => true. 5353 // Check for undetectable objects => true.
5401 __ movq(input, FieldOperand(input, HeapObject::kMapOffset)); 5354 __ movq(input, FieldOperand(input, HeapObject::kMapOffset));
5402 __ testb(FieldOperand(input, Map::kBitFieldOffset), 5355 __ testb(FieldOperand(input, Map::kBitFieldOffset),
5403 Immediate(1 << Map::kIsUndetectable)); 5356 Immediate(1 << Map::kIsUndetectable));
5404 final_branch_condition = not_zero; 5357 final_branch_condition = not_zero;
5405 5358
5406 } else if (type_name->Equals(heap()->function_string())) { 5359 } else if (type_name->Equals(heap()->function_string())) {
5407 STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2); 5360 STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2);
5408 __ JumpIfSmi(input, false_label); 5361 __ JumpIfSmi(input, false_label, false_distance);
5409 __ CmpObjectType(input, JS_FUNCTION_TYPE, input); 5362 __ CmpObjectType(input, JS_FUNCTION_TYPE, input);
5410 __ j(equal, true_label); 5363 __ j(equal, true_label, true_distance);
5411 __ CmpInstanceType(input, JS_FUNCTION_PROXY_TYPE); 5364 __ CmpInstanceType(input, JS_FUNCTION_PROXY_TYPE);
5412 final_branch_condition = equal; 5365 final_branch_condition = equal;
5413 5366
5414 } else if (type_name->Equals(heap()->object_string())) { 5367 } else if (type_name->Equals(heap()->object_string())) {
5415 __ JumpIfSmi(input, false_label); 5368 __ JumpIfSmi(input, false_label, false_distance);
5416 if (!FLAG_harmony_typeof) { 5369 if (!FLAG_harmony_typeof) {
5417 __ CompareRoot(input, Heap::kNullValueRootIndex); 5370 __ CompareRoot(input, Heap::kNullValueRootIndex);
5418 __ j(equal, true_label); 5371 __ j(equal, true_label, true_distance);
5419 } 5372 }
5420 __ CmpObjectType(input, FIRST_NONCALLABLE_SPEC_OBJECT_TYPE, input); 5373 __ CmpObjectType(input, FIRST_NONCALLABLE_SPEC_OBJECT_TYPE, input);
5421 __ j(below, false_label); 5374 __ j(below, false_label, false_distance);
5422 __ CmpInstanceType(input, LAST_NONCALLABLE_SPEC_OBJECT_TYPE); 5375 __ CmpInstanceType(input, LAST_NONCALLABLE_SPEC_OBJECT_TYPE);
5423 __ j(above, false_label); 5376 __ j(above, false_label, false_distance);
5424 // Check for undetectable objects => false. 5377 // Check for undetectable objects => false.
5425 __ testb(FieldOperand(input, Map::kBitFieldOffset), 5378 __ testb(FieldOperand(input, Map::kBitFieldOffset),
5426 Immediate(1 << Map::kIsUndetectable)); 5379 Immediate(1 << Map::kIsUndetectable));
5427 final_branch_condition = zero; 5380 final_branch_condition = zero;
5428 5381
5429 } else { 5382 } else {
5430 __ jmp(false_label); 5383 __ jmp(false_label, false_distance);
5431 } 5384 }
5432 5385
5433 return final_branch_condition; 5386 return final_branch_condition;
5434 } 5387 }
5435 5388
5436 5389
5437 void LCodeGen::DoIsConstructCallAndBranch(LIsConstructCallAndBranch* instr) { 5390 void LCodeGen::DoIsConstructCallAndBranch(LIsConstructCallAndBranch* instr) {
5438 Register temp = ToRegister(instr->temp()); 5391 Register temp = ToRegister(instr->temp());
5439 5392
5440 EmitIsConstructCall(temp); 5393 EmitIsConstructCall(temp);
(...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after
5673 FixedArray::kHeaderSize - kPointerSize)); 5626 FixedArray::kHeaderSize - kPointerSize));
5674 __ bind(&done); 5627 __ bind(&done);
5675 } 5628 }
5676 5629
5677 5630
5678 #undef __ 5631 #undef __
5679 5632
5680 } } // namespace v8::internal 5633 } } // namespace v8::internal
5681 5634
5682 #endif // V8_TARGET_ARCH_X64 5635 #endif // V8_TARGET_ARCH_X64
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698