LCOV - code coverage report
Current view: top level - src/x64 - codegen-x64.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 76 84 90.5 %
Date: 2017-04-26 Functions: 7 9 77.8 %

          Line data    Source code
       1             : // Copyright 2012 the V8 project authors. All rights reserved.
       2             : // Use of this source code is governed by a BSD-style license that can be
       3             : // found in the LICENSE file.
       4             : 
       5             : #include "src/x64/codegen-x64.h"
       6             : 
       7             : #if V8_TARGET_ARCH_X64
       8             : 
       9             : #include "src/codegen.h"
      10             : #include "src/macro-assembler.h"
      11             : #include "src/x64/assembler-x64-inl.h"
      12             : 
      13             : namespace v8 {
      14             : namespace internal {
      15             : 
      16             : // -------------------------------------------------------------------------
      17             : // Platform-specific RuntimeCallHelper functions.
      18             : 
      19           0 : void StubRuntimeCallHelper::BeforeCall(MacroAssembler* masm) const {
      20           0 :   masm->EnterFrame(StackFrame::INTERNAL);
      21             :   DCHECK(!masm->has_frame());
      22             :   masm->set_has_frame(true);
      23           0 : }
      24             : 
      25             : 
      26           0 : void StubRuntimeCallHelper::AfterCall(MacroAssembler* masm) const {
      27           0 :   masm->LeaveFrame(StackFrame::INTERNAL);
      28             :   DCHECK(masm->has_frame());
      29             :   masm->set_has_frame(false);
      30           0 : }
      31             : 
      32             : 
      33             : #define __ masm.
      34             : 
      35             : 
      36           2 : UnaryMathFunctionWithIsolate CreateSqrtFunction(Isolate* isolate) {
      37             :   size_t actual_size;
      38             :   // Allocate buffer in executable space.
      39             :   byte* buffer =
      40           2 :       static_cast<byte*>(base::OS::Allocate(1 * KB, &actual_size, true));
      41           2 :   if (buffer == nullptr) return nullptr;
      42             : 
      43             :   MacroAssembler masm(isolate, buffer, static_cast<int>(actual_size),
      44           2 :                       CodeObjectRequired::kNo);
      45             :   // xmm0: raw double input.
      46             :   // Move double input into registers.
      47           2 :   __ Sqrtsd(xmm0, xmm0);
      48           2 :   __ Ret();
      49             : 
      50             :   CodeDesc desc;
      51           2 :   masm.GetCode(&desc);
      52             :   DCHECK(!RelocInfo::RequiresRelocation(isolate, desc));
      53             : 
      54           2 :   Assembler::FlushICache(isolate, buffer, actual_size);
      55           2 :   base::OS::ProtectCode(buffer, actual_size);
      56             :   return FUNCTION_CAST<UnaryMathFunctionWithIsolate>(buffer);
      57             : }
      58             : 
      59             : #undef __
      60             : 
      61             : // -------------------------------------------------------------------------
      62             : // Code generators
      63             : 
      64             : #define __ ACCESS_MASM(masm)
      65             : 
      66         438 : void StringCharLoadGenerator::Generate(MacroAssembler* masm,
      67             :                                        Register string,
      68             :                                        Register index,
      69             :                                        Register result,
      70             :                                        Label* call_runtime) {
      71             :   Label indirect_string_loaded;
      72         438 :   __ bind(&indirect_string_loaded);
      73             : 
      74             :   // Fetch the instance type of the receiver into result register.
      75             :   __ movp(result, FieldOperand(string, HeapObject::kMapOffset));
      76             :   __ movzxbl(result, FieldOperand(result, Map::kInstanceTypeOffset));
      77             : 
      78             :   // We need special handling for indirect strings.
      79             :   Label check_sequential;
      80         438 :   __ testb(result, Immediate(kIsIndirectStringMask));
      81         438 :   __ j(zero, &check_sequential, Label::kNear);
      82             : 
      83             :   // Dispatch on the indirect string shape: slice or cons.
      84             :   Label cons_string, thin_string;
      85         438 :   __ andl(result, Immediate(kStringRepresentationMask));
      86         438 :   __ cmpl(result, Immediate(kConsStringTag));
      87         438 :   __ j(equal, &cons_string, Label::kNear);
      88         438 :   __ cmpl(result, Immediate(kThinStringTag));
      89         438 :   __ j(equal, &thin_string, Label::kNear);
      90             : 
      91             :   // Handle slices.
      92         438 :   __ SmiToInteger32(result, FieldOperand(string, SlicedString::kOffsetOffset));
      93         438 :   __ addp(index, result);
      94             :   __ movp(string, FieldOperand(string, SlicedString::kParentOffset));
      95         438 :   __ jmp(&indirect_string_loaded);
      96             : 
      97             :   // Handle thin strings.
      98         438 :   __ bind(&thin_string);
      99             :   __ movp(string, FieldOperand(string, ThinString::kActualOffset));
     100         438 :   __ jmp(&indirect_string_loaded);
     101             : 
     102             :   // Handle cons strings.
     103             :   // Check whether the right hand side is the empty string (i.e. if
     104             :   // this is really a flat string in a cons string). If that is not
     105             :   // the case we would rather go to the runtime system now to flatten
     106             :   // the string.
     107         438 :   __ bind(&cons_string);
     108             :   __ CompareRoot(FieldOperand(string, ConsString::kSecondOffset),
     109         438 :                  Heap::kempty_stringRootIndex);
     110         438 :   __ j(not_equal, call_runtime);
     111             :   __ movp(string, FieldOperand(string, ConsString::kFirstOffset));
     112         438 :   __ jmp(&indirect_string_loaded);
     113             : 
     114             :   // Distinguish sequential and external strings. Only these two string
     115             :   // representations can reach here (slices and flat cons strings have been
     116             :   // reduced to the underlying sequential or external string).
     117             :   Label seq_string;
     118         438 :   __ bind(&check_sequential);
     119             :   STATIC_ASSERT(kSeqStringTag == 0);
     120         438 :   __ testb(result, Immediate(kStringRepresentationMask));
     121         438 :   __ j(zero, &seq_string, Label::kNear);
     122             : 
     123             :   // Handle external strings.
     124             :   Label one_byte_external, done;
     125         438 :   if (FLAG_debug_code) {
     126             :     // Assert that we do not have a cons or slice (indirect strings) here.
     127             :     // Sequential strings have already been ruled out.
     128           0 :     __ testb(result, Immediate(kIsIndirectStringMask));
     129           0 :     __ Assert(zero, kExternalStringExpectedButNotFound);
     130             :   }
     131             :   // Rule out short external strings.
     132             :   STATIC_ASSERT(kShortExternalStringTag != 0);
     133         438 :   __ testb(result, Immediate(kShortExternalStringTag));
     134         438 :   __ j(not_zero, call_runtime);
     135             :   // Check encoding.
     136             :   STATIC_ASSERT(kTwoByteStringTag == 0);
     137         438 :   __ testb(result, Immediate(kStringEncodingMask));
     138             :   __ movp(result, FieldOperand(string, ExternalString::kResourceDataOffset));
     139         438 :   __ j(not_equal, &one_byte_external, Label::kNear);
     140             :   // Two-byte string.
     141         876 :   __ movzxwl(result, Operand(result, index, times_2, 0));
     142         438 :   __ jmp(&done, Label::kNear);
     143         438 :   __ bind(&one_byte_external);
     144             :   // One-byte string.
     145         876 :   __ movzxbl(result, Operand(result, index, times_1, 0));
     146         438 :   __ jmp(&done, Label::kNear);
     147             : 
     148             :   // Dispatch on the encoding: one-byte or two-byte.
     149             :   Label one_byte;
     150         438 :   __ bind(&seq_string);
     151             :   STATIC_ASSERT((kStringEncodingMask & kOneByteStringTag) != 0);
     152             :   STATIC_ASSERT((kStringEncodingMask & kTwoByteStringTag) == 0);
     153         438 :   __ testb(result, Immediate(kStringEncodingMask));
     154         438 :   __ j(not_zero, &one_byte, Label::kNear);
     155             : 
     156             :   // Two-byte string.
     157             :   // Load the two-byte character code into the result register.
     158             :   STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize == 1);
     159             :   __ movzxwl(result, FieldOperand(string,
     160             :                                   index,
     161             :                                   times_2,
     162             :                                   SeqTwoByteString::kHeaderSize));
     163         438 :   __ jmp(&done, Label::kNear);
     164             : 
     165             :   // One-byte string.
     166             :   // Load the byte into the result register.
     167         438 :   __ bind(&one_byte);
     168             :   __ movzxbl(result, FieldOperand(string,
     169             :                                   index,
     170             :                                   times_1,
     171             :                                   SeqOneByteString::kHeaderSize));
     172         438 :   __ bind(&done);
     173         438 : }
     174             : 
     175             : #undef __
     176             : 
     177             : 
     178       60782 : CodeAgingHelper::CodeAgingHelper(Isolate* isolate) {
     179             :   USE(isolate);
     180             :   DCHECK(young_sequence_.length() == kNoCodeAgeSequenceLength);
     181             :   // The sequence of instructions that is patched out for aging code is the
     182             :   // following boilerplate stack-building prologue that is found both in
     183             :   // FUNCTION and OPTIMIZED_FUNCTION code:
     184             :   CodePatcher patcher(isolate, young_sequence_.start(),
     185       60782 :                       young_sequence_.length());
     186       60782 :   patcher.masm()->pushq(rbp);
     187             :   patcher.masm()->movp(rbp, rsp);
     188       60782 :   patcher.masm()->Push(rsi);
     189       60782 :   patcher.masm()->Push(rdi);
     190       60782 : }
     191             : 
     192             : 
     193             : #ifdef DEBUG
     194             : bool CodeAgingHelper::IsOld(byte* candidate) const {
     195             :   return *candidate == kCallOpcode;
     196             : }
     197             : #endif
     198             : 
     199             : 
     200     6303174 : bool Code::IsYoungSequence(Isolate* isolate, byte* sequence) {
     201             :   bool result = isolate->code_aging_helper()->IsYoung(sequence);
     202             :   DCHECK(result || isolate->code_aging_helper()->IsOld(sequence));
     203     4487652 :   return result;
     204             : }
     205             : 
     206     1815522 : Code::Age Code::GetCodeAge(Isolate* isolate, byte* sequence) {
     207     1815522 :   if (IsYoungSequence(isolate, sequence)) return kNoAgeCodeAge;
     208             : 
     209      623965 :   sequence++;  // Skip the kCallOpcode byte
     210             :   Address target_address = sequence + *reinterpret_cast<int*>(sequence) +
     211      623965 :                            Assembler::kCallTargetAddressOffset;
     212      623965 :   Code* stub = GetCodeFromTargetAddress(target_address);
     213      623965 :   return GetAgeOfCodeAgeStub(stub);
     214             : }
     215             : 
     216     1667487 : void Code::PatchPlatformCodeAge(Isolate* isolate, byte* sequence,
     217             :                                 Code::Age age) {
     218             :   uint32_t young_length = isolate->code_aging_helper()->young_sequence_length();
     219     1667487 :   if (age == kNoAgeCodeAge) {
     220             :     isolate->code_aging_helper()->CopyYoungSequenceTo(sequence);
     221      656451 :     Assembler::FlushICache(isolate, sequence, young_length);
     222             :   } else {
     223     1011036 :     Code* stub = GetCodeAgeStub(isolate, age);
     224     1011036 :     CodePatcher patcher(isolate, sequence, young_length);
     225     1011036 :     patcher.masm()->call(stub->instruction_start());
     226             :     patcher.masm()->Nop(
     227     1011036 :         kNoCodeAgeSequenceLength - Assembler::kShortCallInstructionLength);
     228             :   }
     229     1667487 : }
     230             : 
     231             : 
     232       16138 : Operand StackArgumentsAccessor::GetArgumentOperand(int index) {
     233             :   DCHECK(index >= 0);
     234       16138 :   int receiver = (receiver_mode_ == ARGUMENTS_CONTAIN_RECEIVER) ? 1 : 0;
     235             :   int displacement_to_last_argument = base_reg_.is(rsp) ?
     236       16138 :       kPCOnStackSize : kFPOnStackSize + kPCOnStackSize;
     237       16138 :   displacement_to_last_argument += extra_displacement_to_last_argument_;
     238       16138 :   if (argument_count_reg_.is(no_reg)) {
     239             :     // argument[0] is at base_reg_ + displacement_to_last_argument +
     240             :     // (argument_count_immediate_ + receiver - 1) * kPointerSize.
     241             :     DCHECK(argument_count_immediate_ + receiver > 0);
     242             :     return Operand(base_reg_, displacement_to_last_argument +
     243       13958 :         (argument_count_immediate_ + receiver - 1 - index) * kPointerSize);
     244             :   } else {
     245             :     // argument[0] is at base_reg_ + displacement_to_last_argument +
     246             :     // argument_count_reg_ * times_pointer_size + (receiver - 1) * kPointerSize.
     247             :     return Operand(base_reg_, argument_count_reg_, times_pointer_size,
     248        2180 :         displacement_to_last_argument + (receiver - 1 - index) * kPointerSize);
     249             :   }
     250             : }
     251             : 
     252             : 
     253             : }  // namespace internal
     254             : }  // namespace v8
     255             : 
     256             : #endif  // V8_TARGET_ARCH_X64

Generated by: LCOV version 1.10