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