• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
CreateSqrtFunction(Isolate * isolate)18 UnaryMathFunctionWithIsolate CreateSqrtFunction(Isolate* isolate) {
19   return nullptr;
20 }
21 
22 
23 // -------------------------------------------------------------------------
24 // Platform-specific RuntimeCallHelper functions.
25 
BeforeCall(MacroAssembler * masm) const26 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 
AfterCall(MacroAssembler * masm) const33 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 
CodeAgingHelper(Isolate * isolate)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
IsOld(byte * candidate) const65 bool CodeAgingHelper::IsOld(byte* candidate) const {
66   return memcmp(candidate, old_sequence_.start(), kCodeAgeStubEntryOffset) == 0;
67 }
68 #endif
69 
70 
IsYoungSequence(Isolate * isolate,byte * sequence)71 bool Code::IsYoungSequence(Isolate* isolate, byte* sequence) {
72   return MacroAssembler::IsYoungSequence(isolate, sequence);
73 }
74 
GetCodeAge(Isolate * isolate,byte * sequence)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 
PatchPlatformCodeAge(Isolate * isolate,byte * sequence,Code::Age age)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 
Generate(MacroAssembler * masm,Register string,Register index,Register result,Label * call_runtime)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