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" // NOLINT | 5 #include "vm/globals.h" // NOLINT |
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" |
(...skipping 1439 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1450 EmitUint8(0xA9); | 1450 EmitUint8(0xA9); |
1451 EmitImmediate(immediate); | 1451 EmitImmediate(immediate); |
1452 } else { | 1452 } else { |
1453 EmitUint8(0xF7); | 1453 EmitUint8(0xF7); |
1454 EmitOperand(0, Operand(reg)); | 1454 EmitOperand(0, Operand(reg)); |
1455 EmitImmediate(immediate); | 1455 EmitImmediate(immediate); |
1456 } | 1456 } |
1457 } | 1457 } |
1458 | 1458 |
1459 | 1459 |
1460 void Assembler::testb(const Address& address, const Immediate& imm) { | |
1461 ASSERT(imm.is_int8()); | |
1462 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | |
1463 EmitUint8(0xF6); | |
1464 EmitOperand(0, address); | |
1465 EmitUint8(imm.value() & 0xFF); | |
1466 } | |
1467 | |
1468 | |
1460 void Assembler::andl(Register dst, Register src) { | 1469 void Assembler::andl(Register dst, Register src) { |
1461 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | 1470 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
1462 EmitUint8(0x23); | 1471 EmitUint8(0x23); |
1463 EmitOperand(dst, Operand(src)); | 1472 EmitOperand(dst, Operand(src)); |
1464 } | 1473 } |
1465 | 1474 |
1466 | 1475 |
1467 void Assembler::andl(Register dst, const Immediate& imm) { | 1476 void Assembler::andl(Register dst, const Immediate& imm) { |
1468 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | 1477 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
1469 EmitComplex(4, Operand(dst), imm); | 1478 EmitComplex(4, Operand(dst), imm); |
(...skipping 735 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2205 // Mask out higher, uninteresting bits which were polluted by dest. | 2214 // Mask out higher, uninteresting bits which were polluted by dest. |
2206 andl(value, Immediate(kObjectAlignment - 1)); | 2215 andl(value, Immediate(kObjectAlignment - 1)); |
2207 // Compare with the expected bit pattern. | 2216 // Compare with the expected bit pattern. |
2208 cmpl(value, Immediate( | 2217 cmpl(value, Immediate( |
2209 (kNewObjectAlignmentOffset >> 1) + kHeapObjectTag + | 2218 (kNewObjectAlignmentOffset >> 1) + kHeapObjectTag + |
2210 kOldObjectAlignmentOffset + kHeapObjectTag)); | 2219 kOldObjectAlignmentOffset + kHeapObjectTag)); |
2211 j(NOT_ZERO, no_update, Assembler::kNearJump); | 2220 j(NOT_ZERO, no_update, Assembler::kNearJump); |
2212 } | 2221 } |
2213 | 2222 |
2214 | 2223 |
2215 void Assembler::VerifyHeapWord(const Address& address) { | 2224 void Assembler::VerifyHeapWord(const Address& address, |
2225 FieldContent old_content) { | |
2226 #if defined(DEBUG) | |
2227 switch (old_content) { | |
2228 case kEmptySmiOrNull: | |
2229 VerifyUninitialized(address); | |
2230 break; | |
2231 case kHeapObjectOrSmi: | |
2232 VerifyObjectOrSmi(address); | |
2233 break; | |
2234 case kOnlySmi: | |
2235 VerifySmi(address); | |
2236 break; | |
2237 } | |
2238 #endif // DEBUG | |
2216 if (VerifiedMemory::enabled()) { | 2239 if (VerifiedMemory::enabled()) { |
2217 Register addr_reg = EDX; | 2240 Register addr_reg = EDX; |
2218 Register value = EBX; | 2241 Register value = EBX; |
2219 // Preserve registers. | 2242 // Preserve registers. |
2220 pushl(addr_reg); | 2243 pushl(addr_reg); |
2221 pushl(value); | 2244 pushl(value); |
2222 leal(addr_reg, address); | 2245 leal(addr_reg, address); |
2223 // ASSERT(*address == *(address + offset)) | 2246 // ASSERT(*address == *(address + offset)) |
2224 movl(value, Address(addr_reg, 0)); | 2247 movl(value, Address(addr_reg, 0)); |
2225 cmpl(value, Address(addr_reg, VerifiedMemory::offset())); | 2248 cmpl(value, Address(addr_reg, VerifiedMemory::offset())); |
2226 Label ok; | 2249 Label ok; |
2227 j(EQUAL, &ok, Assembler::kNearJump); | 2250 j(EQUAL, &ok, Assembler::kNearJump); |
2228 Stop("Write barrier verification failed"); | 2251 Stop("Write barrier verification failed"); |
2229 Bind(&ok); | 2252 Bind(&ok); |
2230 popl(value); | 2253 popl(value); |
2231 popl(addr_reg); | 2254 popl(addr_reg); |
2232 } | 2255 } |
2233 } | 2256 } |
2234 | 2257 |
2235 | 2258 |
2236 void Assembler::VerifiedWrite(const Address& dest, Register value) { | 2259 void Assembler::VerifiedWrite(const Address& dest, |
2237 VerifyHeapWord(dest); | 2260 Register value, |
2261 FieldContent old_content) { | |
2262 VerifyHeapWord(dest, old_content); | |
2238 movl(dest, value); | 2263 movl(dest, value); |
2239 if (VerifiedMemory::enabled()) { | 2264 if (VerifiedMemory::enabled()) { |
2240 Register temp = (value == EDX) ? ECX : EDX; | 2265 Register temp = (value == EDX) ? ECX : EDX; |
2241 pushl(temp); | 2266 pushl(temp); |
2242 leal(temp, dest); | 2267 leal(temp, dest); |
2243 movl(Address(temp, VerifiedMemory::offset()), value); | 2268 movl(Address(temp, VerifiedMemory::offset()), value); |
2244 popl(temp); | 2269 popl(temp); |
2245 } | 2270 } |
2246 } | 2271 } |
2247 | 2272 |
2248 | 2273 |
2274 #if defined(DEBUG) | |
2275 void Assembler::VerifyObjectOrSmi(const Address& dest) { | |
2276 Label ok; | |
2277 testb(dest, Immediate(kHeapObjectTag)); | |
2278 j(ZERO, &ok, Assembler::kNearJump); | |
2279 // Non-smi case: Verify object pointer is word-aligned when untagged. | |
2280 COMPILE_ASSERT(kHeapObjectTag == 1); | |
2281 testb(dest, Immediate((kWordSize - 1) - kHeapObjectTag)); | |
2282 j(ZERO, &ok, Assembler::kNearJump); | |
2283 Stop("Expected heap object or Smi"); | |
2284 Bind(&ok); | |
2285 } | |
2286 | |
2287 | |
2288 void Assembler::VerifyUninitialized(const Address& dest) { | |
2289 Label ok; | |
2290 testb(dest, Immediate(kHeapObjectTag)); | |
Ivan Posva
2015/01/08 19:34:51
// Check for Smi.
or as above explain the "// Non
koda
2015/01/08 20:25:34
Done.
| |
2291 j(ZERO, &ok, Assembler::kNearJump); | |
2292 cmpl(dest, Immediate(Heap::kZap32Bits)); | |
2293 j(EQUAL, &ok, Assembler::kNearJump); | |
2294 cmpl(dest, Immediate(reinterpret_cast<uint32_t>(Object::null()))); | |
2295 j(EQUAL, &ok, Assembler::kNearJump); | |
2296 Stop("Expected zapped, Smi or null"); | |
2297 Bind(&ok); | |
2298 } | |
2299 | |
2300 | |
2301 void Assembler::VerifySmi(const Address& dest, const char* stop_msg) { | |
2302 Label done; | |
2303 testb(dest, Immediate(kHeapObjectTag)); | |
2304 j(ZERO, &done, Assembler::kNearJump); | |
2305 Stop(stop_msg); | |
2306 Bind(&done); | |
2307 } | |
2308 #endif // defined(DEBUG) | |
2309 | |
2310 | |
2249 // Destroys the value register. | 2311 // Destroys the value register. |
2250 void Assembler::StoreIntoObject(Register object, | 2312 void Assembler::StoreIntoObject(Register object, |
2251 const Address& dest, | 2313 const Address& dest, |
2252 Register value, | 2314 Register value, |
2253 bool can_value_be_smi) { | 2315 bool can_value_be_smi) { |
2254 ASSERT(object != value); | 2316 ASSERT(object != value); |
2255 VerifiedWrite(dest, value); | 2317 VerifiedWrite(dest, value, kHeapObjectOrSmi); |
2256 Label done; | 2318 Label done; |
2257 if (can_value_be_smi) { | 2319 if (can_value_be_smi) { |
2258 StoreIntoObjectFilter(object, value, &done); | 2320 StoreIntoObjectFilter(object, value, &done); |
2259 } else { | 2321 } else { |
2260 StoreIntoObjectFilterNoSmi(object, value, &done); | 2322 StoreIntoObjectFilterNoSmi(object, value, &done); |
2261 } | 2323 } |
2262 // A store buffer update is required. | 2324 // A store buffer update is required. |
2263 if (value != EDX) { | 2325 if (value != EDX) { |
2264 pushl(EDX); // Preserve EDX. | 2326 pushl(EDX); // Preserve EDX. |
2265 } | 2327 } |
2266 if (object != EDX) { | 2328 if (object != EDX) { |
2267 movl(EDX, object); | 2329 movl(EDX, object); |
2268 } | 2330 } |
2269 StubCode* stub_code = Isolate::Current()->stub_code(); | 2331 StubCode* stub_code = Isolate::Current()->stub_code(); |
2270 call(&stub_code->UpdateStoreBufferLabel()); | 2332 call(&stub_code->UpdateStoreBufferLabel()); |
2271 if (value != EDX) { | 2333 if (value != EDX) { |
2272 popl(EDX); // Restore EDX. | 2334 popl(EDX); // Restore EDX. |
2273 } | 2335 } |
2274 Bind(&done); | 2336 Bind(&done); |
2275 } | 2337 } |
2276 | 2338 |
2277 | 2339 |
2278 void Assembler::StoreIntoObjectNoBarrier(Register object, | 2340 void Assembler::StoreIntoObjectNoBarrier(Register object, |
2279 const Address& dest, | 2341 const Address& dest, |
2280 Register value) { | 2342 Register value, |
2281 VerifiedWrite(dest, value); | 2343 FieldContent old_content) { |
2344 VerifiedWrite(dest, value, old_content); | |
2282 #if defined(DEBUG) | 2345 #if defined(DEBUG) |
2283 Label done; | 2346 Label done; |
2284 pushl(value); | 2347 pushl(value); |
2285 StoreIntoObjectFilter(object, value, &done); | 2348 StoreIntoObjectFilter(object, value, &done); |
2286 Stop("Store buffer update is required"); | 2349 Stop("Store buffer update is required"); |
2287 Bind(&done); | 2350 Bind(&done); |
2288 popl(value); | 2351 popl(value); |
2289 #endif // defined(DEBUG) | 2352 #endif // defined(DEBUG) |
2290 // No store buffer update. | 2353 // No store buffer update. |
2291 } | 2354 } |
2292 | 2355 |
2293 | 2356 |
2294 void Assembler::UnverifiedStoreOldObject(const Address& dest, | 2357 void Assembler::UnverifiedStoreOldObject(const Address& dest, |
2295 const Object& value) { | 2358 const Object& value) { |
2296 ASSERT(value.IsOld()); | 2359 ASSERT(value.IsOld()); |
2297 ASSERT(!value.InVMHeap()); | 2360 ASSERT(!value.InVMHeap()); |
2298 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | 2361 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
2299 EmitUint8(0xC7); | 2362 EmitUint8(0xC7); |
2300 EmitOperand(0, dest); | 2363 EmitOperand(0, dest); |
2301 buffer_.EmitObject(value); | 2364 buffer_.EmitObject(value); |
2302 } | 2365 } |
2303 | 2366 |
2304 | 2367 |
2305 void Assembler::StoreIntoObjectNoBarrier(Register object, | 2368 void Assembler::StoreIntoObjectNoBarrier(Register object, |
2306 const Address& dest, | 2369 const Address& dest, |
2307 const Object& value) { | 2370 const Object& value, |
2308 VerifyHeapWord(dest); | 2371 FieldContent old_content) { |
2372 VerifyHeapWord(dest, old_content); | |
2309 if (value.IsSmi() || value.InVMHeap()) { | 2373 if (value.IsSmi() || value.InVMHeap()) { |
2310 Immediate imm_value(reinterpret_cast<int32_t>(value.raw())); | 2374 Immediate imm_value(reinterpret_cast<int32_t>(value.raw())); |
2311 movl(dest, imm_value); | 2375 movl(dest, imm_value); |
2312 if (VerifiedMemory::enabled()) { | 2376 if (VerifiedMemory::enabled()) { |
2313 Register temp = ECX; | 2377 Register temp = ECX; |
2314 pushl(temp); | 2378 pushl(temp); |
2315 leal(temp, dest); | 2379 leal(temp, dest); |
2316 movl(Address(temp, VerifiedMemory::offset()), imm_value); | 2380 movl(Address(temp, VerifiedMemory::offset()), imm_value); |
2317 popl(temp); | 2381 popl(temp); |
2318 } | 2382 } |
2319 } else { | 2383 } else { |
2320 UnverifiedStoreOldObject(dest, value); | 2384 UnverifiedStoreOldObject(dest, value); |
2321 if (VerifiedMemory::enabled()) { | 2385 if (VerifiedMemory::enabled()) { |
2322 Register temp = EDX; | 2386 Register temp = EDX; |
2323 pushl(temp); | 2387 pushl(temp); |
2324 leal(temp, dest); | 2388 leal(temp, dest); |
2325 UnverifiedStoreOldObject(Address(temp, VerifiedMemory::offset()), value); | 2389 UnverifiedStoreOldObject(Address(temp, VerifiedMemory::offset()), value); |
2326 popl(temp); | 2390 popl(temp); |
2327 } | 2391 } |
2328 } | 2392 } |
2329 // No store buffer update. | 2393 // No store buffer update. |
2330 } | 2394 } |
2331 | 2395 |
2332 | 2396 |
2333 void Assembler::StoreIntoSmiField(const Address& dest, Register value) { | 2397 void Assembler::StoreIntoSmiField(const Address& dest, Register value) { |
2334 VerifiedWrite(dest, value); | 2398 VerifiedWrite(dest, value, kOnlySmi); |
2335 #if defined(DEBUG) | 2399 #if defined(DEBUG) |
2336 Label done; | 2400 VerifySmi(dest, "New value must be Smi."); |
Ivan Posva
2015/01/08 19:34:51
Why are you checking that the value is Smi after t
koda
2015/01/08 20:25:34
Done.
| |
2337 testl(value, Immediate(kHeapObjectTag)); | |
2338 j(ZERO, &done); | |
2339 Stop("Smi expected"); | |
2340 Bind(&done); | |
2341 #endif // defined(DEBUG) | 2401 #endif // defined(DEBUG) |
2342 } | 2402 } |
2343 | 2403 |
2344 | 2404 |
2345 void Assembler::ZeroSmiField(const Address& dest) { | 2405 void Assembler::ZeroSmiField(const Address& dest) { |
Ivan Posva
2015/01/08 19:34:51
Is this only used in initializing writes?
koda
2015/01/08 20:25:33
Yes. Renamed to clarify this.
| |
2346 // TODO(koda): Add VerifySmi once we distinguish initalization. | 2406 VerifyHeapWord(dest, kEmptySmiOrNull); |
2347 VerifyHeapWord(dest); | |
2348 Immediate zero(Smi::RawValue(0)); | 2407 Immediate zero(Smi::RawValue(0)); |
2349 movl(dest, zero); | 2408 movl(dest, zero); |
2350 if (VerifiedMemory::enabled()) { | 2409 if (VerifiedMemory::enabled()) { |
2351 Register temp = ECX; | 2410 Register temp = ECX; |
2352 pushl(temp); | 2411 pushl(temp); |
2353 leal(temp, dest); | 2412 leal(temp, dest); |
2354 movl(Address(temp, VerifiedMemory::offset()), zero); | 2413 movl(Address(temp, VerifiedMemory::offset()), zero); |
2355 popl(temp); | 2414 popl(temp); |
2356 } | 2415 } |
2357 } | 2416 } |
2358 | 2417 |
2359 | 2418 |
2360 void Assembler::IncrementSmiField(const Address& dest, int32_t increment) { | 2419 void Assembler::IncrementSmiField(const Address& dest, int32_t increment) { |
2361 // Note: FlowGraphCompiler::EdgeCounterIncrementSizeInBytes depends on | 2420 // Note: FlowGraphCompiler::EdgeCounterIncrementSizeInBytes depends on |
2362 // the length of this instruction sequence. | 2421 // the length of this instruction sequence. |
2363 // TODO(koda): Add VerifySmi once we distinguish initalization. | 2422 VerifyHeapWord(dest, kOnlySmi); |
2364 VerifyHeapWord(dest); | |
2365 Immediate inc_imm(Smi::RawValue(increment)); | 2423 Immediate inc_imm(Smi::RawValue(increment)); |
2366 addl(dest, inc_imm); | 2424 addl(dest, inc_imm); |
2367 if (VerifiedMemory::enabled()) { | 2425 if (VerifiedMemory::enabled()) { |
2368 Register temp = ECX; | 2426 Register temp = ECX; |
2369 pushl(temp); | 2427 pushl(temp); |
2370 leal(temp, dest); | 2428 leal(temp, dest); |
2371 addl(Address(temp, VerifiedMemory::offset()), inc_imm); | 2429 addl(Address(temp, VerifiedMemory::offset()), inc_imm); |
2372 popl(temp); | 2430 popl(temp); |
2373 } | 2431 } |
2374 } | 2432 } |
(...skipping 659 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3034 | 3092 |
3035 const char* Assembler::FpuRegisterName(FpuRegister reg) { | 3093 const char* Assembler::FpuRegisterName(FpuRegister reg) { |
3036 ASSERT((0 <= reg) && (reg < kNumberOfXmmRegisters)); | 3094 ASSERT((0 <= reg) && (reg < kNumberOfXmmRegisters)); |
3037 return xmm_reg_names[reg]; | 3095 return xmm_reg_names[reg]; |
3038 } | 3096 } |
3039 | 3097 |
3040 | 3098 |
3041 } // namespace dart | 3099 } // namespace dart |
3042 | 3100 |
3043 #endif // defined TARGET_ARCH_IA32 | 3101 #endif // defined TARGET_ARCH_IA32 |
OLD | NEW |