Home | History | Annotate | Download | only in arm64
      1 // Copyright 2013 the V8 project authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "src/arm64/codegen-arm64.h"
      6 
      7 #if V8_TARGET_ARCH_ARM64
      8 
      9 #include "src/arm64/simulator-arm64.h"
     10 #include "src/codegen.h"
     11 #include "src/macro-assembler.h"
     12 
     13 namespace v8 {
     14 namespace internal {
     15 
     16 #define __ ACCESS_MASM(masm)
     17 
     18 UnaryMathFunctionWithIsolate CreateSqrtFunction(Isolate* isolate) {
     19   return nullptr;
     20 }
     21 
     22 
     23 // -------------------------------------------------------------------------
     24 // Platform-specific RuntimeCallHelper functions.
     25 
     26 void StubRuntimeCallHelper::BeforeCall(MacroAssembler* masm) const {
     27   masm->EnterFrame(StackFrame::INTERNAL);
     28   DCHECK(!masm->has_frame());
     29   masm->set_has_frame(true);
     30 }
     31 
     32 
     33 void StubRuntimeCallHelper::AfterCall(MacroAssembler* masm) const {
     34   masm->LeaveFrame(StackFrame::INTERNAL);
     35   DCHECK(masm->has_frame());
     36   masm->set_has_frame(false);
     37 }
     38 
     39 
     40 // -------------------------------------------------------------------------
     41 // Code generators
     42 
     43 CodeAgingHelper::CodeAgingHelper(Isolate* isolate) {
     44   USE(isolate);
     45   DCHECK(young_sequence_.length() == kNoCodeAgeSequenceLength);
     46   // The sequence of instructions that is patched out for aging code is the
     47   // following boilerplate stack-building prologue that is found both in
     48   // FUNCTION and OPTIMIZED_FUNCTION code:
     49   PatchingAssembler patcher(isolate, young_sequence_.start(),
     50                             young_sequence_.length() / kInstructionSize);
     51   // The young sequence is the frame setup code for FUNCTION code types. It is
     52   // generated by FullCodeGenerator::Generate.
     53   MacroAssembler::EmitFrameSetupForCodeAgePatching(&patcher);
     54 
     55 #ifdef DEBUG
     56   const int length = kCodeAgeStubEntryOffset / kInstructionSize;
     57   DCHECK(old_sequence_.length() >= kCodeAgeStubEntryOffset);
     58   PatchingAssembler patcher_old(isolate, old_sequence_.start(), length);
     59   MacroAssembler::EmitCodeAgeSequence(&patcher_old, NULL);
     60 #endif
     61 }
     62 
     63 
     64 #ifdef DEBUG
     65 bool CodeAgingHelper::IsOld(byte* candidate) const {
     66   return memcmp(candidate, old_sequence_.start(), kCodeAgeStubEntryOffset) == 0;
     67 }
     68 #endif
     69 
     70 
     71 bool Code::IsYoungSequence(Isolate* isolate, byte* sequence) {
     72   return MacroAssembler::IsYoungSequence(isolate, sequence);
     73 }
     74 
     75 Code::Age Code::GetCodeAge(Isolate* isolate, byte* sequence) {
     76   if (IsYoungSequence(isolate, sequence)) return kNoAgeCodeAge;
     77 
     78   byte* target = sequence + kCodeAgeStubEntryOffset;
     79   Code* stub = GetCodeFromTargetAddress(Memory::Address_at(target));
     80   return GetAgeOfCodeAgeStub(stub);
     81 }
     82 
     83 void Code::PatchPlatformCodeAge(Isolate* isolate, byte* sequence,
     84                                 Code::Age age) {
     85   PatchingAssembler patcher(isolate, sequence,
     86                             kNoCodeAgeSequenceLength / kInstructionSize);
     87   if (age == kNoAgeCodeAge) {
     88     MacroAssembler::EmitFrameSetupForCodeAgePatching(&patcher);
     89   } else {
     90     Code* stub = GetCodeAgeStub(isolate, age);
     91     MacroAssembler::EmitCodeAgeSequence(&patcher, stub);
     92   }
     93 }
     94 
     95 
     96 void StringCharLoadGenerator::Generate(MacroAssembler* masm,
     97                                        Register string,
     98                                        Register index,
     99                                        Register result,
    100                                        Label* call_runtime) {
    101   DCHECK(string.Is64Bits() && index.Is32Bits() && result.Is64Bits());
    102   Label indirect_string_loaded;
    103   __ Bind(&indirect_string_loaded);
    104 
    105   // Fetch the instance type of the receiver into result register.
    106   __ Ldr(result, FieldMemOperand(string, HeapObject::kMapOffset));
    107   __ Ldrb(result, FieldMemOperand(result, Map::kInstanceTypeOffset));
    108 
    109   // We need special handling for indirect strings.
    110   Label check_sequential;
    111   __ TestAndBranchIfAllClear(result, kIsIndirectStringMask, &check_sequential);
    112 
    113   // Dispatch on the indirect string shape: slice or cons.
    114   Label cons_string, thin_string;
    115   __ And(result, result, kStringRepresentationMask);
    116   __ Cmp(result, kConsStringTag);
    117   __ B(eq, &cons_string);
    118   __ Cmp(result, kThinStringTag);
    119   __ B(eq, &thin_string);
    120 
    121   // Handle slices.
    122   __ Ldr(result.W(),
    123          UntagSmiFieldMemOperand(string, SlicedString::kOffsetOffset));
    124   __ Ldr(string, FieldMemOperand(string, SlicedString::kParentOffset));
    125   __ Add(index, index, result.W());
    126   __ B(&indirect_string_loaded);
    127 
    128   // Handle thin strings.
    129   __ Bind(&thin_string);
    130   __ Ldr(string, FieldMemOperand(string, ThinString::kActualOffset));
    131   __ B(&indirect_string_loaded);
    132 
    133   // Handle cons strings.
    134   // Check whether the right hand side is the empty string (i.e. if
    135   // this is really a flat string in a cons string). If that is not
    136   // the case we would rather go to the runtime system now to flatten
    137   // the string.
    138   __ Bind(&cons_string);
    139   __ Ldr(result, FieldMemOperand(string, ConsString::kSecondOffset));
    140   __ JumpIfNotRoot(result, Heap::kempty_stringRootIndex, call_runtime);
    141   // Get the first of the two strings and load its instance type.
    142   __ Ldr(string, FieldMemOperand(string, ConsString::kFirstOffset));
    143   __ B(&indirect_string_loaded);
    144 
    145   // Distinguish sequential and external strings. Only these two string
    146   // representations can reach here (slices and flat cons strings have been
    147   // reduced to the underlying sequential or external string).
    148   Label external_string, check_encoding;
    149   __ Bind(&check_sequential);
    150   STATIC_ASSERT(kSeqStringTag == 0);
    151   __ TestAndBranchIfAnySet(result, kStringRepresentationMask, &external_string);
    152 
    153   // Prepare sequential strings
    154   STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize);
    155   __ Add(string, string, SeqTwoByteString::kHeaderSize - kHeapObjectTag);
    156   __ B(&check_encoding);
    157 
    158   // Handle external strings.
    159   __ Bind(&external_string);
    160   if (FLAG_debug_code) {
    161     // Assert that we do not have a cons or slice (indirect strings) here.
    162     // Sequential strings have already been ruled out.
    163     __ Tst(result, kIsIndirectStringMask);
    164     __ Assert(eq, kExternalStringExpectedButNotFound);
    165   }
    166   // Rule out short external strings.
    167   STATIC_ASSERT(kShortExternalStringTag != 0);
    168   // TestAndBranchIfAnySet can emit Tbnz. Do not use it because call_runtime
    169   // can be bound far away in deferred code.
    170   __ Tst(result, kShortExternalStringMask);
    171   __ B(ne, call_runtime);
    172   __ Ldr(string, FieldMemOperand(string, ExternalString::kResourceDataOffset));
    173 
    174   Label one_byte, done;
    175   __ Bind(&check_encoding);
    176   STATIC_ASSERT(kTwoByteStringTag == 0);
    177   __ TestAndBranchIfAnySet(result, kStringEncodingMask, &one_byte);
    178   // Two-byte string.
    179   __ Ldrh(result, MemOperand(string, index, SXTW, 1));
    180   __ B(&done);
    181   __ Bind(&one_byte);
    182   // One-byte string.
    183   __ Ldrb(result, MemOperand(string, index, SXTW));
    184   __ Bind(&done);
    185 }
    186 
    187 #undef __
    188 
    189 }  // namespace internal
    190 }  // namespace v8
    191 
    192 #endif  // V8_TARGET_ARCH_ARM64
    193