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" // 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 |