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 kEmptyOrSmiOrNull: |
| 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)); |
| 2291 j(ZERO, &ok, Assembler::kNearJump); |
| 2292 // Non-smi case: Check for the special zap word or null. |
| 2293 cmpl(dest, Immediate(Heap::kZap32Bits)); |
| 2294 j(EQUAL, &ok, Assembler::kNearJump); |
| 2295 cmpl(dest, Immediate(reinterpret_cast<uint32_t>(Object::null()))); |
| 2296 j(EQUAL, &ok, Assembler::kNearJump); |
| 2297 Stop("Expected zapped, Smi or null"); |
| 2298 Bind(&ok); |
| 2299 } |
| 2300 |
| 2301 |
| 2302 void Assembler::VerifySmi(const Address& dest, const char* stop_msg) { |
| 2303 Label done; |
| 2304 testb(dest, Immediate(kHeapObjectTag)); |
| 2305 j(ZERO, &done, Assembler::kNearJump); |
| 2306 Stop(stop_msg); |
| 2307 Bind(&done); |
| 2308 } |
| 2309 #endif // defined(DEBUG) |
| 2310 |
| 2311 |
2249 // Destroys the value register. | 2312 // Destroys the value register. |
2250 void Assembler::StoreIntoObject(Register object, | 2313 void Assembler::StoreIntoObject(Register object, |
2251 const Address& dest, | 2314 const Address& dest, |
2252 Register value, | 2315 Register value, |
2253 bool can_value_be_smi) { | 2316 bool can_value_be_smi) { |
2254 ASSERT(object != value); | 2317 ASSERT(object != value); |
2255 VerifiedWrite(dest, value); | 2318 VerifiedWrite(dest, value, kHeapObjectOrSmi); |
2256 Label done; | 2319 Label done; |
2257 if (can_value_be_smi) { | 2320 if (can_value_be_smi) { |
2258 StoreIntoObjectFilter(object, value, &done); | 2321 StoreIntoObjectFilter(object, value, &done); |
2259 } else { | 2322 } else { |
2260 StoreIntoObjectFilterNoSmi(object, value, &done); | 2323 StoreIntoObjectFilterNoSmi(object, value, &done); |
2261 } | 2324 } |
2262 // A store buffer update is required. | 2325 // A store buffer update is required. |
2263 if (value != EDX) { | 2326 if (value != EDX) { |
2264 pushl(EDX); // Preserve EDX. | 2327 pushl(EDX); // Preserve EDX. |
2265 } | 2328 } |
2266 if (object != EDX) { | 2329 if (object != EDX) { |
2267 movl(EDX, object); | 2330 movl(EDX, object); |
2268 } | 2331 } |
2269 StubCode* stub_code = Isolate::Current()->stub_code(); | 2332 StubCode* stub_code = Isolate::Current()->stub_code(); |
2270 call(&stub_code->UpdateStoreBufferLabel()); | 2333 call(&stub_code->UpdateStoreBufferLabel()); |
2271 if (value != EDX) { | 2334 if (value != EDX) { |
2272 popl(EDX); // Restore EDX. | 2335 popl(EDX); // Restore EDX. |
2273 } | 2336 } |
2274 Bind(&done); | 2337 Bind(&done); |
2275 } | 2338 } |
2276 | 2339 |
2277 | 2340 |
2278 void Assembler::StoreIntoObjectNoBarrier(Register object, | 2341 void Assembler::StoreIntoObjectNoBarrier(Register object, |
2279 const Address& dest, | 2342 const Address& dest, |
2280 Register value) { | 2343 Register value, |
2281 VerifiedWrite(dest, value); | 2344 FieldContent old_content) { |
| 2345 VerifiedWrite(dest, value, old_content); |
2282 #if defined(DEBUG) | 2346 #if defined(DEBUG) |
2283 Label done; | 2347 Label done; |
2284 pushl(value); | 2348 pushl(value); |
2285 StoreIntoObjectFilter(object, value, &done); | 2349 StoreIntoObjectFilter(object, value, &done); |
2286 Stop("Store buffer update is required"); | 2350 Stop("Store buffer update is required"); |
2287 Bind(&done); | 2351 Bind(&done); |
2288 popl(value); | 2352 popl(value); |
2289 #endif // defined(DEBUG) | 2353 #endif // defined(DEBUG) |
2290 // No store buffer update. | 2354 // No store buffer update. |
2291 } | 2355 } |
2292 | 2356 |
2293 | 2357 |
2294 void Assembler::UnverifiedStoreOldObject(const Address& dest, | 2358 void Assembler::UnverifiedStoreOldObject(const Address& dest, |
2295 const Object& value) { | 2359 const Object& value) { |
2296 ASSERT(value.IsOld()); | 2360 ASSERT(value.IsOld()); |
2297 ASSERT(!value.InVMHeap()); | 2361 ASSERT(!value.InVMHeap()); |
2298 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | 2362 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
2299 EmitUint8(0xC7); | 2363 EmitUint8(0xC7); |
2300 EmitOperand(0, dest); | 2364 EmitOperand(0, dest); |
2301 buffer_.EmitObject(value); | 2365 buffer_.EmitObject(value); |
2302 } | 2366 } |
2303 | 2367 |
2304 | 2368 |
2305 void Assembler::StoreIntoObjectNoBarrier(Register object, | 2369 void Assembler::StoreIntoObjectNoBarrier(Register object, |
2306 const Address& dest, | 2370 const Address& dest, |
2307 const Object& value) { | 2371 const Object& value, |
2308 VerifyHeapWord(dest); | 2372 FieldContent old_content) { |
| 2373 VerifyHeapWord(dest, old_content); |
2309 if (value.IsSmi() || value.InVMHeap()) { | 2374 if (value.IsSmi() || value.InVMHeap()) { |
2310 Immediate imm_value(reinterpret_cast<int32_t>(value.raw())); | 2375 Immediate imm_value(reinterpret_cast<int32_t>(value.raw())); |
2311 movl(dest, imm_value); | 2376 movl(dest, imm_value); |
2312 if (VerifiedMemory::enabled()) { | 2377 if (VerifiedMemory::enabled()) { |
2313 Register temp = ECX; | 2378 Register temp = ECX; |
2314 pushl(temp); | 2379 pushl(temp); |
2315 leal(temp, dest); | 2380 leal(temp, dest); |
2316 movl(Address(temp, VerifiedMemory::offset()), imm_value); | 2381 movl(Address(temp, VerifiedMemory::offset()), imm_value); |
2317 popl(temp); | 2382 popl(temp); |
2318 } | 2383 } |
2319 } else { | 2384 } else { |
2320 UnverifiedStoreOldObject(dest, value); | 2385 UnverifiedStoreOldObject(dest, value); |
2321 if (VerifiedMemory::enabled()) { | 2386 if (VerifiedMemory::enabled()) { |
2322 Register temp = EDX; | 2387 Register temp = EDX; |
2323 pushl(temp); | 2388 pushl(temp); |
2324 leal(temp, dest); | 2389 leal(temp, dest); |
2325 UnverifiedStoreOldObject(Address(temp, VerifiedMemory::offset()), value); | 2390 UnverifiedStoreOldObject(Address(temp, VerifiedMemory::offset()), value); |
2326 popl(temp); | 2391 popl(temp); |
2327 } | 2392 } |
2328 } | 2393 } |
2329 // No store buffer update. | 2394 // No store buffer update. |
2330 } | 2395 } |
2331 | 2396 |
2332 | 2397 |
2333 void Assembler::StoreIntoSmiField(const Address& dest, Register value) { | 2398 void Assembler::StoreIntoSmiField(const Address& dest, Register value) { |
2334 VerifiedWrite(dest, value); | |
2335 #if defined(DEBUG) | 2399 #if defined(DEBUG) |
2336 Label done; | 2400 Label done; |
2337 testl(value, Immediate(kHeapObjectTag)); | 2401 testl(value, Immediate(kHeapObjectTag)); |
2338 j(ZERO, &done); | 2402 j(ZERO, &done); |
2339 Stop("Smi expected"); | 2403 Stop("New value must be Smi."); |
2340 Bind(&done); | 2404 Bind(&done); |
2341 #endif // defined(DEBUG) | 2405 #endif // defined(DEBUG) |
| 2406 VerifiedWrite(dest, value, kOnlySmi); |
2342 } | 2407 } |
2343 | 2408 |
2344 | 2409 |
2345 void Assembler::ZeroSmiField(const Address& dest) { | 2410 void Assembler::ZeroInitSmiField(const Address& dest) { |
2346 // TODO(koda): Add VerifySmi once we distinguish initalization. | 2411 VerifyHeapWord(dest, kEmptyOrSmiOrNull); |
2347 VerifyHeapWord(dest); | |
2348 Immediate zero(Smi::RawValue(0)); | 2412 Immediate zero(Smi::RawValue(0)); |
2349 movl(dest, zero); | 2413 movl(dest, zero); |
2350 if (VerifiedMemory::enabled()) { | 2414 if (VerifiedMemory::enabled()) { |
2351 Register temp = ECX; | 2415 Register temp = ECX; |
2352 pushl(temp); | 2416 pushl(temp); |
2353 leal(temp, dest); | 2417 leal(temp, dest); |
2354 movl(Address(temp, VerifiedMemory::offset()), zero); | 2418 movl(Address(temp, VerifiedMemory::offset()), zero); |
2355 popl(temp); | 2419 popl(temp); |
2356 } | 2420 } |
2357 } | 2421 } |
2358 | 2422 |
2359 | 2423 |
2360 void Assembler::IncrementSmiField(const Address& dest, int32_t increment) { | 2424 void Assembler::IncrementSmiField(const Address& dest, int32_t increment) { |
2361 // Note: FlowGraphCompiler::EdgeCounterIncrementSizeInBytes depends on | 2425 // Note: FlowGraphCompiler::EdgeCounterIncrementSizeInBytes depends on |
2362 // the length of this instruction sequence. | 2426 // the length of this instruction sequence. |
2363 // TODO(koda): Add VerifySmi once we distinguish initalization. | 2427 VerifyHeapWord(dest, kOnlySmi); |
2364 VerifyHeapWord(dest); | |
2365 Immediate inc_imm(Smi::RawValue(increment)); | 2428 Immediate inc_imm(Smi::RawValue(increment)); |
2366 addl(dest, inc_imm); | 2429 addl(dest, inc_imm); |
2367 if (VerifiedMemory::enabled()) { | 2430 if (VerifiedMemory::enabled()) { |
2368 Register temp = ECX; | 2431 Register temp = ECX; |
2369 pushl(temp); | 2432 pushl(temp); |
2370 leal(temp, dest); | 2433 leal(temp, dest); |
2371 addl(Address(temp, VerifiedMemory::offset()), inc_imm); | 2434 addl(Address(temp, VerifiedMemory::offset()), inc_imm); |
2372 popl(temp); | 2435 popl(temp); |
2373 } | 2436 } |
2374 } | 2437 } |
(...skipping 659 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3034 | 3097 |
3035 const char* Assembler::FpuRegisterName(FpuRegister reg) { | 3098 const char* Assembler::FpuRegisterName(FpuRegister reg) { |
3036 ASSERT((0 <= reg) && (reg < kNumberOfXmmRegisters)); | 3099 ASSERT((0 <= reg) && (reg < kNumberOfXmmRegisters)); |
3037 return xmm_reg_names[reg]; | 3100 return xmm_reg_names[reg]; |
3038 } | 3101 } |
3039 | 3102 |
3040 | 3103 |
3041 } // namespace dart | 3104 } // namespace dart |
3042 | 3105 |
3043 #endif // defined TARGET_ARCH_IA32 | 3106 #endif // defined TARGET_ARCH_IA32 |
OLD | NEW |