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" |
(...skipping 1927 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1938 | 1938 |
1939 | 1939 |
1940 void Assembler::hlt() { | 1940 void Assembler::hlt() { |
1941 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | 1941 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
1942 EmitUint8(0xF4); | 1942 EmitUint8(0xF4); |
1943 } | 1943 } |
1944 | 1944 |
1945 | 1945 |
1946 void Assembler::j(Condition condition, Label* label, bool near) { | 1946 void Assembler::j(Condition condition, Label* label, bool near) { |
1947 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | 1947 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1948 if (VerifiedMemory::enabled()) { |
| 1949 near = Assembler::kFarJump; |
| 1950 } |
1948 if (label->IsBound()) { | 1951 if (label->IsBound()) { |
1949 static const int kShortSize = 2; | 1952 static const int kShortSize = 2; |
1950 static const int kLongSize = 6; | 1953 static const int kLongSize = 6; |
1951 intptr_t offset = label->Position() - buffer_.Size(); | 1954 intptr_t offset = label->Position() - buffer_.Size(); |
1952 ASSERT(offset <= 0); | 1955 ASSERT(offset <= 0); |
1953 if (Utils::IsInt(8, offset - kShortSize)) { | 1956 if (Utils::IsInt(8, offset - kShortSize)) { |
1954 EmitUint8(0x70 + condition); | 1957 EmitUint8(0x70 + condition); |
1955 EmitUint8((offset - kShortSize) & 0xFF); | 1958 EmitUint8((offset - kShortSize) & 0xFF); |
1956 } else { | 1959 } else { |
1957 EmitUint8(0x0F); | 1960 EmitUint8(0x0F); |
(...skipping 22 matching lines...) Expand all Loading... |
1980 | 1983 |
1981 void Assembler::jmp(Register reg) { | 1984 void Assembler::jmp(Register reg) { |
1982 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | 1985 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
1983 EmitUint8(0xFF); | 1986 EmitUint8(0xFF); |
1984 EmitRegisterOperand(4, reg); | 1987 EmitRegisterOperand(4, reg); |
1985 } | 1988 } |
1986 | 1989 |
1987 | 1990 |
1988 void Assembler::jmp(Label* label, bool near) { | 1991 void Assembler::jmp(Label* label, bool near) { |
1989 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | 1992 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1993 if (VerifiedMemory::enabled()) { |
| 1994 near = Assembler::kFarJump; |
| 1995 } |
1990 if (label->IsBound()) { | 1996 if (label->IsBound()) { |
1991 static const int kShortSize = 2; | 1997 static const int kShortSize = 2; |
1992 static const int kLongSize = 5; | 1998 static const int kLongSize = 5; |
1993 intptr_t offset = label->Position() - buffer_.Size(); | 1999 intptr_t offset = label->Position() - buffer_.Size(); |
1994 ASSERT(offset <= 0); | 2000 ASSERT(offset <= 0); |
1995 if (Utils::IsInt(8, offset - kShortSize)) { | 2001 if (Utils::IsInt(8, offset - kShortSize)) { |
1996 EmitUint8(0xEB); | 2002 EmitUint8(0xEB); |
1997 EmitUint8((offset - kShortSize) & 0xFF); | 2003 EmitUint8((offset - kShortSize) & 0xFF); |
1998 } else { | 2004 } else { |
1999 EmitUint8(0xE9); | 2005 EmitUint8(0xE9); |
(...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2192 // Mask out higher, uninteresting bits which were polluted by dest. | 2198 // Mask out higher, uninteresting bits which were polluted by dest. |
2193 andl(value, Immediate(kObjectAlignment - 1)); | 2199 andl(value, Immediate(kObjectAlignment - 1)); |
2194 // Compare with the expected bit pattern. | 2200 // Compare with the expected bit pattern. |
2195 cmpl(value, Immediate( | 2201 cmpl(value, Immediate( |
2196 (kNewObjectAlignmentOffset >> 1) + kHeapObjectTag + | 2202 (kNewObjectAlignmentOffset >> 1) + kHeapObjectTag + |
2197 kOldObjectAlignmentOffset + kHeapObjectTag)); | 2203 kOldObjectAlignmentOffset + kHeapObjectTag)); |
2198 j(NOT_ZERO, no_update, Assembler::kNearJump); | 2204 j(NOT_ZERO, no_update, Assembler::kNearJump); |
2199 } | 2205 } |
2200 | 2206 |
2201 | 2207 |
| 2208 void Assembler::VerifyHeapWord(const Address& address) { |
| 2209 if (VerifiedMemory::enabled()) { |
| 2210 Register addr_reg = EDX; |
| 2211 Register value = EBX; |
| 2212 // Preserve registers. |
| 2213 pushl(addr_reg); |
| 2214 pushl(value); |
| 2215 leal(addr_reg, address); |
| 2216 // ASSERT(*address == *(address + offset)) |
| 2217 movl(value, Address(addr_reg, 0)); |
| 2218 cmpl(value, Address(addr_reg, VerifiedMemory::offset())); |
| 2219 Label ok; |
| 2220 j(EQUAL, &ok, Assembler::kNearJump); |
| 2221 Stop("Write barrier verification failed"); |
| 2222 Bind(&ok); |
| 2223 popl(value); |
| 2224 popl(addr_reg); |
| 2225 } |
| 2226 } |
| 2227 |
| 2228 |
2202 void Assembler::VerifiedWrite(const Address& dest, Register value) { | 2229 void Assembler::VerifiedWrite(const Address& dest, Register value) { |
2203 // TODO(koda): Verify previous value. | 2230 VerifyHeapWord(dest); |
2204 movl(dest, value); | 2231 movl(dest, value); |
2205 if (VerifiedMemory::enabled()) { | 2232 if (VerifiedMemory::enabled()) { |
2206 Register temp = (value == EDX) ? ECX : EDX; | 2233 Register temp = (value == EDX) ? ECX : EDX; |
2207 pushl(temp); | 2234 pushl(temp); |
2208 leal(temp, dest); | 2235 leal(temp, dest); |
2209 movl(Address(temp, VerifiedMemory::offset()), value); | 2236 movl(Address(temp, VerifiedMemory::offset()), value); |
2210 popl(temp); | 2237 popl(temp); |
2211 } | 2238 } |
2212 } | 2239 } |
2213 | 2240 |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2264 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | 2291 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
2265 EmitUint8(0xC7); | 2292 EmitUint8(0xC7); |
2266 EmitOperand(0, dest); | 2293 EmitOperand(0, dest); |
2267 buffer_.EmitObject(value); | 2294 buffer_.EmitObject(value); |
2268 } | 2295 } |
2269 | 2296 |
2270 | 2297 |
2271 void Assembler::StoreIntoObjectNoBarrier(Register object, | 2298 void Assembler::StoreIntoObjectNoBarrier(Register object, |
2272 const Address& dest, | 2299 const Address& dest, |
2273 const Object& value) { | 2300 const Object& value) { |
| 2301 VerifyHeapWord(dest); |
2274 if (value.IsSmi() || value.InVMHeap()) { | 2302 if (value.IsSmi() || value.InVMHeap()) { |
2275 // TODO(koda): Verify previous value. | |
2276 Immediate imm_value(reinterpret_cast<int32_t>(value.raw())); | 2303 Immediate imm_value(reinterpret_cast<int32_t>(value.raw())); |
2277 movl(dest, imm_value); | 2304 movl(dest, imm_value); |
2278 if (VerifiedMemory::enabled()) { | 2305 if (VerifiedMemory::enabled()) { |
2279 Register temp = ECX; | 2306 Register temp = ECX; |
2280 pushl(temp); | 2307 pushl(temp); |
2281 leal(temp, dest); | 2308 leal(temp, dest); |
2282 movl(Address(temp, VerifiedMemory::offset()), imm_value); | 2309 movl(Address(temp, VerifiedMemory::offset()), imm_value); |
2283 popl(temp); | 2310 popl(temp); |
2284 } | 2311 } |
2285 } else { | 2312 } else { |
(...skipping 16 matching lines...) Expand all Loading... |
2302 Label done; | 2329 Label done; |
2303 testl(value, Immediate(kHeapObjectTag)); | 2330 testl(value, Immediate(kHeapObjectTag)); |
2304 j(ZERO, &done); | 2331 j(ZERO, &done); |
2305 Stop("Smi expected"); | 2332 Stop("Smi expected"); |
2306 Bind(&done); | 2333 Bind(&done); |
2307 #endif // defined(DEBUG) | 2334 #endif // defined(DEBUG) |
2308 } | 2335 } |
2309 | 2336 |
2310 | 2337 |
2311 void Assembler::ZeroSmiField(const Address& dest) { | 2338 void Assembler::ZeroSmiField(const Address& dest) { |
| 2339 // TODO(koda): Add VerifySmi once we distinguish initalization. |
| 2340 VerifyHeapWord(dest); |
2312 Immediate zero(Smi::RawValue(0)); | 2341 Immediate zero(Smi::RawValue(0)); |
2313 // TODO(koda): Verify previous value. | |
2314 movl(dest, zero); | 2342 movl(dest, zero); |
2315 if (VerifiedMemory::enabled()) { | 2343 if (VerifiedMemory::enabled()) { |
2316 Register temp = ECX; | 2344 Register temp = ECX; |
2317 pushl(temp); | 2345 pushl(temp); |
2318 leal(temp, dest); | 2346 leal(temp, dest); |
2319 movl(Address(temp, VerifiedMemory::offset()), zero); | 2347 movl(Address(temp, VerifiedMemory::offset()), zero); |
2320 popl(temp); | 2348 popl(temp); |
2321 } | 2349 } |
2322 } | 2350 } |
2323 | 2351 |
2324 | 2352 |
2325 void Assembler::IncrementSmiField(const Address& dest, int32_t increment) { | 2353 void Assembler::IncrementSmiField(const Address& dest, int32_t increment) { |
2326 // Note: FlowGraphCompiler::EdgeCounterIncrementSizeInBytes depends on | 2354 // Note: FlowGraphCompiler::EdgeCounterIncrementSizeInBytes depends on |
2327 // the length of this instruction sequence. | 2355 // the length of this instruction sequence. |
2328 // | 2356 // TODO(koda): Add VerifySmi once we distinguish initalization. |
2329 // TODO(koda): Implement testl for addresses and check that dest is a smi. | 2357 VerifyHeapWord(dest); |
2330 Immediate inc_imm(Smi::RawValue(increment)); | 2358 Immediate inc_imm(Smi::RawValue(increment)); |
2331 addl(dest, inc_imm); | 2359 addl(dest, inc_imm); |
2332 if (VerifiedMemory::enabled()) { | 2360 if (VerifiedMemory::enabled()) { |
2333 Register temp = ECX; | 2361 Register temp = ECX; |
2334 pushl(temp); | 2362 pushl(temp); |
2335 leal(temp, dest); | 2363 leal(temp, dest); |
2336 addl(Address(temp, VerifiedMemory::offset()), inc_imm); | 2364 addl(Address(temp, VerifiedMemory::offset()), inc_imm); |
2337 popl(temp); | 2365 popl(temp); |
2338 } | 2366 } |
2339 } | 2367 } |
(...skipping 618 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2958 | 2986 |
2959 const char* Assembler::FpuRegisterName(FpuRegister reg) { | 2987 const char* Assembler::FpuRegisterName(FpuRegister reg) { |
2960 ASSERT((0 <= reg) && (reg < kNumberOfXmmRegisters)); | 2988 ASSERT((0 <= reg) && (reg < kNumberOfXmmRegisters)); |
2961 return xmm_reg_names[reg]; | 2989 return xmm_reg_names[reg]; |
2962 } | 2990 } |
2963 | 2991 |
2964 | 2992 |
2965 } // namespace dart | 2993 } // namespace dart |
2966 | 2994 |
2967 #endif // defined TARGET_ARCH_IA32 | 2995 #endif // defined TARGET_ARCH_IA32 |
OLD | NEW |