OLD | NEW |
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 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
184 } | 184 } |
185 | 185 |
186 // Reserve space for the stack slots needed by the code. | 186 // Reserve space for the stack slots needed by the code. |
187 int slots = GetStackSlotCount(); | 187 int slots = GetStackSlotCount(); |
188 if (slots > 0) { | 188 if (slots > 0) { |
189 if (FLAG_debug_code) { | 189 if (FLAG_debug_code) { |
190 __ subq(rsp, Immediate(slots * kPointerSize)); | 190 __ subq(rsp, Immediate(slots * kPointerSize)); |
191 #ifdef _MSC_VER | 191 #ifdef _MSC_VER |
192 MakeSureStackPagesMapped(slots * kPointerSize); | 192 MakeSureStackPagesMapped(slots * kPointerSize); |
193 #endif | 193 #endif |
194 __ push(rax); | 194 __ Push(rax); |
195 __ Set(rax, slots); | 195 __ Set(rax, slots); |
196 __ movq(kScratchRegister, kSlotsZapValue); | 196 __ movq(kScratchRegister, kSlotsZapValue); |
197 Label loop; | 197 Label loop; |
198 __ bind(&loop); | 198 __ bind(&loop); |
199 __ movp(MemOperand(rsp, rax, times_pointer_size, 0), | 199 __ movp(MemOperand(rsp, rax, times_pointer_size, 0), |
200 kScratchRegister); | 200 kScratchRegister); |
201 __ decl(rax); | 201 __ decl(rax); |
202 __ j(not_zero, &loop); | 202 __ j(not_zero, &loop); |
203 __ pop(rax); | 203 __ Pop(rax); |
204 } else { | 204 } else { |
205 __ subq(rsp, Immediate(slots * kPointerSize)); | 205 __ subq(rsp, Immediate(slots * kPointerSize)); |
206 #ifdef _MSC_VER | 206 #ifdef _MSC_VER |
207 MakeSureStackPagesMapped(slots * kPointerSize); | 207 MakeSureStackPagesMapped(slots * kPointerSize); |
208 #endif | 208 #endif |
209 } | 209 } |
210 | 210 |
211 if (info()->saves_caller_doubles()) { | 211 if (info()->saves_caller_doubles()) { |
212 SaveCallerDoubles(); | 212 SaveCallerDoubles(); |
213 } | 213 } |
214 } | 214 } |
215 | 215 |
216 // Possibly allocate a local context. | 216 // Possibly allocate a local context. |
217 int heap_slots = info_->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; | 217 int heap_slots = info_->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; |
218 if (heap_slots > 0) { | 218 if (heap_slots > 0) { |
219 Comment(";;; Allocate local context"); | 219 Comment(";;; Allocate local context"); |
220 // Argument to NewContext is the function, which is still in rdi. | 220 // Argument to NewContext is the function, which is still in rdi. |
221 if (heap_slots <= FastNewContextStub::kMaximumSlots) { | 221 if (heap_slots <= FastNewContextStub::kMaximumSlots) { |
222 FastNewContextStub stub(heap_slots); | 222 FastNewContextStub stub(heap_slots); |
223 __ CallStub(&stub); | 223 __ CallStub(&stub); |
224 } else { | 224 } else { |
225 __ push(rdi); | 225 __ Push(rdi); |
226 __ CallRuntime(Runtime::kNewFunctionContext, 1); | 226 __ CallRuntime(Runtime::kNewFunctionContext, 1); |
227 } | 227 } |
228 RecordSafepoint(Safepoint::kNoLazyDeopt); | 228 RecordSafepoint(Safepoint::kNoLazyDeopt); |
229 // Context is returned in rax. It replaces the context passed to us. | 229 // Context is returned in rax. It replaces the context passed to us. |
230 // It's saved in the stack and kept live in rsi. | 230 // It's saved in the stack and kept live in rsi. |
231 __ movp(rsi, rax); | 231 __ movp(rsi, rax); |
232 __ movp(Operand(rbp, StandardFrameConstants::kContextOffset), rax); | 232 __ movp(Operand(rbp, StandardFrameConstants::kContextOffset), rax); |
233 | 233 |
234 // Copy any necessary parameters into the context. | 234 // Copy any necessary parameters into the context. |
235 int num_parameters = scope()->num_parameters(); | 235 int num_parameters = scope()->num_parameters(); |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
296 Comment(";;; jump table entry %d: deoptimization bailout %d.", i, id); | 296 Comment(";;; jump table entry %d: deoptimization bailout %d.", i, id); |
297 } | 297 } |
298 if (jump_table_[i].needs_frame) { | 298 if (jump_table_[i].needs_frame) { |
299 ASSERT(!info()->saves_caller_doubles()); | 299 ASSERT(!info()->saves_caller_doubles()); |
300 __ Move(kScratchRegister, ExternalReference::ForDeoptEntry(entry)); | 300 __ Move(kScratchRegister, ExternalReference::ForDeoptEntry(entry)); |
301 if (needs_frame.is_bound()) { | 301 if (needs_frame.is_bound()) { |
302 __ jmp(&needs_frame); | 302 __ jmp(&needs_frame); |
303 } else { | 303 } else { |
304 __ bind(&needs_frame); | 304 __ bind(&needs_frame); |
305 __ movp(rsi, MemOperand(rbp, StandardFrameConstants::kContextOffset)); | 305 __ movp(rsi, MemOperand(rbp, StandardFrameConstants::kContextOffset)); |
306 __ push(rbp); | 306 __ pushq(rbp); |
307 __ movp(rbp, rsp); | 307 __ movp(rbp, rsp); |
308 __ push(rsi); | 308 __ Push(rsi); |
309 // This variant of deopt can only be used with stubs. Since we don't | 309 // This variant of deopt can only be used with stubs. Since we don't |
310 // have a function pointer to install in the stack frame that we're | 310 // have a function pointer to install in the stack frame that we're |
311 // building, install a special marker there instead. | 311 // building, install a special marker there instead. |
312 ASSERT(info()->IsStub()); | 312 ASSERT(info()->IsStub()); |
313 __ Move(rsi, Smi::FromInt(StackFrame::STUB)); | 313 __ Move(rsi, Smi::FromInt(StackFrame::STUB)); |
314 __ push(rsi); | 314 __ Push(rsi); |
315 __ movp(rsi, MemOperand(rsp, kPointerSize)); | 315 __ movp(rsi, MemOperand(rsp, kPointerSize)); |
316 __ call(kScratchRegister); | 316 __ call(kScratchRegister); |
317 } | 317 } |
318 } else { | 318 } else { |
319 if (info()->saves_caller_doubles()) { | 319 if (info()->saves_caller_doubles()) { |
320 ASSERT(info()->IsStub()); | 320 ASSERT(info()->IsStub()); |
321 RestoreCallerDoubles(); | 321 RestoreCallerDoubles(); |
322 } | 322 } |
323 __ call(entry, RelocInfo::RUNTIME_ENTRY); | 323 __ call(entry, RelocInfo::RUNTIME_ENTRY); |
324 } | 324 } |
(...skipping 18 matching lines...) Expand all Loading... |
343 code->instruction_index(), | 343 code->instruction_index(), |
344 code->instr()->hydrogen_value()->id(), | 344 code->instr()->hydrogen_value()->id(), |
345 code->instr()->Mnemonic()); | 345 code->instr()->Mnemonic()); |
346 __ bind(code->entry()); | 346 __ bind(code->entry()); |
347 if (NeedsDeferredFrame()) { | 347 if (NeedsDeferredFrame()) { |
348 Comment(";;; Build frame"); | 348 Comment(";;; Build frame"); |
349 ASSERT(!frame_is_built_); | 349 ASSERT(!frame_is_built_); |
350 ASSERT(info()->IsStub()); | 350 ASSERT(info()->IsStub()); |
351 frame_is_built_ = true; | 351 frame_is_built_ = true; |
352 // Build the frame in such a way that esi isn't trashed. | 352 // Build the frame in such a way that esi isn't trashed. |
353 __ push(rbp); // Caller's frame pointer. | 353 __ pushq(rbp); // Caller's frame pointer. |
354 __ push(Operand(rbp, StandardFrameConstants::kContextOffset)); | 354 __ Push(Operand(rbp, StandardFrameConstants::kContextOffset)); |
355 __ Push(Smi::FromInt(StackFrame::STUB)); | 355 __ Push(Smi::FromInt(StackFrame::STUB)); |
356 __ lea(rbp, Operand(rsp, 2 * kPointerSize)); | 356 __ lea(rbp, Operand(rsp, 2 * kPointerSize)); |
357 Comment(";;; Deferred code"); | 357 Comment(";;; Deferred code"); |
358 } | 358 } |
359 code->Generate(); | 359 code->Generate(); |
360 if (NeedsDeferredFrame()) { | 360 if (NeedsDeferredFrame()) { |
361 __ bind(code->done()); | 361 __ bind(code->done()); |
362 Comment(";;; Destroy frame"); | 362 Comment(";;; Destroy frame"); |
363 ASSERT(frame_is_built_); | 363 ASSERT(frame_is_built_); |
364 frame_is_built_ = false; | 364 frame_is_built_ = false; |
365 __ movp(rsp, rbp); | 365 __ movp(rsp, rbp); |
366 __ pop(rbp); | 366 __ popq(rbp); |
367 } | 367 } |
368 __ jmp(code->exit()); | 368 __ jmp(code->exit()); |
369 } | 369 } |
370 } | 370 } |
371 | 371 |
372 // Deferred code is the last part of the instruction sequence. Mark | 372 // Deferred code is the last part of the instruction sequence. Mark |
373 // the generated code as done unless we bailed out. | 373 // the generated code as done unless we bailed out. |
374 if (!is_aborted()) status_ = DONE; | 374 if (!is_aborted()) status_ = DONE; |
375 return !is_aborted(); | 375 return !is_aborted(); |
376 } | 376 } |
(...skipping 338 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
715 Deoptimizer::GetDeoptimizationEntry(isolate(), id, bailout_type); | 715 Deoptimizer::GetDeoptimizationEntry(isolate(), id, bailout_type); |
716 if (entry == NULL) { | 716 if (entry == NULL) { |
717 Abort(kBailoutWasNotPrepared); | 717 Abort(kBailoutWasNotPrepared); |
718 return; | 718 return; |
719 } | 719 } |
720 | 720 |
721 if (DeoptEveryNTimes()) { | 721 if (DeoptEveryNTimes()) { |
722 ExternalReference count = ExternalReference::stress_deopt_count(isolate()); | 722 ExternalReference count = ExternalReference::stress_deopt_count(isolate()); |
723 Label no_deopt; | 723 Label no_deopt; |
724 __ pushfq(); | 724 __ pushfq(); |
725 __ push(rax); | 725 __ Push(rax); |
726 Operand count_operand = masm()->ExternalOperand(count, kScratchRegister); | 726 Operand count_operand = masm()->ExternalOperand(count, kScratchRegister); |
727 __ movl(rax, count_operand); | 727 __ movl(rax, count_operand); |
728 __ subl(rax, Immediate(1)); | 728 __ subl(rax, Immediate(1)); |
729 __ j(not_zero, &no_deopt, Label::kNear); | 729 __ j(not_zero, &no_deopt, Label::kNear); |
730 if (FLAG_trap_on_deopt) __ int3(); | 730 if (FLAG_trap_on_deopt) __ int3(); |
731 __ movl(rax, Immediate(FLAG_deopt_every_n_times)); | 731 __ movl(rax, Immediate(FLAG_deopt_every_n_times)); |
732 __ movl(count_operand, rax); | 732 __ movl(count_operand, rax); |
733 __ pop(rax); | 733 __ Pop(rax); |
734 __ popfq(); | 734 __ popfq(); |
735 ASSERT(frame_is_built_); | 735 ASSERT(frame_is_built_); |
736 __ call(entry, RelocInfo::RUNTIME_ENTRY); | 736 __ call(entry, RelocInfo::RUNTIME_ENTRY); |
737 __ bind(&no_deopt); | 737 __ bind(&no_deopt); |
738 __ movl(count_operand, rax); | 738 __ movl(count_operand, rax); |
739 __ pop(rax); | 739 __ Pop(rax); |
740 __ popfq(); | 740 __ popfq(); |
741 } | 741 } |
742 | 742 |
743 if (info()->ShouldTrapOnDeopt()) { | 743 if (info()->ShouldTrapOnDeopt()) { |
744 Label done; | 744 Label done; |
745 if (cc != no_condition) { | 745 if (cc != no_condition) { |
746 __ j(NegateCondition(cc), &done, Label::kNear); | 746 __ j(NegateCondition(cc), &done, Label::kNear); |
747 } | 747 } |
748 __ int3(); | 748 __ int3(); |
749 __ bind(&done); | 749 __ bind(&done); |
(...skipping 915 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1665 SeqString::kHeaderSize); | 1665 SeqString::kHeaderSize); |
1666 } | 1666 } |
1667 | 1667 |
1668 | 1668 |
1669 void LCodeGen::DoSeqStringGetChar(LSeqStringGetChar* instr) { | 1669 void LCodeGen::DoSeqStringGetChar(LSeqStringGetChar* instr) { |
1670 String::Encoding encoding = instr->hydrogen()->encoding(); | 1670 String::Encoding encoding = instr->hydrogen()->encoding(); |
1671 Register result = ToRegister(instr->result()); | 1671 Register result = ToRegister(instr->result()); |
1672 Register string = ToRegister(instr->string()); | 1672 Register string = ToRegister(instr->string()); |
1673 | 1673 |
1674 if (FLAG_debug_code) { | 1674 if (FLAG_debug_code) { |
1675 __ push(string); | 1675 __ Push(string); |
1676 __ movp(string, FieldOperand(string, HeapObject::kMapOffset)); | 1676 __ movp(string, FieldOperand(string, HeapObject::kMapOffset)); |
1677 __ movzxbq(string, FieldOperand(string, Map::kInstanceTypeOffset)); | 1677 __ movzxbq(string, FieldOperand(string, Map::kInstanceTypeOffset)); |
1678 | 1678 |
1679 __ andb(string, Immediate(kStringRepresentationMask | kStringEncodingMask)); | 1679 __ andb(string, Immediate(kStringRepresentationMask | kStringEncodingMask)); |
1680 static const uint32_t one_byte_seq_type = kSeqStringTag | kOneByteStringTag; | 1680 static const uint32_t one_byte_seq_type = kSeqStringTag | kOneByteStringTag; |
1681 static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag; | 1681 static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag; |
1682 __ cmpq(string, Immediate(encoding == String::ONE_BYTE_ENCODING | 1682 __ cmpq(string, Immediate(encoding == String::ONE_BYTE_ENCODING |
1683 ? one_byte_seq_type : two_byte_seq_type)); | 1683 ? one_byte_seq_type : two_byte_seq_type)); |
1684 __ Check(equal, kUnexpectedStringType); | 1684 __ Check(equal, kUnexpectedStringType); |
1685 __ pop(string); | 1685 __ Pop(string); |
1686 } | 1686 } |
1687 | 1687 |
1688 Operand operand = BuildSeqStringOperand(string, instr->index(), encoding); | 1688 Operand operand = BuildSeqStringOperand(string, instr->index(), encoding); |
1689 if (encoding == String::ONE_BYTE_ENCODING) { | 1689 if (encoding == String::ONE_BYTE_ENCODING) { |
1690 __ movzxbl(result, operand); | 1690 __ movzxbl(result, operand); |
1691 } else { | 1691 } else { |
1692 __ movzxwl(result, operand); | 1692 __ movzxwl(result, operand); |
1693 } | 1693 } |
1694 } | 1694 } |
1695 | 1695 |
(...skipping 797 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2493 Register reg = ToRegister(instr->value()); | 2493 Register reg = ToRegister(instr->value()); |
2494 | 2494 |
2495 __ Cmp(FieldOperand(reg, HeapObject::kMapOffset), instr->map()); | 2495 __ Cmp(FieldOperand(reg, HeapObject::kMapOffset), instr->map()); |
2496 EmitBranch(instr, equal); | 2496 EmitBranch(instr, equal); |
2497 } | 2497 } |
2498 | 2498 |
2499 | 2499 |
2500 void LCodeGen::DoInstanceOf(LInstanceOf* instr) { | 2500 void LCodeGen::DoInstanceOf(LInstanceOf* instr) { |
2501 ASSERT(ToRegister(instr->context()).is(rsi)); | 2501 ASSERT(ToRegister(instr->context()).is(rsi)); |
2502 InstanceofStub stub(InstanceofStub::kNoFlags); | 2502 InstanceofStub stub(InstanceofStub::kNoFlags); |
2503 __ push(ToRegister(instr->left())); | 2503 __ Push(ToRegister(instr->left())); |
2504 __ push(ToRegister(instr->right())); | 2504 __ Push(ToRegister(instr->right())); |
2505 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | 2505 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); |
2506 Label true_value, done; | 2506 Label true_value, done; |
2507 __ testq(rax, rax); | 2507 __ testq(rax, rax); |
2508 __ j(zero, &true_value, Label::kNear); | 2508 __ j(zero, &true_value, Label::kNear); |
2509 __ LoadRoot(ToRegister(instr->result()), Heap::kFalseValueRootIndex); | 2509 __ LoadRoot(ToRegister(instr->result()), Heap::kFalseValueRootIndex); |
2510 __ jmp(&done, Label::kNear); | 2510 __ jmp(&done, Label::kNear); |
2511 __ bind(&true_value); | 2511 __ bind(&true_value); |
2512 __ LoadRoot(ToRegister(instr->result()), Heap::kTrueValueRootIndex); | 2512 __ LoadRoot(ToRegister(instr->result()), Heap::kTrueValueRootIndex); |
2513 __ bind(&done); | 2513 __ bind(&done); |
2514 } | 2514 } |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2580 | 2580 |
2581 | 2581 |
2582 void LCodeGen::DoDeferredInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr, | 2582 void LCodeGen::DoDeferredInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr, |
2583 Label* map_check) { | 2583 Label* map_check) { |
2584 { | 2584 { |
2585 PushSafepointRegistersScope scope(this); | 2585 PushSafepointRegistersScope scope(this); |
2586 InstanceofStub::Flags flags = static_cast<InstanceofStub::Flags>( | 2586 InstanceofStub::Flags flags = static_cast<InstanceofStub::Flags>( |
2587 InstanceofStub::kNoFlags | InstanceofStub::kCallSiteInlineCheck); | 2587 InstanceofStub::kNoFlags | InstanceofStub::kCallSiteInlineCheck); |
2588 InstanceofStub stub(flags); | 2588 InstanceofStub stub(flags); |
2589 | 2589 |
2590 __ push(ToRegister(instr->value())); | 2590 __ Push(ToRegister(instr->value())); |
2591 __ Push(instr->function()); | 2591 __ Push(instr->function()); |
2592 | 2592 |
2593 static const int kAdditionalDelta = 10; | 2593 static const int kAdditionalDelta = 10; |
2594 int delta = | 2594 int delta = |
2595 masm_->SizeOfCodeGeneratedSince(map_check) + kAdditionalDelta; | 2595 masm_->SizeOfCodeGeneratedSince(map_check) + kAdditionalDelta; |
2596 ASSERT(delta >= 0); | 2596 ASSERT(delta >= 0); |
2597 __ push_imm32(delta); | 2597 __ PushImm32(delta); |
2598 | 2598 |
2599 // We are pushing three values on the stack but recording a | 2599 // We are pushing three values on the stack but recording a |
2600 // safepoint with two arguments because stub is going to | 2600 // safepoint with two arguments because stub is going to |
2601 // remove the third argument from the stack before jumping | 2601 // remove the third argument from the stack before jumping |
2602 // to instanceof builtin on the slow path. | 2602 // to instanceof builtin on the slow path. |
2603 CallCodeGeneric(stub.GetCode(isolate()), | 2603 CallCodeGeneric(stub.GetCode(isolate()), |
2604 RelocInfo::CODE_TARGET, | 2604 RelocInfo::CODE_TARGET, |
2605 instr, | 2605 instr, |
2606 RECORD_SAFEPOINT_WITH_REGISTERS, | 2606 RECORD_SAFEPOINT_WITH_REGISTERS, |
2607 2); | 2607 2); |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2642 __ bind(&done); | 2642 __ bind(&done); |
2643 } | 2643 } |
2644 | 2644 |
2645 | 2645 |
2646 void LCodeGen::DoReturn(LReturn* instr) { | 2646 void LCodeGen::DoReturn(LReturn* instr) { |
2647 if (FLAG_trace && info()->IsOptimizing()) { | 2647 if (FLAG_trace && info()->IsOptimizing()) { |
2648 // Preserve the return value on the stack and rely on the runtime call | 2648 // Preserve the return value on the stack and rely on the runtime call |
2649 // to return the value in the same register. We're leaving the code | 2649 // to return the value in the same register. We're leaving the code |
2650 // managed by the register allocator and tearing down the frame, it's | 2650 // managed by the register allocator and tearing down the frame, it's |
2651 // safe to write to the context register. | 2651 // safe to write to the context register. |
2652 __ push(rax); | 2652 __ Push(rax); |
2653 __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); | 2653 __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); |
2654 __ CallRuntime(Runtime::kTraceExit, 1); | 2654 __ CallRuntime(Runtime::kTraceExit, 1); |
2655 } | 2655 } |
2656 if (info()->saves_caller_doubles()) { | 2656 if (info()->saves_caller_doubles()) { |
2657 RestoreCallerDoubles(); | 2657 RestoreCallerDoubles(); |
2658 } | 2658 } |
2659 int no_frame_start = -1; | 2659 int no_frame_start = -1; |
2660 if (NeedsEagerFrame()) { | 2660 if (NeedsEagerFrame()) { |
2661 __ movp(rsp, rbp); | 2661 __ movp(rsp, rbp); |
2662 __ pop(rbp); | 2662 __ popq(rbp); |
2663 no_frame_start = masm_->pc_offset(); | 2663 no_frame_start = masm_->pc_offset(); |
2664 } | 2664 } |
2665 if (instr->has_constant_parameter_count()) { | 2665 if (instr->has_constant_parameter_count()) { |
2666 __ Ret((ToInteger32(instr->constant_parameter_count()) + 1) * kPointerSize, | 2666 __ Ret((ToInteger32(instr->constant_parameter_count()) + 1) * kPointerSize, |
2667 rcx); | 2667 rcx); |
2668 } else { | 2668 } else { |
2669 Register reg = ToRegister(instr->parameter_count()); | 2669 Register reg = ToRegister(instr->parameter_count()); |
2670 // The argument count parameter is a smi | 2670 // The argument count parameter is a smi |
2671 __ SmiToInteger32(reg, reg); | 2671 __ SmiToInteger32(reg, reg); |
2672 Register return_addr_reg = reg.is(rcx) ? rbx : rcx; | 2672 Register return_addr_reg = reg.is(rcx) ? rbx : rcx; |
(...skipping 591 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3264 ASSERT(receiver.is(rax)); // Used for parameter count. | 3264 ASSERT(receiver.is(rax)); // Used for parameter count. |
3265 ASSERT(function.is(rdi)); // Required by InvokeFunction. | 3265 ASSERT(function.is(rdi)); // Required by InvokeFunction. |
3266 ASSERT(ToRegister(instr->result()).is(rax)); | 3266 ASSERT(ToRegister(instr->result()).is(rax)); |
3267 | 3267 |
3268 // Copy the arguments to this function possibly from the | 3268 // Copy the arguments to this function possibly from the |
3269 // adaptor frame below it. | 3269 // adaptor frame below it. |
3270 const uint32_t kArgumentsLimit = 1 * KB; | 3270 const uint32_t kArgumentsLimit = 1 * KB; |
3271 __ cmpq(length, Immediate(kArgumentsLimit)); | 3271 __ cmpq(length, Immediate(kArgumentsLimit)); |
3272 DeoptimizeIf(above, instr->environment()); | 3272 DeoptimizeIf(above, instr->environment()); |
3273 | 3273 |
3274 __ push(receiver); | 3274 __ Push(receiver); |
3275 __ movp(receiver, length); | 3275 __ movp(receiver, length); |
3276 | 3276 |
3277 // Loop through the arguments pushing them onto the execution | 3277 // Loop through the arguments pushing them onto the execution |
3278 // stack. | 3278 // stack. |
3279 Label invoke, loop; | 3279 Label invoke, loop; |
3280 // length is a small non-negative integer, due to the test above. | 3280 // length is a small non-negative integer, due to the test above. |
3281 __ testl(length, length); | 3281 __ testl(length, length); |
3282 __ j(zero, &invoke, Label::kNear); | 3282 __ j(zero, &invoke, Label::kNear); |
3283 __ bind(&loop); | 3283 __ bind(&loop); |
3284 StackArgumentsAccessor args(elements, length, | 3284 StackArgumentsAccessor args(elements, length, |
3285 ARGUMENTS_DONT_CONTAIN_RECEIVER); | 3285 ARGUMENTS_DONT_CONTAIN_RECEIVER); |
3286 __ push(args.GetArgumentOperand(0)); | 3286 __ Push(args.GetArgumentOperand(0)); |
3287 __ decl(length); | 3287 __ decl(length); |
3288 __ j(not_zero, &loop); | 3288 __ j(not_zero, &loop); |
3289 | 3289 |
3290 // Invoke the function. | 3290 // Invoke the function. |
3291 __ bind(&invoke); | 3291 __ bind(&invoke); |
3292 ASSERT(instr->HasPointerMap()); | 3292 ASSERT(instr->HasPointerMap()); |
3293 LPointerMap* pointers = instr->pointer_map(); | 3293 LPointerMap* pointers = instr->pointer_map(); |
3294 SafepointGenerator safepoint_generator( | 3294 SafepointGenerator safepoint_generator( |
3295 this, pointers, Safepoint::kLazyDeopt); | 3295 this, pointers, Safepoint::kLazyDeopt); |
3296 ParameterCount actual(rax); | 3296 ParameterCount actual(rax); |
(...skipping 24 matching lines...) Expand all Loading... |
3321 __ movp(result, Operand(rbp, StandardFrameConstants::kContextOffset)); | 3321 __ movp(result, Operand(rbp, StandardFrameConstants::kContextOffset)); |
3322 } else { | 3322 } else { |
3323 // If there is no frame, the context must be in rsi. | 3323 // If there is no frame, the context must be in rsi. |
3324 ASSERT(result.is(rsi)); | 3324 ASSERT(result.is(rsi)); |
3325 } | 3325 } |
3326 } | 3326 } |
3327 | 3327 |
3328 | 3328 |
3329 void LCodeGen::DoDeclareGlobals(LDeclareGlobals* instr) { | 3329 void LCodeGen::DoDeclareGlobals(LDeclareGlobals* instr) { |
3330 ASSERT(ToRegister(instr->context()).is(rsi)); | 3330 ASSERT(ToRegister(instr->context()).is(rsi)); |
3331 __ push(rsi); // The context is the first argument. | 3331 __ Push(rsi); // The context is the first argument. |
3332 __ Push(instr->hydrogen()->pairs()); | 3332 __ Push(instr->hydrogen()->pairs()); |
3333 __ Push(Smi::FromInt(instr->hydrogen()->flags())); | 3333 __ Push(Smi::FromInt(instr->hydrogen()->flags())); |
3334 CallRuntime(Runtime::kDeclareGlobals, 3, instr); | 3334 CallRuntime(Runtime::kDeclareGlobals, 3, instr); |
3335 } | 3335 } |
3336 | 3336 |
3337 | 3337 |
3338 void LCodeGen::CallKnownFunction(Handle<JSFunction> function, | 3338 void LCodeGen::CallKnownFunction(Handle<JSFunction> function, |
3339 int formal_parameter_count, | 3339 int formal_parameter_count, |
3340 int arity, | 3340 int arity, |
3341 LInstruction* instr, | 3341 LInstruction* instr, |
(...skipping 1089 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4431 void LCodeGen::DoDeferredStringCharCodeAt(LStringCharCodeAt* instr) { | 4431 void LCodeGen::DoDeferredStringCharCodeAt(LStringCharCodeAt* instr) { |
4432 Register string = ToRegister(instr->string()); | 4432 Register string = ToRegister(instr->string()); |
4433 Register result = ToRegister(instr->result()); | 4433 Register result = ToRegister(instr->result()); |
4434 | 4434 |
4435 // TODO(3095996): Get rid of this. For now, we need to make the | 4435 // TODO(3095996): Get rid of this. For now, we need to make the |
4436 // result register contain a valid pointer because it is already | 4436 // result register contain a valid pointer because it is already |
4437 // contained in the register pointer map. | 4437 // contained in the register pointer map. |
4438 __ Set(result, 0); | 4438 __ Set(result, 0); |
4439 | 4439 |
4440 PushSafepointRegistersScope scope(this); | 4440 PushSafepointRegistersScope scope(this); |
4441 __ push(string); | 4441 __ Push(string); |
4442 // Push the index as a smi. This is safe because of the checks in | 4442 // Push the index as a smi. This is safe because of the checks in |
4443 // DoStringCharCodeAt above. | 4443 // DoStringCharCodeAt above. |
4444 STATIC_ASSERT(String::kMaxLength <= Smi::kMaxValue); | 4444 STATIC_ASSERT(String::kMaxLength <= Smi::kMaxValue); |
4445 if (instr->index()->IsConstantOperand()) { | 4445 if (instr->index()->IsConstantOperand()) { |
4446 int32_t const_index = ToInteger32(LConstantOperand::cast(instr->index())); | 4446 int32_t const_index = ToInteger32(LConstantOperand::cast(instr->index())); |
4447 __ Push(Smi::FromInt(const_index)); | 4447 __ Push(Smi::FromInt(const_index)); |
4448 } else { | 4448 } else { |
4449 Register index = ToRegister(instr->index()); | 4449 Register index = ToRegister(instr->index()); |
4450 __ Integer32ToSmi(index, index); | 4450 __ Integer32ToSmi(index, index); |
4451 __ push(index); | 4451 __ Push(index); |
4452 } | 4452 } |
4453 CallRuntimeFromDeferred( | 4453 CallRuntimeFromDeferred( |
4454 Runtime::kStringCharCodeAt, 2, instr, instr->context()); | 4454 Runtime::kStringCharCodeAt, 2, instr, instr->context()); |
4455 __ AssertSmi(rax); | 4455 __ AssertSmi(rax); |
4456 __ SmiToInteger32(rax, rax); | 4456 __ SmiToInteger32(rax, rax); |
4457 __ StoreToSafepointRegisterSlot(result, rax); | 4457 __ StoreToSafepointRegisterSlot(result, rax); |
4458 } | 4458 } |
4459 | 4459 |
4460 | 4460 |
4461 void LCodeGen::DoStringCharFromCode(LStringCharFromCode* instr) { | 4461 void LCodeGen::DoStringCharFromCode(LStringCharFromCode* instr) { |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4496 Register char_code = ToRegister(instr->char_code()); | 4496 Register char_code = ToRegister(instr->char_code()); |
4497 Register result = ToRegister(instr->result()); | 4497 Register result = ToRegister(instr->result()); |
4498 | 4498 |
4499 // TODO(3095996): Get rid of this. For now, we need to make the | 4499 // TODO(3095996): Get rid of this. For now, we need to make the |
4500 // result register contain a valid pointer because it is already | 4500 // result register contain a valid pointer because it is already |
4501 // contained in the register pointer map. | 4501 // contained in the register pointer map. |
4502 __ Set(result, 0); | 4502 __ Set(result, 0); |
4503 | 4503 |
4504 PushSafepointRegistersScope scope(this); | 4504 PushSafepointRegistersScope scope(this); |
4505 __ Integer32ToSmi(char_code, char_code); | 4505 __ Integer32ToSmi(char_code, char_code); |
4506 __ push(char_code); | 4506 __ Push(char_code); |
4507 CallRuntimeFromDeferred(Runtime::kCharFromCode, 1, instr, instr->context()); | 4507 CallRuntimeFromDeferred(Runtime::kCharFromCode, 1, instr, instr->context()); |
4508 __ StoreToSafepointRegisterSlot(result, rax); | 4508 __ StoreToSafepointRegisterSlot(result, rax); |
4509 } | 4509 } |
4510 | 4510 |
4511 | 4511 |
4512 void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) { | 4512 void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) { |
4513 LOperand* input = instr->value(); | 4513 LOperand* input = instr->value(); |
4514 ASSERT(input->IsRegister() || input->IsStackSlot()); | 4514 ASSERT(input->IsRegister() || input->IsStackSlot()); |
4515 LOperand* output = instr->result(); | 4515 LOperand* output = instr->result(); |
4516 ASSERT(output->IsDoubleRegister()); | 4516 ASSERT(output->IsDoubleRegister()); |
(...skipping 449 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4966 void LCodeGen::DoCheckValue(LCheckValue* instr) { | 4966 void LCodeGen::DoCheckValue(LCheckValue* instr) { |
4967 Register reg = ToRegister(instr->value()); | 4967 Register reg = ToRegister(instr->value()); |
4968 __ Cmp(reg, instr->hydrogen()->object().handle()); | 4968 __ Cmp(reg, instr->hydrogen()->object().handle()); |
4969 DeoptimizeIf(not_equal, instr->environment()); | 4969 DeoptimizeIf(not_equal, instr->environment()); |
4970 } | 4970 } |
4971 | 4971 |
4972 | 4972 |
4973 void LCodeGen::DoDeferredInstanceMigration(LCheckMaps* instr, Register object) { | 4973 void LCodeGen::DoDeferredInstanceMigration(LCheckMaps* instr, Register object) { |
4974 { | 4974 { |
4975 PushSafepointRegistersScope scope(this); | 4975 PushSafepointRegistersScope scope(this); |
4976 __ push(object); | 4976 __ Push(object); |
4977 __ Set(rsi, 0); | 4977 __ Set(rsi, 0); |
4978 __ CallRuntimeSaveDoubles(Runtime::kTryMigrateInstance); | 4978 __ CallRuntimeSaveDoubles(Runtime::kTryMigrateInstance); |
4979 RecordSafepointWithRegisters( | 4979 RecordSafepointWithRegisters( |
4980 instr->pointer_map(), 1, Safepoint::kNoLazyDeopt); | 4980 instr->pointer_map(), 1, Safepoint::kNoLazyDeopt); |
4981 | 4981 |
4982 __ testq(rax, Immediate(kSmiTagMask)); | 4982 __ testq(rax, Immediate(kSmiTagMask)); |
4983 } | 4983 } |
4984 DeoptimizeIf(zero, instr->environment()); | 4984 DeoptimizeIf(zero, instr->environment()); |
4985 } | 4985 } |
4986 | 4986 |
(...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5182 // TODO(3095996): Get rid of this. For now, we need to make the | 5182 // TODO(3095996): Get rid of this. For now, we need to make the |
5183 // result register contain a valid pointer because it is already | 5183 // result register contain a valid pointer because it is already |
5184 // contained in the register pointer map. | 5184 // contained in the register pointer map. |
5185 __ Move(result, Smi::FromInt(0)); | 5185 __ Move(result, Smi::FromInt(0)); |
5186 | 5186 |
5187 PushSafepointRegistersScope scope(this); | 5187 PushSafepointRegistersScope scope(this); |
5188 if (instr->size()->IsRegister()) { | 5188 if (instr->size()->IsRegister()) { |
5189 Register size = ToRegister(instr->size()); | 5189 Register size = ToRegister(instr->size()); |
5190 ASSERT(!size.is(result)); | 5190 ASSERT(!size.is(result)); |
5191 __ Integer32ToSmi(size, size); | 5191 __ Integer32ToSmi(size, size); |
5192 __ push(size); | 5192 __ Push(size); |
5193 } else { | 5193 } else { |
5194 int32_t size = ToInteger32(LConstantOperand::cast(instr->size())); | 5194 int32_t size = ToInteger32(LConstantOperand::cast(instr->size())); |
5195 __ Push(Smi::FromInt(size)); | 5195 __ Push(Smi::FromInt(size)); |
5196 } | 5196 } |
5197 | 5197 |
5198 int flags = 0; | 5198 int flags = 0; |
5199 if (instr->hydrogen()->IsOldPointerSpaceAllocation()) { | 5199 if (instr->hydrogen()->IsOldPointerSpaceAllocation()) { |
5200 ASSERT(!instr->hydrogen()->IsOldDataSpaceAllocation()); | 5200 ASSERT(!instr->hydrogen()->IsOldDataSpaceAllocation()); |
5201 ASSERT(!instr->hydrogen()->IsNewSpaceAllocation()); | 5201 ASSERT(!instr->hydrogen()->IsNewSpaceAllocation()); |
5202 flags = AllocateTargetSpace::update(flags, OLD_POINTER_SPACE); | 5202 flags = AllocateTargetSpace::update(flags, OLD_POINTER_SPACE); |
5203 } else if (instr->hydrogen()->IsOldDataSpaceAllocation()) { | 5203 } else if (instr->hydrogen()->IsOldDataSpaceAllocation()) { |
5204 ASSERT(!instr->hydrogen()->IsNewSpaceAllocation()); | 5204 ASSERT(!instr->hydrogen()->IsNewSpaceAllocation()); |
5205 flags = AllocateTargetSpace::update(flags, OLD_DATA_SPACE); | 5205 flags = AllocateTargetSpace::update(flags, OLD_DATA_SPACE); |
5206 } else { | 5206 } else { |
5207 flags = AllocateTargetSpace::update(flags, NEW_SPACE); | 5207 flags = AllocateTargetSpace::update(flags, NEW_SPACE); |
5208 } | 5208 } |
5209 __ Push(Smi::FromInt(flags)); | 5209 __ Push(Smi::FromInt(flags)); |
5210 | 5210 |
5211 CallRuntimeFromDeferred( | 5211 CallRuntimeFromDeferred( |
5212 Runtime::kAllocateInTargetSpace, 2, instr, instr->context()); | 5212 Runtime::kAllocateInTargetSpace, 2, instr, instr->context()); |
5213 __ StoreToSafepointRegisterSlot(result, rax); | 5213 __ StoreToSafepointRegisterSlot(result, rax); |
5214 } | 5214 } |
5215 | 5215 |
5216 | 5216 |
5217 void LCodeGen::DoToFastProperties(LToFastProperties* instr) { | 5217 void LCodeGen::DoToFastProperties(LToFastProperties* instr) { |
5218 ASSERT(ToRegister(instr->value()).is(rax)); | 5218 ASSERT(ToRegister(instr->value()).is(rax)); |
5219 __ push(rax); | 5219 __ Push(rax); |
5220 CallRuntime(Runtime::kToFastProperties, 1, instr); | 5220 CallRuntime(Runtime::kToFastProperties, 1, instr); |
5221 } | 5221 } |
5222 | 5222 |
5223 | 5223 |
5224 void LCodeGen::DoRegExpLiteral(LRegExpLiteral* instr) { | 5224 void LCodeGen::DoRegExpLiteral(LRegExpLiteral* instr) { |
5225 ASSERT(ToRegister(instr->context()).is(rsi)); | 5225 ASSERT(ToRegister(instr->context()).is(rsi)); |
5226 Label materialized; | 5226 Label materialized; |
5227 // Registers will be used as follows: | 5227 // Registers will be used as follows: |
5228 // rcx = literals array. | 5228 // rcx = literals array. |
5229 // rbx = regexp literal. | 5229 // rbx = regexp literal. |
5230 // rax = regexp literal clone. | 5230 // rax = regexp literal clone. |
5231 int literal_offset = | 5231 int literal_offset = |
5232 FixedArray::OffsetOfElementAt(instr->hydrogen()->literal_index()); | 5232 FixedArray::OffsetOfElementAt(instr->hydrogen()->literal_index()); |
5233 __ Move(rcx, instr->hydrogen()->literals()); | 5233 __ Move(rcx, instr->hydrogen()->literals()); |
5234 __ movp(rbx, FieldOperand(rcx, literal_offset)); | 5234 __ movp(rbx, FieldOperand(rcx, literal_offset)); |
5235 __ CompareRoot(rbx, Heap::kUndefinedValueRootIndex); | 5235 __ CompareRoot(rbx, Heap::kUndefinedValueRootIndex); |
5236 __ j(not_equal, &materialized, Label::kNear); | 5236 __ j(not_equal, &materialized, Label::kNear); |
5237 | 5237 |
5238 // Create regexp literal using runtime function | 5238 // Create regexp literal using runtime function |
5239 // Result will be in rax. | 5239 // Result will be in rax. |
5240 __ push(rcx); | 5240 __ Push(rcx); |
5241 __ Push(Smi::FromInt(instr->hydrogen()->literal_index())); | 5241 __ Push(Smi::FromInt(instr->hydrogen()->literal_index())); |
5242 __ Push(instr->hydrogen()->pattern()); | 5242 __ Push(instr->hydrogen()->pattern()); |
5243 __ Push(instr->hydrogen()->flags()); | 5243 __ Push(instr->hydrogen()->flags()); |
5244 CallRuntime(Runtime::kMaterializeRegExpLiteral, 4, instr); | 5244 CallRuntime(Runtime::kMaterializeRegExpLiteral, 4, instr); |
5245 __ movp(rbx, rax); | 5245 __ movp(rbx, rax); |
5246 | 5246 |
5247 __ bind(&materialized); | 5247 __ bind(&materialized); |
5248 int size = JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kPointerSize; | 5248 int size = JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kPointerSize; |
5249 Label allocated, runtime_allocate; | 5249 Label allocated, runtime_allocate; |
5250 __ Allocate(size, rax, rcx, rdx, &runtime_allocate, TAG_OBJECT); | 5250 __ Allocate(size, rax, rcx, rdx, &runtime_allocate, TAG_OBJECT); |
5251 __ jmp(&allocated, Label::kNear); | 5251 __ jmp(&allocated, Label::kNear); |
5252 | 5252 |
5253 __ bind(&runtime_allocate); | 5253 __ bind(&runtime_allocate); |
5254 __ push(rbx); | 5254 __ Push(rbx); |
5255 __ Push(Smi::FromInt(size)); | 5255 __ Push(Smi::FromInt(size)); |
5256 CallRuntime(Runtime::kAllocateInNewSpace, 1, instr); | 5256 CallRuntime(Runtime::kAllocateInNewSpace, 1, instr); |
5257 __ pop(rbx); | 5257 __ Pop(rbx); |
5258 | 5258 |
5259 __ bind(&allocated); | 5259 __ bind(&allocated); |
5260 // Copy the content into the newly allocated memory. | 5260 // Copy the content into the newly allocated memory. |
5261 // (Unroll copy loop once for better throughput). | 5261 // (Unroll copy loop once for better throughput). |
5262 for (int i = 0; i < size - kPointerSize; i += 2 * kPointerSize) { | 5262 for (int i = 0; i < size - kPointerSize; i += 2 * kPointerSize) { |
5263 __ movp(rdx, FieldOperand(rbx, i)); | 5263 __ movp(rdx, FieldOperand(rbx, i)); |
5264 __ movp(rcx, FieldOperand(rbx, i + kPointerSize)); | 5264 __ movp(rcx, FieldOperand(rbx, i + kPointerSize)); |
5265 __ movp(FieldOperand(rax, i), rdx); | 5265 __ movp(FieldOperand(rax, i), rdx); |
5266 __ movp(FieldOperand(rax, i + kPointerSize), rcx); | 5266 __ movp(FieldOperand(rax, i + kPointerSize), rcx); |
5267 } | 5267 } |
5268 if ((size % (2 * kPointerSize)) != 0) { | 5268 if ((size % (2 * kPointerSize)) != 0) { |
5269 __ movp(rdx, FieldOperand(rbx, size - kPointerSize)); | 5269 __ movp(rdx, FieldOperand(rbx, size - kPointerSize)); |
5270 __ movp(FieldOperand(rax, size - kPointerSize), rdx); | 5270 __ movp(FieldOperand(rax, size - kPointerSize), rdx); |
5271 } | 5271 } |
5272 } | 5272 } |
5273 | 5273 |
5274 | 5274 |
5275 void LCodeGen::DoFunctionLiteral(LFunctionLiteral* instr) { | 5275 void LCodeGen::DoFunctionLiteral(LFunctionLiteral* instr) { |
5276 ASSERT(ToRegister(instr->context()).is(rsi)); | 5276 ASSERT(ToRegister(instr->context()).is(rsi)); |
5277 // Use the fast case closure allocation code that allocates in new | 5277 // Use the fast case closure allocation code that allocates in new |
5278 // space for nested functions that don't need literals cloning. | 5278 // space for nested functions that don't need literals cloning. |
5279 bool pretenure = instr->hydrogen()->pretenure(); | 5279 bool pretenure = instr->hydrogen()->pretenure(); |
5280 if (!pretenure && instr->hydrogen()->has_no_literals()) { | 5280 if (!pretenure && instr->hydrogen()->has_no_literals()) { |
5281 FastNewClosureStub stub(instr->hydrogen()->strict_mode(), | 5281 FastNewClosureStub stub(instr->hydrogen()->strict_mode(), |
5282 instr->hydrogen()->is_generator()); | 5282 instr->hydrogen()->is_generator()); |
5283 __ Move(rbx, instr->hydrogen()->shared_info()); | 5283 __ Move(rbx, instr->hydrogen()->shared_info()); |
5284 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | 5284 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); |
5285 } else { | 5285 } else { |
5286 __ push(rsi); | 5286 __ Push(rsi); |
5287 __ Push(instr->hydrogen()->shared_info()); | 5287 __ Push(instr->hydrogen()->shared_info()); |
5288 __ PushRoot(pretenure ? Heap::kTrueValueRootIndex : | 5288 __ PushRoot(pretenure ? Heap::kTrueValueRootIndex : |
5289 Heap::kFalseValueRootIndex); | 5289 Heap::kFalseValueRootIndex); |
5290 CallRuntime(Runtime::kNewClosure, 3, instr); | 5290 CallRuntime(Runtime::kNewClosure, 3, instr); |
5291 } | 5291 } |
5292 } | 5292 } |
5293 | 5293 |
5294 | 5294 |
5295 void LCodeGen::DoTypeof(LTypeof* instr) { | 5295 void LCodeGen::DoTypeof(LTypeof* instr) { |
5296 ASSERT(ToRegister(instr->context()).is(rsi)); | 5296 ASSERT(ToRegister(instr->context()).is(rsi)); |
5297 LOperand* input = instr->value(); | 5297 LOperand* input = instr->value(); |
5298 EmitPushTaggedOperand(input); | 5298 EmitPushTaggedOperand(input); |
5299 CallRuntime(Runtime::kTypeof, 1, instr); | 5299 CallRuntime(Runtime::kTypeof, 1, instr); |
5300 } | 5300 } |
5301 | 5301 |
5302 | 5302 |
5303 void LCodeGen::EmitPushTaggedOperand(LOperand* operand) { | 5303 void LCodeGen::EmitPushTaggedOperand(LOperand* operand) { |
5304 ASSERT(!operand->IsDoubleRegister()); | 5304 ASSERT(!operand->IsDoubleRegister()); |
5305 if (operand->IsConstantOperand()) { | 5305 if (operand->IsConstantOperand()) { |
5306 __ Push(ToHandle(LConstantOperand::cast(operand))); | 5306 __ Push(ToHandle(LConstantOperand::cast(operand))); |
5307 } else if (operand->IsRegister()) { | 5307 } else if (operand->IsRegister()) { |
5308 __ push(ToRegister(operand)); | 5308 __ Push(ToRegister(operand)); |
5309 } else { | 5309 } else { |
5310 __ push(ToOperand(operand)); | 5310 __ Push(ToOperand(operand)); |
5311 } | 5311 } |
5312 } | 5312 } |
5313 | 5313 |
5314 | 5314 |
5315 void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) { | 5315 void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) { |
5316 Register input = ToRegister(instr->value()); | 5316 Register input = ToRegister(instr->value()); |
5317 Condition final_branch_condition = EmitTypeofIs(instr, input); | 5317 Condition final_branch_condition = EmitTypeofIs(instr, input); |
5318 if (final_branch_condition != no_condition) { | 5318 if (final_branch_condition != no_condition) { |
5319 EmitBranch(instr, final_branch_condition); | 5319 EmitBranch(instr, final_branch_condition); |
5320 } | 5320 } |
(...skipping 252 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5573 DeoptimizeIf(below_equal, instr->environment()); | 5573 DeoptimizeIf(below_equal, instr->environment()); |
5574 | 5574 |
5575 Label use_cache, call_runtime; | 5575 Label use_cache, call_runtime; |
5576 __ CheckEnumCache(null_value, &call_runtime); | 5576 __ CheckEnumCache(null_value, &call_runtime); |
5577 | 5577 |
5578 __ movp(rax, FieldOperand(rax, HeapObject::kMapOffset)); | 5578 __ movp(rax, FieldOperand(rax, HeapObject::kMapOffset)); |
5579 __ jmp(&use_cache, Label::kNear); | 5579 __ jmp(&use_cache, Label::kNear); |
5580 | 5580 |
5581 // Get the set of properties to enumerate. | 5581 // Get the set of properties to enumerate. |
5582 __ bind(&call_runtime); | 5582 __ bind(&call_runtime); |
5583 __ push(rax); | 5583 __ Push(rax); |
5584 CallRuntime(Runtime::kGetPropertyNamesFast, 1, instr); | 5584 CallRuntime(Runtime::kGetPropertyNamesFast, 1, instr); |
5585 | 5585 |
5586 __ CompareRoot(FieldOperand(rax, HeapObject::kMapOffset), | 5586 __ CompareRoot(FieldOperand(rax, HeapObject::kMapOffset), |
5587 Heap::kMetaMapRootIndex); | 5587 Heap::kMetaMapRootIndex); |
5588 DeoptimizeIf(not_equal, instr->environment()); | 5588 DeoptimizeIf(not_equal, instr->environment()); |
5589 __ bind(&use_cache); | 5589 __ bind(&use_cache); |
5590 } | 5590 } |
5591 | 5591 |
5592 | 5592 |
5593 void LCodeGen::DoForInCacheArray(LForInCacheArray* instr) { | 5593 void LCodeGen::DoForInCacheArray(LForInCacheArray* instr) { |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5643 FixedArray::kHeaderSize - kPointerSize)); | 5643 FixedArray::kHeaderSize - kPointerSize)); |
5644 __ bind(&done); | 5644 __ bind(&done); |
5645 } | 5645 } |
5646 | 5646 |
5647 | 5647 |
5648 #undef __ | 5648 #undef __ |
5649 | 5649 |
5650 } } // namespace v8::internal | 5650 } } // namespace v8::internal |
5651 | 5651 |
5652 #endif // V8_TARGET_ARCH_X64 | 5652 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |