Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(11)

Side by Side Diff: runtime/vm/assembler_ia32.cc

Issue 836593002: Deletion barrier: Distinguish+verify field initialization in ia32 generated code. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 5 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698