Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(143)

Side by Side Diff: runtime/vm/assembler_x64.cc

Issue 22825023: Uses an object pool on x64 (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "vm/globals.h" 5 #include "vm/globals.h"
6 #if defined(TARGET_ARCH_X64) 6 #if defined(TARGET_ARCH_X64)
7 7
8 #include "vm/assembler.h" 8 #include "vm/assembler.h"
9 #include "vm/heap.h" 9 #include "vm/heap.h"
10 #include "vm/memory_region.h" 10 #include "vm/memory_region.h"
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
58 reinterpret_cast<DetectCPUFeatures>(instructions.EntryPoint())(); 58 reinterpret_cast<DetectCPUFeatures>(instructions.EntryPoint())();
59 sse4_1_supported_ = (features & kSSE4_1BitMask) != 0; 59 sse4_1_supported_ = (features & kSSE4_1BitMask) != 0;
60 #ifdef DEBUG 60 #ifdef DEBUG
61 initialized_ = true; 61 initialized_ = true;
62 #endif 62 #endif
63 } 63 }
64 64
65 #undef __ 65 #undef __
66 66
67 67
68 Assembler::Assembler(bool use_far_branches)
69 : buffer_(),
70 object_pool_(GrowableObjectArray::Handle()),
71 prologue_offset_(-1),
72 comments_() {
73 // Far branching mode is only needed and implemented for MIPS and ARM.
74 ASSERT(!use_far_branches);
75 if (Isolate::Current() != Dart::vm_isolate()) {
76 object_pool_ = GrowableObjectArray::New(Heap::kOld);
77
78 // These objects and labels need to be accessible through every pool-pointer
79 // at the same index.
80 object_pool_.Add(Object::Handle(Object::null()), Heap::kOld);
81 object_pool_.Add(Bool::True(), Heap::kOld);
82 object_pool_.Add(Bool::False(), Heap::kOld);
83
84 if (StubCode::UpdateStoreBuffer_entry() != NULL) {
85 AddExternalLabel(&StubCode::UpdateStoreBufferLabel(), kNotPatchable);
86 } else {
87 object_pool_.Add(Object::Handle(Object::null()), Heap::kOld);
88 }
89
90 if (StubCode::CallToRuntime_entry() != NULL) {
91 AddExternalLabel(&StubCode::CallToRuntimeLabel(), kNotPatchable);
92 } else {
93 object_pool_.Add(Object::Handle(Object::null()), Heap::kOld);
94 }
95 }
96 }
97
98
68 void Assembler::InitializeMemoryWithBreakpoints(uword data, int length) { 99 void Assembler::InitializeMemoryWithBreakpoints(uword data, int length) {
69 memset(reinterpret_cast<void*>(data), Instr::kBreakPointInstruction, length); 100 memset(reinterpret_cast<void*>(data), Instr::kBreakPointInstruction, length);
70 } 101 }
71 102
72 103
73 void Assembler::call(Register reg) { 104 void Assembler::call(Register reg) {
74 AssemblerBuffer::EnsureCapacity ensured(&buffer_); 105 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
75 Operand operand(reg); 106 Operand operand(reg);
76 EmitOperandREX(2, operand, REX_NONE); 107 EmitOperandREX(2, operand, REX_NONE);
77 EmitUint8(0xFF); 108 EmitUint8(0xFF);
(...skipping 10 matching lines...) Expand all
88 119
89 120
90 void Assembler::call(Label* label) { 121 void Assembler::call(Label* label) {
91 AssemblerBuffer::EnsureCapacity ensured(&buffer_); 122 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
92 static const int kSize = 5; 123 static const int kSize = 5;
93 EmitUint8(0xE8); 124 EmitUint8(0xE8);
94 EmitLabel(label, kSize); 125 EmitLabel(label, kSize);
95 } 126 }
96 127
97 128
129 void Assembler::LoadExternalLabel(const ExternalLabel* label,
130 Patchability patchable,
131 Register pp) {
132 const int32_t offset =
133 Array::element_offset(AddExternalLabel(label, patchable));
134 LoadWordFromPoolOffset(TMP, pp, offset - kHeapObjectTag, patchable);
135 }
136
137
98 void Assembler::call(const ExternalLabel* label) { 138 void Assembler::call(const ExternalLabel* label) {
99 AssemblerBuffer::EnsureCapacity ensured(&buffer_); 139 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
100 intptr_t call_start = buffer_.GetPosition();
101 140
102 // Encode movq(TMP, Immediate(label->address())), but always as imm64. 141 // Encode movq(TMP, Immediate(label->address())), but always as imm64.
103 EmitRegisterREX(TMP, REX_W); 142 EmitRegisterREX(TMP, REX_W);
104 EmitUint8(0xB8 | (TMP & 7)); 143 EmitUint8(0xB8 | (TMP & 7));
105 EmitInt64(label->address()); 144 EmitInt64(label->address());
106 145
107 // Encode call(TMP). 146 // Encode call(TMP).
108 Operand operand(TMP); 147 Operand operand(TMP);
109 EmitOperandREX(2, operand, REX_NONE); 148 EmitOperandREX(2, operand, REX_NONE);
110 EmitUint8(0xFF); 149 EmitUint8(0xFF);
111 EmitOperand(2, operand); 150 EmitOperand(2, operand);
151 }
112 152
153
154 void Assembler::CallPatchable(const ExternalLabel* label) {
155 intptr_t call_start = buffer_.GetPosition();
156 LoadExternalLabel(label);
157 {
158 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
159 // Encode call(TMP).
160 Operand operand(TMP);
161 EmitOperandREX(2, operand, REX_NONE);
162 EmitUint8(0xFF);
163 EmitOperand(2, operand);
164 }
113 ASSERT((buffer_.GetPosition() - call_start) == kCallExternalLabelSize); 165 ASSERT((buffer_.GetPosition() - call_start) == kCallExternalLabelSize);
114 } 166 }
115 167
116 168
169 void Assembler::CallFromPool(const ExternalLabel* label) {
170 if (Isolate::Current() == Dart::vm_isolate()) {
171 call(label);
172 } else {
173 LoadExternalLabel(label, kNotPatchable);
Florian Schneider 2013/09/04 09:39:47 This assumes LoadExternalLabel stores into TMP. Wh
zra 2013/09/04 21:00:41 Done.
174 {
175 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
176 // Encode call(TMP).
177 Operand operand(TMP);
178 EmitOperandREX(2, operand, REX_NONE);
179 EmitUint8(0xFF);
180 EmitOperand(2, operand);
181 }
182 }
183 }
184
185
117 void Assembler::pushq(Register reg) { 186 void Assembler::pushq(Register reg) {
118 AssemblerBuffer::EnsureCapacity ensured(&buffer_); 187 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
119 EmitRegisterREX(reg, REX_NONE); 188 EmitRegisterREX(reg, REX_NONE);
120 EmitUint8(0x50 | (reg & 7)); 189 EmitUint8(0x50 | (reg & 7));
121 } 190 }
122 191
123 192
124 void Assembler::pushq(const Address& address) { 193 void Assembler::pushq(const Address& address) {
125 AssemblerBuffer::EnsureCapacity ensured(&buffer_); 194 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
126 EmitOperandREX(6, address, REX_NONE); 195 EmitOperandREX(6, address, REX_NONE);
(...skipping 1826 matching lines...) Expand 10 before | Expand all | Expand 10 after
1953 2022
1954 2023
1955 void Assembler::j(Condition condition, const ExternalLabel* label) { 2024 void Assembler::j(Condition condition, const ExternalLabel* label) {
1956 Label no_jump; 2025 Label no_jump;
1957 j(static_cast<Condition>(condition ^ 1), &no_jump); // Negate condition. 2026 j(static_cast<Condition>(condition ^ 1), &no_jump); // Negate condition.
1958 jmp(label); 2027 jmp(label);
1959 Bind(&no_jump); 2028 Bind(&no_jump);
1960 } 2029 }
1961 2030
1962 2031
2032 void Assembler::JumpFromPool(Condition condition, const ExternalLabel* label,
2033 Register pp) {
2034 Label no_jump;
2035 j(static_cast<Condition>(condition ^ 1), &no_jump); // Negate condition.
2036 JumpFromPool(label, pp);
2037 Bind(&no_jump);
2038 }
2039
2040
1963 void Assembler::jmp(Register reg) { 2041 void Assembler::jmp(Register reg) {
1964 AssemblerBuffer::EnsureCapacity ensured(&buffer_); 2042 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
1965 Operand operand(reg); 2043 Operand operand(reg);
1966 EmitOperandREX(4, operand, REX_NONE); 2044 EmitOperandREX(4, operand, REX_NONE);
1967 EmitUint8(0xFF); 2045 EmitUint8(0xFF);
1968 EmitOperand(4, operand); 2046 EmitOperand(4, operand);
1969 } 2047 }
1970 2048
1971 2049
1972 void Assembler::jmp(Label* label, bool near) { 2050 void Assembler::jmp(Label* label, bool near) {
(...skipping 15 matching lines...) Expand all
1988 EmitNearLabelLink(label); 2066 EmitNearLabelLink(label);
1989 } else { 2067 } else {
1990 EmitUint8(0xE9); 2068 EmitUint8(0xE9);
1991 EmitLabelLink(label); 2069 EmitLabelLink(label);
1992 } 2070 }
1993 } 2071 }
1994 2072
1995 2073
1996 void Assembler::jmp(const ExternalLabel* label) { 2074 void Assembler::jmp(const ExternalLabel* label) {
1997 AssemblerBuffer::EnsureCapacity ensured(&buffer_); 2075 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
1998 intptr_t call_start = buffer_.GetPosition();
1999 2076
2000 // Encode movq(TMP, Immediate(label->address())), but always as imm64. 2077 // Encode movq(TMP, Immediate(label->address())), but always as imm64.
2001 EmitRegisterREX(TMP, REX_W); 2078 EmitRegisterREX(TMP, REX_W);
2002 EmitUint8(0xB8 | (TMP & 7)); 2079 EmitUint8(0xB8 | (TMP & 7));
2003 EmitInt64(label->address()); 2080 EmitInt64(label->address());
2004 2081
2005 // Encode jmp(TMP). 2082 // Encode jmp(TMP).
2006 Operand operand(TMP); 2083 Operand operand(TMP);
2007 EmitOperandREX(4, operand, REX_NONE); 2084 EmitOperandREX(4, operand, REX_NONE);
2008 EmitUint8(0xFF); 2085 EmitUint8(0xFF);
2009 EmitOperand(4, operand); 2086 EmitOperand(4, operand);
2087 }
2010 2088
2089
2090 void Assembler::JumpPatchable(const ExternalLabel* label, Register pp) {
2091 intptr_t call_start = buffer_.GetPosition();
2092 LoadExternalLabel(label, kPatchable, pp);
2093 {
2094 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
2095 // Encode jmp(TMP).
2096 Operand operand(TMP);
2097 EmitOperandREX(4, operand, REX_NONE);
2098 EmitUint8(0xFF);
2099 EmitOperand(4, operand);
2100 }
2011 ASSERT((buffer_.GetPosition() - call_start) == kCallExternalLabelSize); 2101 ASSERT((buffer_.GetPosition() - call_start) == kCallExternalLabelSize);
2012 } 2102 }
2013 2103
2014 2104
2105 void Assembler::JumpFromPool(const ExternalLabel* label, Register pp) {
2106 LoadExternalLabel(label, kNotPatchable, pp);
2107 {
2108 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
2109 // Encode jmp(TMP).
2110 Operand operand(TMP);
2111 EmitOperandREX(4, operand, REX_NONE);
2112 EmitUint8(0xFF);
2113 EmitOperand(4, operand);
2114 }
2115 }
2116
2117
2015 void Assembler::lock() { 2118 void Assembler::lock() {
2016 AssemblerBuffer::EnsureCapacity ensured(&buffer_); 2119 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
2017 EmitUint8(0xF0); 2120 EmitUint8(0xF0);
2018 } 2121 }
2019 2122
2020 2123
2021 void Assembler::cmpxchgl(const Address& address, Register reg) { 2124 void Assembler::cmpxchgl(const Address& address, Register reg) {
2022 AssemblerBuffer::EnsureCapacity ensured(&buffer_); 2125 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
2023 EmitOperandREX(reg, address, REX_NONE); 2126 EmitOperandREX(reg, address, REX_NONE);
2024 EmitUint8(0x0F); 2127 EmitUint8(0x0F);
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
2084 if (stack_elements <= 4) { 2187 if (stack_elements <= 4) {
2085 for (intptr_t i = 0; i < stack_elements; i++) { 2188 for (intptr_t i = 0; i < stack_elements; i++) {
2086 popq(TMP); 2189 popq(TMP);
2087 } 2190 }
2088 return; 2191 return;
2089 } 2192 }
2090 addq(RSP, Immediate(stack_elements * kWordSize)); 2193 addq(RSP, Immediate(stack_elements * kWordSize));
2091 } 2194 }
2092 2195
2093 2196
2094 void Assembler::LoadObject(Register dst, const Object& object) { 2197 int32_t Assembler::AddObject(const Object& obj) {
2095 if (object.IsSmi() || object.InVMHeap()) { 2198 // The object pool cannot be used in the vm isolate.
2199 ASSERT(Isolate::Current() != Dart::vm_isolate());
2200 ASSERT(obj.IsNotTemporaryScopedHandle());
2201 ASSERT(obj.IsOld());
2202 if (object_pool_.IsNull()) {
2203 object_pool_ = GrowableObjectArray::New(Heap::kOld);
2204 }
2205 for (int i = 0; i < object_pool_.Length(); i++) {
2206 if (object_pool_.At(i) == obj.raw()) {
2207 return i;
2208 }
2209 }
2210 object_pool_.Add(obj, Heap::kOld);
2211 return object_pool_.Length() - 1;
2212 }
2213
2214
2215 int32_t Assembler::AddExternalLabel(const ExternalLabel* label,
2216 Patchability patchable) {
2217 // The object pool cannot be used in the vm isolate.
2218 ASSERT(Isolate::Current() != Dart::vm_isolate());
2219 if (object_pool_.IsNull()) {
2220 object_pool_ = GrowableObjectArray::New(Heap::kOld);
2221 }
2222 const word address = label->address();
2223 ASSERT(Utils::IsAligned(address, 4));
2224 // The address is stored in the object array as a RawSmi.
2225 const Smi& smi = Smi::Handle(Smi::New(address >> kSmiTagShift));
2226 if (patchable == kNotPatchable) {
2227 // An external label used in a non-patchable call shouldn't also be used in
2228 // patchable calls. So, we can re-use existing entries for non-patchable
2229 // calls.
2230 for (int i = 0; i < object_pool_.Length(); i++) {
2231 if (object_pool_.At(i) == smi.raw()) {
2232 return i;
2233 }
2234 }
2235 }
2236 // If the call is patchable, do not reuse an existing entry since each
2237 // reference may be patched independently.
2238 object_pool_.Add(smi, Heap::kOld);
2239 return object_pool_.Length() - 1;
2240 }
2241
2242
2243 bool Assembler::CanLoadFromObjectPool(const Object& object) {
2244 return !object.IsSmi() && // Not a Smi
2245 // Not in the VMHeap, OR is one of the VMHeap objects we put in every
2246 // object pool.
2247 (!object.InVMHeap() || (object.raw() == Object::null()) ||
2248 (object.raw() == Bool::True().raw()) ||
2249 (object.raw() == Bool::False().raw())) &&
2250 object.IsNotTemporaryScopedHandle() &&
2251 object.IsOld();
2252 }
2253
2254
2255 void Assembler::LoadWordFromPoolOffset(Register dst, Register pp,
2256 int32_t offset, Patchability patchable) {
2257 movq(dst, Address(pp, offset));
2258 // This sequence must be of fixed size. If offset fits in a signed byte we
2259 // have to pad with nops.
2260 if (Utils::IsInt(8, offset) && (patchable == kPatchable)) {
Florian Schneider 2013/09/04 09:39:47 In the case that patching is allowed, why not gene
zra 2013/09/04 21:00:41 I'm afraid I don't see a straightforward way of do
srdjan 2013/09/04 22:57:23 I am with Florian here, it would simplify the code
zra 2013/09/05 00:23:11 Added a constructor to Address to generate a fixed
2261 nop(3);
2262 }
2263 }
2264
2265
2266 void Assembler::LoadObject(Register dst, const Object& object,
Florian Schneider 2013/09/04 09:39:47 I find it too invasive to specify kPatchable/kNotP
zra 2013/09/04 21:00:41 I've used a different function. See above comment
2267 Patchability patchable, Register pp) {
2268 if (CanLoadFromObjectPool(object)) {
2269 const int32_t offset = Array::element_offset(AddObject(object));
2270 LoadWordFromPoolOffset(dst, pp, offset - kHeapObjectTag, patchable);
2271 } else {
2096 movq(dst, Immediate(reinterpret_cast<int64_t>(object.raw()))); 2272 movq(dst, Immediate(reinterpret_cast<int64_t>(object.raw())));
2097 } else {
2098 ASSERT(object.IsNotTemporaryScopedHandle());
2099 ASSERT(object.IsOld());
2100 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
2101 EmitRegisterREX(dst, REX_W);
2102 EmitUint8(0xB8 | (dst & 7));
2103 buffer_.EmitObject(object);
2104 } 2273 }
2105 } 2274 }
2106 2275
2107 2276
2108 void Assembler::StoreObject(const Address& dst, const Object& object) { 2277 void Assembler::StoreObject(const Address& dst, const Object& object) {
2109 if (object.IsSmi() || object.InVMHeap()) { 2278 if (CanLoadFromObjectPool(object)) {
2279 LoadObject(TMP, object, kNotPatchable);
2280 movq(dst, TMP);
2281 } else {
2110 movq(dst, Immediate(reinterpret_cast<int64_t>(object.raw()))); 2282 movq(dst, Immediate(reinterpret_cast<int64_t>(object.raw())));
2111 } else {
2112 ASSERT(object.IsNotTemporaryScopedHandle());
2113 ASSERT(object.IsOld());
2114 LoadObject(TMP, object);
2115 movq(dst, TMP);
2116 } 2283 }
2117 } 2284 }
2118 2285
2119 2286
2120 void Assembler::PushObject(const Object& object) { 2287 void Assembler::PushObject(const Object& object) {
2121 if (object.IsSmi() || object.InVMHeap()) { 2288 if (CanLoadFromObjectPool(object)) {
2289 LoadObject(TMP, object, kNotPatchable);
2290 pushq(TMP);
2291 } else {
2122 pushq(Immediate(reinterpret_cast<int64_t>(object.raw()))); 2292 pushq(Immediate(reinterpret_cast<int64_t>(object.raw())));
2123 } else {
2124 LoadObject(TMP, object);
2125 pushq(TMP);
2126 } 2293 }
2127 } 2294 }
2128 2295
2129 2296
2130 void Assembler::CompareObject(Register reg, const Object& object) { 2297 void Assembler::CompareObject(Register reg, const Object& object) {
2131 if (object.IsSmi() || object.InVMHeap()) { 2298 if (CanLoadFromObjectPool(object)) {
2299 ASSERT(reg != TMP);
2300 LoadObject(TMP, object, kNotPatchable);
2301 cmpq(reg, TMP);
2302 } else {
2132 cmpq(reg, Immediate(reinterpret_cast<int64_t>(object.raw()))); 2303 cmpq(reg, Immediate(reinterpret_cast<int64_t>(object.raw())));
2133 } else {
2134 ASSERT(reg != TMP);
2135 LoadObject(TMP, object);
2136 cmpq(reg, TMP);
2137 } 2304 }
2138 } 2305 }
2139 2306
2140 2307
2141 // Destroys the value register. 2308 // Destroys the value register.
2142 void Assembler::StoreIntoObjectFilterNoSmi(Register object, 2309 void Assembler::StoreIntoObjectFilterNoSmi(Register object,
2143 Register value, 2310 Register value,
2144 Label* no_update) { 2311 Label* no_update) {
2145 COMPILE_ASSERT((kNewObjectAlignmentOffset == kWordSize) && 2312 COMPILE_ASSERT((kNewObjectAlignmentOffset == kWordSize) &&
2146 (kOldObjectAlignmentOffset == 0), young_alignment); 2313 (kOldObjectAlignmentOffset == 0), young_alignment);
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
2189 if (can_value_be_smi) { 2356 if (can_value_be_smi) {
2190 StoreIntoObjectFilter(object, value, &done); 2357 StoreIntoObjectFilter(object, value, &done);
2191 } else { 2358 } else {
2192 StoreIntoObjectFilterNoSmi(object, value, &done); 2359 StoreIntoObjectFilterNoSmi(object, value, &done);
2193 } 2360 }
2194 // A store buffer update is required. 2361 // A store buffer update is required.
2195 if (value != RAX) pushq(RAX); 2362 if (value != RAX) pushq(RAX);
2196 if (object != RAX) { 2363 if (object != RAX) {
2197 movq(RAX, object); 2364 movq(RAX, object);
2198 } 2365 }
2199 call(&StubCode::UpdateStoreBufferLabel()); 2366 CallFromPool(&StubCode::UpdateStoreBufferLabel());
2200 if (value != RAX) popq(RAX); 2367 if (value != RAX) popq(RAX);
2201 Bind(&done); 2368 Bind(&done);
2202 } 2369 }
2203 2370
2204 2371
2205 void Assembler::StoreIntoObjectNoBarrier(Register object, 2372 void Assembler::StoreIntoObjectNoBarrier(Register object,
2206 const Address& dest, 2373 const Address& dest,
2207 Register value) { 2374 Register value) {
2208 movq(dest, value); 2375 movq(dest, value);
2209 #if defined(DEBUG) 2376 #if defined(DEBUG)
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
2285 } 2452 }
2286 pushq(RBP); 2453 pushq(RBP);
2287 movq(RBP, RSP); 2454 movq(RBP, RSP);
2288 if (frame_size != 0) { 2455 if (frame_size != 0) {
2289 Immediate frame_space(frame_size); 2456 Immediate frame_space(frame_size);
2290 subq(RSP, frame_space); 2457 subq(RSP, frame_space);
2291 } 2458 }
2292 } 2459 }
2293 2460
2294 2461
2295 void Assembler::LeaveFrame() { 2462 void Assembler::LeaveFrame(bool restore_pp) {
2463 if (restore_pp) {
2464 movq(PP, Address(RBP, -2 * kWordSize));
2465 }
2296 movq(RSP, RBP); 2466 movq(RSP, RBP);
2297 popq(RBP); 2467 popq(RBP);
2298 } 2468 }
2299 2469
2300 2470
2301 void Assembler::ReserveAlignedFrameSpace(intptr_t frame_space) { 2471 void Assembler::ReserveAlignedFrameSpace(intptr_t frame_space) {
2302 // Reserve space for arguments and align frame before entering 2472 // Reserve space for arguments and align frame before entering
2303 // the C++ world. 2473 // the C++ world.
2304 AddImmediate(RSP, Immediate(-frame_space)); 2474 AddImmediate(RSP, Immediate(-frame_space));
2305 if (OS::ActivationFrameAlignment() > 0) { 2475 if (OS::ActivationFrameAlignment() > 0) {
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
2370 2540
2371 leave(); 2541 leave();
2372 } 2542 }
2373 2543
2374 2544
2375 void Assembler::CallRuntime(const RuntimeEntry& entry) { 2545 void Assembler::CallRuntime(const RuntimeEntry& entry) {
2376 entry.Call(this); 2546 entry.Call(this);
2377 } 2547 }
2378 2548
2379 2549
2380 void Assembler::EnterDartFrame(intptr_t frame_size) { 2550 void Assembler::LoadPoolPointer(Register pp) {
2551 Label next;
2552 call(&next);
2553 Bind(&next);
2554
2555 // Load new pool pointer.
2556 const intptr_t object_pool_pc_dist =
2557 Instructions::HeaderSize() - Instructions::object_pool_offset() +
2558 CodeSize();
2559 popq(pp);
2560 movq(pp, Address(pp, -object_pool_pc_dist));
2561 }
2562
2563
2564 void Assembler::EnterDartFrame(intptr_t frame_size,
2565 Register new_pp, Register new_pc) {
2381 EnterFrame(0); 2566 EnterFrame(0);
2382 Label dart_entry; 2567 if (new_pc == kNoRegister) {
2383 call(&dart_entry); 2568 Label dart_entry;
2384 Bind(&dart_entry); 2569 call(&dart_entry);
2385 // The runtime system assumes that the code marker address is 2570 Bind(&dart_entry);
2386 // kEntryPointToPcMarkerOffset bytes from the entry. If there is any code 2571 // The runtime system assumes that the code marker address is
2387 // generated before entering the frame, the address needs to be adjusted. 2572 // kEntryPointToPcMarkerOffset bytes from the entry. If there is any code
2388 const intptr_t offset = kEntryPointToPcMarkerOffset - CodeSize(); 2573 // generated before entering the frame, the address needs to be adjusted.
2389 if (offset != 0) { 2574 const intptr_t object_pool_pc_dist =
2390 addq(Address(RSP, 0), Immediate(offset)); 2575 Instructions::HeaderSize() - Instructions::object_pool_offset() +
2576 CodeSize();
2577 const intptr_t offset = kEntryPointToPcMarkerOffset - CodeSize();
2578 if (offset != 0) {
2579 addq(Address(RSP, 0), Immediate(offset));
2580 }
2581 // Save caller's pool pointer
2582 pushq(PP);
2583
2584 // Load callee's pool pointer.
2585 movq(PP, Address(RSP, 1 * kWordSize));
2586 movq(PP, Address(PP, -object_pool_pc_dist - offset));
2587 } else {
2588 pushq(new_pc);
2589 pushq(PP);
2590 movq(PP, new_pp);
2391 } 2591 }
2392 if (frame_size != 0) { 2592 if (frame_size != 0) {
2393 subq(RSP, Immediate(frame_size)); 2593 subq(RSP, Immediate(frame_size));
2394 } 2594 }
2395 } 2595 }
2396 2596
2397 2597
2398 // On entry to a function compiled for OSR, the caller's frame pointer, the 2598 // On entry to a function compiled for OSR, the caller's frame pointer, the
2399 // stack locals, and any copied parameters are already in place. The frame 2599 // stack locals, and any copied parameters are already in place. The frame
2400 // pointer is already set up. The PC marker is not correct for the 2600 // pointer is already set up. The PC marker is not correct for the
2401 // optimized function and there may be extra space for spill slots to 2601 // optimized function and there may be extra space for spill slots to
2402 // allocate. 2602 // allocate.
2403 void Assembler::EnterOsrFrame(intptr_t extra_size) { 2603 void Assembler::EnterOsrFrame(intptr_t extra_size,
2404 Label dart_entry; 2604 Register new_pp, Register new_pc) {
2405 call(&dart_entry); 2605 if (new_pc == kNoRegister) {
2406 Bind(&dart_entry); 2606 Label dart_entry;
2407 // The runtime system assumes that the code marker address is 2607 call(&dart_entry);
2408 // kEntryPointToPcMarkerOffset bytes from the entry. Since there is no 2608 Bind(&dart_entry);
2409 // code to set up the frame pointer, the address needs to be adjusted. 2609 // The runtime system assumes that the code marker address is
2410 const intptr_t offset = kEntryPointToPcMarkerOffset - CodeSize(); 2610 // kEntryPointToPcMarkerOffset bytes from the entry. Since there is no
2411 if (offset != 0) { 2611 // code to set up the frame pointer, the address needs to be adjusted.
2412 addq(Address(RSP, 0), Immediate(offset)); 2612 const intptr_t object_pool_pc_dist =
2613 Instructions::HeaderSize() - Instructions::object_pool_offset() +
2614 CodeSize();
2615 const intptr_t offset = kEntryPointToPcMarkerOffset - CodeSize();
2616 if (offset != 0) {
2617 addq(Address(RSP, 0), Immediate(offset));
2618 }
2619
2620 // Load callee's pool pointer.
2621 movq(PP, Address(RSP, 0));
2622 movq(PP, Address(PP, -object_pool_pc_dist - offset));
2623
2624 popq(Address(RBP, kPcMarkerSlotFromFp * kWordSize));
2625 } else {
2626 movq(Address(RBP, kPcMarkerSlotFromFp * kWordSize), new_pc);
2627 movq(PP, new_pp);
2413 } 2628 }
2414 popq(Address(RBP, kPcMarkerSlotFromFp * kWordSize));
2415 if (extra_size != 0) { 2629 if (extra_size != 0) {
2416 subq(RSP, Immediate(extra_size)); 2630 subq(RSP, Immediate(extra_size));
2417 } 2631 }
2418 } 2632 }
2419 2633
2420 2634
2421 void Assembler::EnterStubFrame() { 2635 void Assembler::EnterStubFrame(bool save_pp) {
2422 EnterFrame(0); 2636 if (save_pp) {
2423 pushq(Immediate(0)); // Push 0 in the saved PC area for stub frames. 2637 EnterFrame(0);
2638 pushq(Immediate(0)); // Push 0 in the saved PC area for stub frames.
2639 pushq(PP); // Save caller's pool pointer
2640 LoadPoolPointer();
2641 } else {
2642 EnterFrame(0);
2643 pushq(Immediate(0)); // Push 0 in the saved PC area for stub frames.
2644 }
2424 } 2645 }
2425 2646
2426 2647
2427 void Assembler::TryAllocate(const Class& cls, 2648 void Assembler::TryAllocate(const Class& cls,
2428 Label* failure, 2649 Label* failure,
2429 bool near_jump, 2650 bool near_jump,
2430 Register instance_reg) { 2651 Register instance_reg) {
2431 ASSERT(failure != NULL); 2652 ASSERT(failure != NULL);
2432 if (FLAG_inline_alloc) { 2653 if (FLAG_inline_alloc) {
2433 Heap* heap = Isolate::Current()->heap(); 2654 Heap* heap = Isolate::Current()->heap();
(...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after
2643 2864
2644 const char* Assembler::FpuRegisterName(FpuRegister reg) { 2865 const char* Assembler::FpuRegisterName(FpuRegister reg) {
2645 ASSERT((0 <= reg) && (reg < kNumberOfXmmRegisters)); 2866 ASSERT((0 <= reg) && (reg < kNumberOfXmmRegisters));
2646 return xmm_reg_names[reg]; 2867 return xmm_reg_names[reg];
2647 } 2868 }
2648 2869
2649 2870
2650 } // namespace dart 2871 } // namespace dart
2651 2872
2652 #endif // defined TARGET_ARCH_X64 2873 #endif // defined TARGET_ARCH_X64
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698