Chromium Code Reviews| 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 |