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

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(), 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(), Heap::kOld);
88 }
89
90 if (StubCode::CallToRuntime_entry() != NULL) {
91 AddExternalLabel(&StubCode::CallToRuntimeLabel(), kNotPatchable);
92 } else {
93 object_pool_.Add(Object::Handle(), 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(Register dst,
130 const ExternalLabel* label,
131 Patchability patchable,
132 Register pp) {
133 const int32_t offset =
134 Array::element_offset(AddExternalLabel(label, patchable));
135 LoadWordFromPoolOffset(dst, pp, offset - kHeapObjectTag);
136 }
137
138
98 void Assembler::call(const ExternalLabel* label) { 139 void Assembler::call(const ExternalLabel* label) {
99 AssemblerBuffer::EnsureCapacity ensured(&buffer_); 140 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
100 intptr_t call_start = buffer_.GetPosition();
101 141
102 // Encode movq(TMP, Immediate(label->address())), but always as imm64. 142 // Encode movq(TMP, Immediate(label->address())), but always as imm64.
103 EmitRegisterREX(TMP, REX_W); 143 EmitRegisterREX(TMP, REX_W);
104 EmitUint8(0xB8 | (TMP & 7)); 144 EmitUint8(0xB8 | (TMP & 7));
105 EmitInt64(label->address()); 145 EmitInt64(label->address());
106 146
107 // Encode call(TMP). 147 // Encode call(TMP).
108 Operand operand(TMP); 148 Operand operand(TMP);
109 EmitOperandREX(2, operand, REX_NONE); 149 EmitOperandREX(2, operand, REX_NONE);
110 EmitUint8(0xFF); 150 EmitUint8(0xFF);
111 EmitOperand(2, operand); 151 EmitOperand(2, operand);
152 }
112 153
154
155 void Assembler::CallPatchable(const ExternalLabel* label) {
156 intptr_t call_start = buffer_.GetPosition();
157 LoadExternalLabel(TMP, label, kPatchable, PP);
158 {
159 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
160 // Encode call(TMP).
161 Operand operand(TMP);
162 EmitOperandREX(2, operand, REX_NONE);
163 EmitUint8(0xFF);
164 EmitOperand(2, operand);
165 }
113 ASSERT((buffer_.GetPosition() - call_start) == kCallExternalLabelSize); 166 ASSERT((buffer_.GetPosition() - call_start) == kCallExternalLabelSize);
114 } 167 }
115 168
116 169
170 void Assembler::CallFromPool(const ExternalLabel* label) {
Florian Schneider 2013/09/05 10:57:45 I'd still rename this to Call to be consistent wit
zra 2013/09/05 20:29:26 Done.
171 if (Isolate::Current() == Dart::vm_isolate()) {
172 call(label);
173 } else {
174 LoadExternalLabel(TMP, label, kNotPatchable, PP);
175 {
176 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
177 // Encode call(TMP).
178 Operand operand(TMP);
179 EmitOperandREX(2, operand, REX_NONE);
180 EmitUint8(0xFF);
181 EmitOperand(2, operand);
182 }
183 }
184 }
185
186
117 void Assembler::pushq(Register reg) { 187 void Assembler::pushq(Register reg) {
118 AssemblerBuffer::EnsureCapacity ensured(&buffer_); 188 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
119 EmitRegisterREX(reg, REX_NONE); 189 EmitRegisterREX(reg, REX_NONE);
120 EmitUint8(0x50 | (reg & 7)); 190 EmitUint8(0x50 | (reg & 7));
121 } 191 }
122 192
123 193
124 void Assembler::pushq(const Address& address) { 194 void Assembler::pushq(const Address& address) {
125 AssemblerBuffer::EnsureCapacity ensured(&buffer_); 195 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
126 EmitOperandREX(6, address, REX_NONE); 196 EmitOperandREX(6, address, REX_NONE);
(...skipping 1826 matching lines...) Expand 10 before | Expand all | Expand 10 after
1953 2023
1954 2024
1955 void Assembler::j(Condition condition, const ExternalLabel* label) { 2025 void Assembler::j(Condition condition, const ExternalLabel* label) {
1956 Label no_jump; 2026 Label no_jump;
1957 j(static_cast<Condition>(condition ^ 1), &no_jump); // Negate condition. 2027 j(static_cast<Condition>(condition ^ 1), &no_jump); // Negate condition.
1958 jmp(label); 2028 jmp(label);
1959 Bind(&no_jump); 2029 Bind(&no_jump);
1960 } 2030 }
1961 2031
1962 2032
2033 void Assembler::ConditionalJumpFromPool(Condition condition,
Florian Schneider 2013/09/05 10:57:45 How about renaming this to just J?
zra 2013/09/05 20:29:26 Done.
2034 const ExternalLabel* label,
2035 Register pp) {
2036 Label no_jump;
2037 j(static_cast<Condition>(condition ^ 1), &no_jump); // Negate condition.
2038 JumpFromPool(label, pp);
2039 Bind(&no_jump);
2040 }
2041
2042
1963 void Assembler::jmp(Register reg) { 2043 void Assembler::jmp(Register reg) {
1964 AssemblerBuffer::EnsureCapacity ensured(&buffer_); 2044 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
1965 Operand operand(reg); 2045 Operand operand(reg);
1966 EmitOperandREX(4, operand, REX_NONE); 2046 EmitOperandREX(4, operand, REX_NONE);
1967 EmitUint8(0xFF); 2047 EmitUint8(0xFF);
1968 EmitOperand(4, operand); 2048 EmitOperand(4, operand);
1969 } 2049 }
1970 2050
1971 2051
1972 void Assembler::jmp(Label* label, bool near) { 2052 void Assembler::jmp(Label* label, bool near) {
(...skipping 15 matching lines...) Expand all
1988 EmitNearLabelLink(label); 2068 EmitNearLabelLink(label);
1989 } else { 2069 } else {
1990 EmitUint8(0xE9); 2070 EmitUint8(0xE9);
1991 EmitLabelLink(label); 2071 EmitLabelLink(label);
1992 } 2072 }
1993 } 2073 }
1994 2074
1995 2075
1996 void Assembler::jmp(const ExternalLabel* label) { 2076 void Assembler::jmp(const ExternalLabel* label) {
1997 AssemblerBuffer::EnsureCapacity ensured(&buffer_); 2077 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
1998 intptr_t call_start = buffer_.GetPosition();
1999 2078
2000 // Encode movq(TMP, Immediate(label->address())), but always as imm64. 2079 // Encode movq(TMP, Immediate(label->address())), but always as imm64.
2001 EmitRegisterREX(TMP, REX_W); 2080 EmitRegisterREX(TMP, REX_W);
2002 EmitUint8(0xB8 | (TMP & 7)); 2081 EmitUint8(0xB8 | (TMP & 7));
2003 EmitInt64(label->address()); 2082 EmitInt64(label->address());
2004 2083
2005 // Encode jmp(TMP). 2084 // Encode jmp(TMP).
2006 Operand operand(TMP); 2085 Operand operand(TMP);
2007 EmitOperandREX(4, operand, REX_NONE); 2086 EmitOperandREX(4, operand, REX_NONE);
2008 EmitUint8(0xFF); 2087 EmitUint8(0xFF);
2009 EmitOperand(4, operand); 2088 EmitOperand(4, operand);
2089 }
2010 2090
2091
2092 void Assembler::JumpPatchable(const ExternalLabel* label, Register pp) {
2093 intptr_t call_start = buffer_.GetPosition();
2094 LoadExternalLabel(TMP, label, kPatchable, pp);
2095 {
2096 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
2097 // Encode jmp(TMP).
2098 Operand operand(TMP);
2099 EmitOperandREX(4, operand, REX_NONE);
2100 EmitUint8(0xFF);
2101 EmitOperand(4, operand);
2102 }
2011 ASSERT((buffer_.GetPosition() - call_start) == kCallExternalLabelSize); 2103 ASSERT((buffer_.GetPosition() - call_start) == kCallExternalLabelSize);
2012 } 2104 }
2013 2105
2014 2106
2107 void Assembler::JumpFromPool(const ExternalLabel* label, Register pp) {
Florian Schneider 2013/09/05 10:57:45 Likewise rename to just Jmp. It's clear from the s
zra 2013/09/05 20:29:26 Done.
2108 LoadExternalLabel(TMP, label, kNotPatchable, pp);
2109 {
2110 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
2111 // Encode jmp(TMP).
2112 Operand operand(TMP);
2113 EmitOperandREX(4, operand, REX_NONE);
2114 EmitUint8(0xFF);
2115 EmitOperand(4, operand);
2116 }
2117 }
2118
2119
2015 void Assembler::lock() { 2120 void Assembler::lock() {
2016 AssemblerBuffer::EnsureCapacity ensured(&buffer_); 2121 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
2017 EmitUint8(0xF0); 2122 EmitUint8(0xF0);
2018 } 2123 }
2019 2124
2020 2125
2021 void Assembler::cmpxchgl(const Address& address, Register reg) { 2126 void Assembler::cmpxchgl(const Address& address, Register reg) {
2022 AssemblerBuffer::EnsureCapacity ensured(&buffer_); 2127 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
2023 EmitOperandREX(reg, address, REX_NONE); 2128 EmitOperandREX(reg, address, REX_NONE);
2024 EmitUint8(0x0F); 2129 EmitUint8(0x0F);
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
2084 if (stack_elements <= 4) { 2189 if (stack_elements <= 4) {
2085 for (intptr_t i = 0; i < stack_elements; i++) { 2190 for (intptr_t i = 0; i < stack_elements; i++) {
2086 popq(TMP); 2191 popq(TMP);
2087 } 2192 }
2088 return; 2193 return;
2089 } 2194 }
2090 addq(RSP, Immediate(stack_elements * kWordSize)); 2195 addq(RSP, Immediate(stack_elements * kWordSize));
2091 } 2196 }
2092 2197
2093 2198
2094 void Assembler::LoadObject(Register dst, const Object& object) { 2199 intptr_t Assembler::AddObject(const Object& obj) {
Florian Schneider 2013/09/05 10:57:45 AddObject is confusing because it does not always
zra 2013/09/05 20:29:26 Changed to FindObject. Likewise, changed AddExtern
2095 if (object.IsSmi() || object.InVMHeap()) { 2200 // The object pool cannot be used in the vm isolate.
2201 ASSERT(Isolate::Current() != Dart::vm_isolate());
2202 ASSERT(obj.IsNotTemporaryScopedHandle());
2203 ASSERT(obj.IsOld());
2204 ASSERT(!object_pool_.IsNull());
2205 // TODO(zra): This can be slow. Add a hash map from obj.raw() to
Florian Schneider 2013/09/05 10:57:45 I think it's ok to land this TODO, but it has to b
zra 2013/09/05 20:29:26 Acknowledged.
2206 // object pool indexes to speed lookup.
2207 for (int i = 0; i < object_pool_.Length(); i++) {
2208 if (object_pool_.At(i) == obj.raw()) {
2209 return i;
2210 }
2211 }
2212 object_pool_.Add(obj, Heap::kOld);
2213 return object_pool_.Length() - 1;
2214 }
2215
2216
2217 intptr_t Assembler::AddExternalLabel(const ExternalLabel* label,
2218 Patchability patchable) {
2219 // The object pool cannot be used in the vm isolate.
2220 ASSERT(Isolate::Current() != Dart::vm_isolate());
2221 ASSERT(!object_pool_.IsNull());
2222 const uword 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(reinterpret_cast<RawSmi*>(address));
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 // TODO(zra): This can be slow. Add a hash map from obj.raw() to
Florian Schneider 2013/09/05 10:57:45 I think it's ok to land this TODO, but it has to b
zra 2013/09/05 20:29:26 Acknowledged.
2231 // object pool indexes to speed lookup.
2232 for (int i = 0; i < object_pool_.Length(); i++) {
2233 if (object_pool_.At(i) == smi.raw()) {
2234 return i;
2235 }
2236 }
2237 }
2238 // If the call is patchable, do not reuse an existing entry since each
2239 // reference may be patched independently.
2240 object_pool_.Add(smi, Heap::kOld);
2241 return object_pool_.Length() - 1;
2242 }
2243
2244
2245 bool Assembler::CanLoadFromObjectPool(const Object& object) {
2246 return !object.IsSmi() && // Not a Smi
2247 // Not in the VMHeap, OR is one of the VMHeap objects we put in every
2248 // object pool.
2249 (!object.InVMHeap() || (object.raw() == Object::null()) ||
2250 (object.raw() == Bool::True().raw()) ||
2251 (object.raw() == Bool::False().raw())) &&
2252 object.IsNotTemporaryScopedHandle() &&
2253 object.IsOld();
2254 }
2255
2256
2257 void Assembler::LoadWordFromPoolOffset(Register dst, Register pp,
2258 int32_t offset) {
2259 // This sequence must be of fixed size. The 'true' argument to the Address
2260 // constructor forces it to use a fixed size encoding.
2261 movq(dst, Address(pp, offset, true));
2262 }
2263
2264
2265 void Assembler::LoadObjectFromPool(Register dst, const Object& object,
2266 Register pp) {
2267 if (CanLoadFromObjectPool(object)) {
2268 const int32_t offset = Array::element_offset(AddObject(object));
2269 LoadWordFromPoolOffset(dst, pp, offset - kHeapObjectTag);
2270 } else {
2096 movq(dst, Immediate(reinterpret_cast<int64_t>(object.raw()))); 2271 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 } 2272 }
2105 } 2273 }
2106 2274
2107 2275
2108 void Assembler::StoreObject(const Address& dst, const Object& object) { 2276 void Assembler::StoreObject(const Address& dst, const Object& object) {
2109 if (object.IsSmi() || object.InVMHeap()) { 2277 if (CanLoadFromObjectPool(object)) {
2278 LoadObjectFromPool(TMP, object, PP);
2279 movq(dst, TMP);
2280 } else {
2110 movq(dst, Immediate(reinterpret_cast<int64_t>(object.raw()))); 2281 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 } 2282 }
2117 } 2283 }
2118 2284
2119 2285
2120 void Assembler::PushObject(const Object& object) { 2286 void Assembler::PushObject(const Object& object) {
2121 if (object.IsSmi() || object.InVMHeap()) { 2287 if (CanLoadFromObjectPool(object)) {
2288 LoadObjectFromPool(TMP, object, PP);
2289 pushq(TMP);
2290 } else {
2122 pushq(Immediate(reinterpret_cast<int64_t>(object.raw()))); 2291 pushq(Immediate(reinterpret_cast<int64_t>(object.raw())));
2123 } else {
2124 LoadObject(TMP, object);
2125 pushq(TMP);
2126 } 2292 }
2127 } 2293 }
2128 2294
2129 2295
2130 void Assembler::CompareObject(Register reg, const Object& object) { 2296 void Assembler::CompareObject(Register reg, const Object& object) {
2131 if (object.IsSmi() || object.InVMHeap()) { 2297 if (CanLoadFromObjectPool(object)) {
2298 ASSERT(reg != TMP);
2299 LoadObjectFromPool(TMP, object, PP);
2300 cmpq(reg, TMP);
2301 } else {
2132 cmpq(reg, Immediate(reinterpret_cast<int64_t>(object.raw()))); 2302 cmpq(reg, Immediate(reinterpret_cast<int64_t>(object.raw())));
2133 } else {
2134 ASSERT(reg != TMP);
2135 LoadObject(TMP, object);
2136 cmpq(reg, TMP);
2137 } 2303 }
2138 } 2304 }
2139 2305
2140 2306
2141 // Destroys the value register. 2307 // Destroys the value register.
2142 void Assembler::StoreIntoObjectFilterNoSmi(Register object, 2308 void Assembler::StoreIntoObjectFilterNoSmi(Register object,
2143 Register value, 2309 Register value,
2144 Label* no_update) { 2310 Label* no_update) {
2145 COMPILE_ASSERT((kNewObjectAlignmentOffset == kWordSize) && 2311 COMPILE_ASSERT((kNewObjectAlignmentOffset == kWordSize) &&
2146 (kOldObjectAlignmentOffset == 0), young_alignment); 2312 (kOldObjectAlignmentOffset == 0), young_alignment);
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
2189 if (can_value_be_smi) { 2355 if (can_value_be_smi) {
2190 StoreIntoObjectFilter(object, value, &done); 2356 StoreIntoObjectFilter(object, value, &done);
2191 } else { 2357 } else {
2192 StoreIntoObjectFilterNoSmi(object, value, &done); 2358 StoreIntoObjectFilterNoSmi(object, value, &done);
2193 } 2359 }
2194 // A store buffer update is required. 2360 // A store buffer update is required.
2195 if (value != RAX) pushq(RAX); 2361 if (value != RAX) pushq(RAX);
2196 if (object != RAX) { 2362 if (object != RAX) {
2197 movq(RAX, object); 2363 movq(RAX, object);
2198 } 2364 }
2199 call(&StubCode::UpdateStoreBufferLabel()); 2365 CallFromPool(&StubCode::UpdateStoreBufferLabel());
2200 if (value != RAX) popq(RAX); 2366 if (value != RAX) popq(RAX);
2201 Bind(&done); 2367 Bind(&done);
2202 } 2368 }
2203 2369
2204 2370
2205 void Assembler::StoreIntoObjectNoBarrier(Register object, 2371 void Assembler::StoreIntoObjectNoBarrier(Register object,
2206 const Address& dest, 2372 const Address& dest,
2207 Register value) { 2373 Register value) {
2208 movq(dest, value); 2374 movq(dest, value);
2209 #if defined(DEBUG) 2375 #if defined(DEBUG)
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
2291 } 2457 }
2292 } 2458 }
2293 2459
2294 2460
2295 void Assembler::LeaveFrame() { 2461 void Assembler::LeaveFrame() {
2296 movq(RSP, RBP); 2462 movq(RSP, RBP);
2297 popq(RBP); 2463 popq(RBP);
2298 } 2464 }
2299 2465
2300 2466
2467 void Assembler::LeaveFrameWithPP() {
2468 movq(PP, Address(RBP, -2 * kWordSize));
2469 movq(RSP, RBP);
2470 popq(RBP);
2471 }
2472
2473
2301 void Assembler::ReserveAlignedFrameSpace(intptr_t frame_space) { 2474 void Assembler::ReserveAlignedFrameSpace(intptr_t frame_space) {
2302 // Reserve space for arguments and align frame before entering 2475 // Reserve space for arguments and align frame before entering
2303 // the C++ world. 2476 // the C++ world.
2304 AddImmediate(RSP, Immediate(-frame_space)); 2477 AddImmediate(RSP, Immediate(-frame_space));
2305 if (OS::ActivationFrameAlignment() > 1) { 2478 if (OS::ActivationFrameAlignment() > 1) {
2306 andq(RSP, Immediate(~(OS::ActivationFrameAlignment() - 1))); 2479 andq(RSP, Immediate(~(OS::ActivationFrameAlignment() - 1)));
2307 } 2480 }
2308 } 2481 }
2309 2482
2310 2483
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
2371 leave(); 2544 leave();
2372 } 2545 }
2373 2546
2374 2547
2375 void Assembler::CallRuntime(const RuntimeEntry& entry, 2548 void Assembler::CallRuntime(const RuntimeEntry& entry,
2376 intptr_t argument_count) { 2549 intptr_t argument_count) {
2377 entry.Call(this, argument_count); 2550 entry.Call(this, argument_count);
2378 } 2551 }
2379 2552
2380 2553
2381 void Assembler::EnterDartFrame(intptr_t frame_size) { 2554 void Assembler::LoadPoolPointer(Register pp) {
2555 Label next;
2556 call(&next);
2557 Bind(&next);
2558
2559 // Load new pool pointer.
2560 const intptr_t object_pool_pc_dist =
2561 Instructions::HeaderSize() - Instructions::object_pool_offset() +
2562 CodeSize();
2563 popq(pp);
2564 movq(pp, Address(pp, -object_pool_pc_dist));
2565 }
2566
2567
2568 void Assembler::EnterDartFrame(intptr_t frame_size,
2569 Register new_pp, Register new_pc) {
Florian Schneider 2013/09/05 10:57:45 If new_pc == kNoRegister, then new_pp is not used
zra 2013/09/05 20:29:26 Created and used function EnterDartFrameWithInfo
2382 EnterFrame(0); 2570 EnterFrame(0);
2383 Label dart_entry; 2571 if (new_pc == kNoRegister) {
2384 call(&dart_entry); 2572 Label dart_entry;
2385 Bind(&dart_entry); 2573 call(&dart_entry);
2386 // The runtime system assumes that the code marker address is 2574 Bind(&dart_entry);
2387 // kEntryPointToPcMarkerOffset bytes from the entry. If there is any code 2575 // The runtime system assumes that the code marker address is
2388 // generated before entering the frame, the address needs to be adjusted. 2576 // kEntryPointToPcMarkerOffset bytes from the entry. If there is any code
2389 const intptr_t offset = kEntryPointToPcMarkerOffset - CodeSize(); 2577 // generated before entering the frame, the address needs to be adjusted.
2390 if (offset != 0) { 2578 const intptr_t object_pool_pc_dist =
2391 addq(Address(RSP, 0), Immediate(offset)); 2579 Instructions::HeaderSize() - Instructions::object_pool_offset() +
2580 CodeSize();
2581 const intptr_t offset = kEntryPointToPcMarkerOffset - CodeSize();
2582 if (offset != 0) {
2583 addq(Address(RSP, 0), Immediate(offset));
2584 }
2585 // Save caller's pool pointer
2586 pushq(PP);
2587
2588 // Load callee's pool pointer.
2589 movq(PP, Address(RSP, 1 * kWordSize));
2590 movq(PP, Address(PP, -object_pool_pc_dist - offset));
Florian Schneider 2013/09/05 10:57:45 This PC-relative addressing procedure is complicat
zra 2013/09/05 20:29:26 After discussion with Ivan and Srdjan, they recomm
2591 } else {
2592 pushq(new_pc);
2593 pushq(PP);
2594 movq(PP, new_pp);
2392 } 2595 }
2393 if (frame_size != 0) { 2596 if (frame_size != 0) {
2394 subq(RSP, Immediate(frame_size)); 2597 subq(RSP, Immediate(frame_size));
2395 } 2598 }
2396 } 2599 }
2397 2600
2398 2601
2399 // On entry to a function compiled for OSR, the caller's frame pointer, the 2602 // On entry to a function compiled for OSR, the caller's frame pointer, the
2400 // stack locals, and any copied parameters are already in place. The frame 2603 // stack locals, and any copied parameters are already in place. The frame
2401 // pointer is already set up. The PC marker is not correct for the 2604 // pointer is already set up. The PC marker is not correct for the
2402 // optimized function and there may be extra space for spill slots to 2605 // optimized function and there may be extra space for spill slots to
2403 // allocate. 2606 // allocate.
2404 void Assembler::EnterOsrFrame(intptr_t extra_size) { 2607 void Assembler::EnterOsrFrame(intptr_t extra_size,
2405 Label dart_entry; 2608 Register new_pp, Register new_pc) {
2406 call(&dart_entry); 2609 if (new_pc == kNoRegister) {
2407 Bind(&dart_entry); 2610 Label dart_entry;
2408 // The runtime system assumes that the code marker address is 2611 call(&dart_entry);
2409 // kEntryPointToPcMarkerOffset bytes from the entry. Since there is no 2612 Bind(&dart_entry);
2410 // code to set up the frame pointer, the address needs to be adjusted. 2613 // The runtime system assumes that the code marker address is
2411 const intptr_t offset = kEntryPointToPcMarkerOffset - CodeSize(); 2614 // kEntryPointToPcMarkerOffset bytes from the entry. Since there is no
2412 if (offset != 0) { 2615 // code to set up the frame pointer, the address needs to be adjusted.
2413 addq(Address(RSP, 0), Immediate(offset)); 2616 const intptr_t object_pool_pc_dist =
2617 Instructions::HeaderSize() - Instructions::object_pool_offset() +
2618 CodeSize();
2619 const intptr_t offset = kEntryPointToPcMarkerOffset - CodeSize();
2620 if (offset != 0) {
2621 addq(Address(RSP, 0), Immediate(offset));
2622 }
2623
2624 // Load callee's pool pointer.
2625 movq(PP, Address(RSP, 0));
2626 movq(PP, Address(PP, -object_pool_pc_dist - offset));
2627
2628 popq(Address(RBP, kPcMarkerSlotFromFp * kWordSize));
2629 } else {
2630 movq(Address(RBP, kPcMarkerSlotFromFp * kWordSize), new_pc);
2631 movq(PP, new_pp);
2414 } 2632 }
2415 popq(Address(RBP, kPcMarkerSlotFromFp * kWordSize));
2416 if (extra_size != 0) { 2633 if (extra_size != 0) {
2417 subq(RSP, Immediate(extra_size)); 2634 subq(RSP, Immediate(extra_size));
2418 } 2635 }
2419 } 2636 }
2420 2637
2421 2638
2422 void Assembler::EnterStubFrame() { 2639 void Assembler::EnterStubFrame() {
2423 EnterFrame(0); 2640 EnterFrame(0);
2424 pushq(Immediate(0)); // Push 0 in the saved PC area for stub frames. 2641 pushq(Immediate(0)); // Push 0 in the saved PC area for stub frames.
2425 } 2642 }
2426 2643
2427 2644
2645 void Assembler::EnterStubFrameWithPP() {
2646 EnterFrame(0);
2647 pushq(Immediate(0)); // Push 0 in the saved PC area for stub frames.
2648 pushq(PP); // Save caller's pool pointer
2649 LoadPoolPointer(PP);
2650 }
2651
2652
2428 void Assembler::TryAllocate(const Class& cls, 2653 void Assembler::TryAllocate(const Class& cls,
2429 Label* failure, 2654 Label* failure,
2430 bool near_jump, 2655 bool near_jump,
2431 Register instance_reg) { 2656 Register instance_reg) {
2432 ASSERT(failure != NULL); 2657 ASSERT(failure != NULL);
2433 if (FLAG_inline_alloc) { 2658 if (FLAG_inline_alloc) {
2434 Heap* heap = Isolate::Current()->heap(); 2659 Heap* heap = Isolate::Current()->heap();
2435 const intptr_t instance_size = cls.instance_size(); 2660 const intptr_t instance_size = cls.instance_size();
2436 movq(TMP, Immediate(heap->TopAddress())); 2661 movq(TMP, Immediate(heap->TopAddress()));
2437 movq(instance_reg, Address(TMP, 0)); 2662 movq(instance_reg, Address(TMP, 0));
(...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after
2644 2869
2645 const char* Assembler::FpuRegisterName(FpuRegister reg) { 2870 const char* Assembler::FpuRegisterName(FpuRegister reg) {
2646 ASSERT((0 <= reg) && (reg < kNumberOfXmmRegisters)); 2871 ASSERT((0 <= reg) && (reg < kNumberOfXmmRegisters));
2647 return xmm_reg_names[reg]; 2872 return xmm_reg_names[reg];
2648 } 2873 }
2649 2874
2650 2875
2651 } // namespace dart 2876 } // namespace dart
2652 2877
2653 #endif // defined TARGET_ARCH_X64 2878 #endif // defined TARGET_ARCH_X64
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698