OLD | NEW |
---|---|
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_IA32) | 6 #if defined(TARGET_ARCH_IA32) |
7 | 7 |
8 #include "vm/assembler.h" | 8 #include "vm/assembler.h" |
9 #include "vm/code_generator.h" | 9 #include "vm/code_generator.h" |
10 #include "vm/cpu.h" | 10 #include "vm/cpu.h" |
11 #include "vm/heap.h" | 11 #include "vm/heap.h" |
12 #include "vm/memory_region.h" | 12 #include "vm/memory_region.h" |
13 #include "vm/runtime_entry.h" | 13 #include "vm/runtime_entry.h" |
14 #include "vm/stack_frame.h" | 14 #include "vm/stack_frame.h" |
15 #include "vm/stub_code.h" | 15 #include "vm/stub_code.h" |
16 #include "vm/verified_memory.h" | |
16 | 17 |
17 namespace dart { | 18 namespace dart { |
18 | 19 |
19 DEFINE_FLAG(bool, print_stop_message, true, "Print stop message."); | 20 DEFINE_FLAG(bool, print_stop_message, true, "Print stop message."); |
20 DECLARE_FLAG(bool, inline_alloc); | 21 DECLARE_FLAG(bool, inline_alloc); |
21 | 22 |
22 | 23 |
23 class DirectCallRelocation : public AssemblerFixup { | 24 class DirectCallRelocation : public AssemblerFixup { |
24 public: | 25 public: |
25 void Process(const MemoryRegion& region, intptr_t position) { | 26 void Process(const MemoryRegion& region, intptr_t position) { |
(...skipping 2165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2191 // Mask out higher, uninteresting bits which were polluted by dest. | 2192 // Mask out higher, uninteresting bits which were polluted by dest. |
2192 andl(value, Immediate(kObjectAlignment - 1)); | 2193 andl(value, Immediate(kObjectAlignment - 1)); |
2193 // Compare with the expected bit pattern. | 2194 // Compare with the expected bit pattern. |
2194 cmpl(value, Immediate( | 2195 cmpl(value, Immediate( |
2195 (kNewObjectAlignmentOffset >> 1) + kHeapObjectTag + | 2196 (kNewObjectAlignmentOffset >> 1) + kHeapObjectTag + |
2196 kOldObjectAlignmentOffset + kHeapObjectTag)); | 2197 kOldObjectAlignmentOffset + kHeapObjectTag)); |
2197 j(NOT_ZERO, no_update, Assembler::kNearJump); | 2198 j(NOT_ZERO, no_update, Assembler::kNearJump); |
2198 } | 2199 } |
2199 | 2200 |
2200 | 2201 |
2202 void Assembler::VerifiedWrite(const Address& dest, Register value) { | |
2203 // TODO(koda): Verify previous value. | |
2204 movl(dest, value); | |
2205 if (VerifiedMemory::enabled()) { | |
2206 Register temp = (value == EDX) ? ECX : EDX; | |
2207 pushl(temp); | |
2208 leal(temp, dest); | |
2209 movl(Address(temp, VerifiedMemory::offset()), value); | |
2210 popl(temp); | |
2211 } | |
2212 } | |
2213 | |
2214 | |
2201 // Destroys the value register. | 2215 // Destroys the value register. |
2202 void Assembler::StoreIntoObject(Register object, | 2216 void Assembler::StoreIntoObject(Register object, |
2203 const Address& dest, | 2217 const Address& dest, |
2204 Register value, | 2218 Register value, |
2205 bool can_value_be_smi) { | 2219 bool can_value_be_smi) { |
2206 ASSERT(object != value); | 2220 ASSERT(object != value); |
2207 movl(dest, value); | 2221 VerifiedWrite(dest, value); |
2208 Label done; | 2222 Label done; |
2209 if (can_value_be_smi) { | 2223 if (can_value_be_smi) { |
2210 StoreIntoObjectFilter(object, value, &done); | 2224 StoreIntoObjectFilter(object, value, &done); |
2211 } else { | 2225 } else { |
2212 StoreIntoObjectFilterNoSmi(object, value, &done); | 2226 StoreIntoObjectFilterNoSmi(object, value, &done); |
2213 } | 2227 } |
2214 // A store buffer update is required. | 2228 // A store buffer update is required. |
2215 if (value != EDX) { | 2229 if (value != EDX) { |
2216 pushl(EDX); // Preserve EDX. | 2230 pushl(EDX); // Preserve EDX. |
2217 } | 2231 } |
2218 if (object != EDX) { | 2232 if (object != EDX) { |
2219 movl(EDX, object); | 2233 movl(EDX, object); |
2220 } | 2234 } |
2221 StubCode* stub_code = Isolate::Current()->stub_code(); | 2235 StubCode* stub_code = Isolate::Current()->stub_code(); |
2222 call(&stub_code->UpdateStoreBufferLabel()); | 2236 call(&stub_code->UpdateStoreBufferLabel()); |
2223 if (value != EDX) { | 2237 if (value != EDX) { |
2224 popl(EDX); // Restore EDX. | 2238 popl(EDX); // Restore EDX. |
2225 } | 2239 } |
2226 Bind(&done); | 2240 Bind(&done); |
2227 } | 2241 } |
2228 | 2242 |
2229 | 2243 |
2230 void Assembler::StoreIntoObjectNoBarrier(Register object, | 2244 void Assembler::StoreIntoObjectNoBarrier(Register object, |
2231 const Address& dest, | 2245 const Address& dest, |
2232 Register value) { | 2246 Register value) { |
2233 movl(dest, value); | 2247 VerifiedWrite(dest, value); |
2234 #if defined(DEBUG) | 2248 #if defined(DEBUG) |
2235 Label done; | 2249 Label done; |
2236 pushl(value); | 2250 pushl(value); |
2237 StoreIntoObjectFilter(object, value, &done); | 2251 StoreIntoObjectFilter(object, value, &done); |
2238 Stop("Store buffer update is required"); | 2252 Stop("Store buffer update is required"); |
2239 Bind(&done); | 2253 Bind(&done); |
2240 popl(value); | 2254 popl(value); |
2241 #endif // defined(DEBUG) | 2255 #endif // defined(DEBUG) |
2242 // No store buffer update. | 2256 // No store buffer update. |
2243 } | 2257 } |
2244 | 2258 |
2245 | 2259 |
2260 void Assembler::UnverifiedStoreOldObject(const Address& dest, | |
2261 const Object& value) { | |
2262 ASSERT(value.IsOld()); | |
2263 ASSERT(!value.InVMHeap()); | |
2264 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
2265 EmitUint8(0xC7); | |
2266 EmitOperand(0, dest); | |
2267 buffer_.EmitObject(value); | |
2268 } | |
2269 | |
2270 | |
2246 void Assembler::StoreIntoObjectNoBarrier(Register object, | 2271 void Assembler::StoreIntoObjectNoBarrier(Register object, |
2247 const Address& dest, | 2272 const Address& dest, |
2248 const Object& value) { | 2273 const Object& value) { |
2249 if (value.IsSmi() || value.InVMHeap()) { | 2274 if (value.IsSmi() || value.InVMHeap()) { |
2250 movl(dest, Immediate(reinterpret_cast<int32_t>(value.raw()))); | 2275 // TODO(koda): Verify previous value. |
2276 Immediate imm_value(reinterpret_cast<int32_t>(value.raw())); | |
2277 movl(dest, imm_value); | |
2278 if (VerifiedMemory::enabled()) { | |
2279 Register temp = ECX; | |
2280 pushl(temp); | |
2281 leal(temp, dest); | |
2282 movl(Address(temp, VerifiedMemory::offset()), imm_value); | |
2283 popl(temp); | |
2284 } | |
2251 } else { | 2285 } else { |
2252 ASSERT(value.IsOld()); | 2286 UnverifiedStoreOldObject(dest, value); |
2253 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | 2287 if (VerifiedMemory::enabled()) { |
2254 EmitUint8(0xC7); | 2288 Register temp = EDX; |
2255 EmitOperand(0, dest); | 2289 pushl(temp); |
2256 buffer_.EmitObject(value); | 2290 leal(temp, dest); |
2291 UnverifiedStoreOldObject(Address(temp, VerifiedMemory::offset()), value); | |
2292 popl(temp); | |
2293 } | |
2257 } | 2294 } |
2258 // No store buffer update. | 2295 // No store buffer update. |
2259 } | 2296 } |
2260 | 2297 |
2261 | 2298 |
2262 void Assembler::StoreIntoSmiField(const Address& dest, Register value) { | 2299 void Assembler::StoreIntoSmiField(const Address& dest, Register value) { |
2263 movl(dest, value); | 2300 VerifiedWrite(dest, value); |
2264 #if defined(DEBUG) | 2301 #if defined(DEBUG) |
2265 Label done; | 2302 Label done; |
2266 testl(value, Immediate(kHeapObjectTag)); | 2303 testl(value, Immediate(kHeapObjectTag)); |
2267 j(ZERO, &done); | 2304 j(ZERO, &done); |
2268 Stop("Smi expected"); | 2305 Stop("Smi expected"); |
2269 Bind(&done); | 2306 Bind(&done); |
2270 #endif // defined(DEBUG) | 2307 #endif // defined(DEBUG) |
2271 } | 2308 } |
2272 | 2309 |
2273 | 2310 |
2311 void Assembler::ZeroSmiField(const Address& dest) { | |
2312 Immediate zero(Smi::RawValue(0)); | |
Ivan Posva
2014/11/12 21:22:49
Add TODO
koda
2014/11/12 23:47:30
Done.
| |
2313 movl(dest, zero); | |
2314 if (VerifiedMemory::enabled()) { | |
2315 Register temp = ECX; | |
2316 pushl(temp); | |
2317 leal(temp, dest); | |
2318 movl(Address(temp, VerifiedMemory::offset()), zero); | |
2319 popl(temp); | |
2320 } | |
2321 } | |
2322 | |
2323 | |
2274 void Assembler::IncrementSmiField(const Address& dest, int32_t increment) { | 2324 void Assembler::IncrementSmiField(const Address& dest, int32_t increment) { |
2325 // Note: FlowGraphCompiler::EdgeCounterIncrementSizeInBytes depends on | |
2326 // the length of this instruction sequence. | |
2327 // | |
2275 // TODO(koda): Implement testl for addresses and check that dest is a smi. | 2328 // TODO(koda): Implement testl for addresses and check that dest is a smi. |
2276 addl(dest, Immediate(Smi::RawValue(increment))); | 2329 Immediate inc_imm(Smi::RawValue(increment)); |
2330 addl(dest, inc_imm); | |
2331 if (VerifiedMemory::enabled()) { | |
2332 Register temp = ECX; | |
2333 pushl(temp); | |
2334 leal(temp, dest); | |
2335 addl(Address(temp, VerifiedMemory::offset()), inc_imm); | |
2336 popl(temp); | |
2337 } | |
2277 } | 2338 } |
2278 | 2339 |
2279 | 2340 |
2280 void Assembler::LoadDoubleConstant(XmmRegister dst, double value) { | 2341 void Assembler::LoadDoubleConstant(XmmRegister dst, double value) { |
2281 // TODO(5410843): Need to have a code constants table. | 2342 // TODO(5410843): Need to have a code constants table. |
2282 int64_t constant = bit_cast<int64_t, double>(value); | 2343 int64_t constant = bit_cast<int64_t, double>(value); |
2283 pushl(Immediate(Utils::High32Bits(constant))); | 2344 pushl(Immediate(Utils::High32Bits(constant))); |
2284 pushl(Immediate(Utils::Low32Bits(constant))); | 2345 pushl(Immediate(Utils::Low32Bits(constant))); |
2285 movsd(dst, Address(ESP, 0)); | 2346 movsd(dst, Address(ESP, 0)); |
2286 addl(ESP, Immediate(2 * kWordSize)); | 2347 addl(ESP, Immediate(2 * kWordSize)); |
(...skipping 609 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2896 | 2957 |
2897 const char* Assembler::FpuRegisterName(FpuRegister reg) { | 2958 const char* Assembler::FpuRegisterName(FpuRegister reg) { |
2898 ASSERT((0 <= reg) && (reg < kNumberOfXmmRegisters)); | 2959 ASSERT((0 <= reg) && (reg < kNumberOfXmmRegisters)); |
2899 return xmm_reg_names[reg]; | 2960 return xmm_reg_names[reg]; |
2900 } | 2961 } |
2901 | 2962 |
2902 | 2963 |
2903 } // namespace dart | 2964 } // namespace dart |
2904 | 2965 |
2905 #endif // defined TARGET_ARCH_IA32 | 2966 #endif // defined TARGET_ARCH_IA32 |
OLD | NEW |