| 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 17 matching lines...) Expand all Loading... |
| 28 int32_t delta = region.start() + position + sizeof(int32_t); | 28 int32_t delta = region.start() + position + sizeof(int32_t); |
| 29 region.Store<int32_t>(position, pointer - delta); | 29 region.Store<int32_t>(position, pointer - delta); |
| 30 } | 30 } |
| 31 | 31 |
| 32 virtual bool IsPointerOffset() const { return false; } | 32 virtual bool IsPointerOffset() const { return false; } |
| 33 }; | 33 }; |
| 34 | 34 |
| 35 | 35 |
| 36 int32_t Assembler::jit_cookie() { | 36 int32_t Assembler::jit_cookie() { |
| 37 if (jit_cookie_ == 0) { | 37 if (jit_cookie_ == 0) { |
| 38 jit_cookie_ = static_cast<int32_t>( | 38 jit_cookie_ = |
| 39 Isolate::Current()->random()->NextUInt32()); | 39 static_cast<int32_t>(Isolate::Current()->random()->NextUInt32()); |
| 40 } | 40 } |
| 41 return jit_cookie_; | 41 return jit_cookie_; |
| 42 } | 42 } |
| 43 | 43 |
| 44 | 44 |
| 45 void Assembler::InitializeMemoryWithBreakpoints(uword data, intptr_t length) { | 45 void Assembler::InitializeMemoryWithBreakpoints(uword data, intptr_t length) { |
| 46 memset(reinterpret_cast<void*>(data), Instr::kBreakPointInstruction, length); | 46 memset(reinterpret_cast<void*>(data), Instr::kBreakPointInstruction, length); |
| 47 } | 47 } |
| 48 | 48 |
| 49 | 49 |
| (...skipping 609 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 659 EmitXmmRegisterOperand(dst, src); | 659 EmitXmmRegisterOperand(dst, src); |
| 660 } | 660 } |
| 661 | 661 |
| 662 | 662 |
| 663 void Assembler::notps(XmmRegister dst) { | 663 void Assembler::notps(XmmRegister dst) { |
| 664 static const struct ALIGN16 { | 664 static const struct ALIGN16 { |
| 665 uint32_t a; | 665 uint32_t a; |
| 666 uint32_t b; | 666 uint32_t b; |
| 667 uint32_t c; | 667 uint32_t c; |
| 668 uint32_t d; | 668 uint32_t d; |
| 669 } float_not_constant = | 669 } float_not_constant = {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF}; |
| 670 { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF }; | 670 xorps(dst, Address::Absolute(reinterpret_cast<uword>(&float_not_constant))); |
| 671 xorps(dst, | |
| 672 Address::Absolute(reinterpret_cast<uword>(&float_not_constant))); | |
| 673 } | 671 } |
| 674 | 672 |
| 675 | 673 |
| 676 void Assembler::negateps(XmmRegister dst) { | 674 void Assembler::negateps(XmmRegister dst) { |
| 677 static const struct ALIGN16 { | 675 static const struct ALIGN16 { |
| 678 uint32_t a; | 676 uint32_t a; |
| 679 uint32_t b; | 677 uint32_t b; |
| 680 uint32_t c; | 678 uint32_t c; |
| 681 uint32_t d; | 679 uint32_t d; |
| 682 } float_negate_constant = | 680 } float_negate_constant = {0x80000000, 0x80000000, 0x80000000, 0x80000000}; |
| 683 { 0x80000000, 0x80000000, 0x80000000, 0x80000000 }; | |
| 684 xorps(dst, | 681 xorps(dst, |
| 685 Address::Absolute(reinterpret_cast<uword>(&float_negate_constant))); | 682 Address::Absolute(reinterpret_cast<uword>(&float_negate_constant))); |
| 686 } | 683 } |
| 687 | 684 |
| 688 | 685 |
| 689 void Assembler::absps(XmmRegister dst) { | 686 void Assembler::absps(XmmRegister dst) { |
| 690 static const struct ALIGN16 { | 687 static const struct ALIGN16 { |
| 691 uint32_t a; | 688 uint32_t a; |
| 692 uint32_t b; | 689 uint32_t b; |
| 693 uint32_t c; | 690 uint32_t c; |
| 694 uint32_t d; | 691 uint32_t d; |
| 695 } float_absolute_constant = | 692 } float_absolute_constant = {0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF}; |
| 696 { 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF }; | |
| 697 andps(dst, | 693 andps(dst, |
| 698 Address::Absolute(reinterpret_cast<uword>(&float_absolute_constant))); | 694 Address::Absolute(reinterpret_cast<uword>(&float_absolute_constant))); |
| 699 } | 695 } |
| 700 | 696 |
| 701 | 697 |
| 702 void Assembler::zerowps(XmmRegister dst) { | 698 void Assembler::zerowps(XmmRegister dst) { |
| 703 static const struct ALIGN16 { | 699 static const struct ALIGN16 { |
| 704 uint32_t a; | 700 uint32_t a; |
| 705 uint32_t b; | 701 uint32_t b; |
| 706 uint32_t c; | 702 uint32_t c; |
| 707 uint32_t d; | 703 uint32_t d; |
| 708 } float_zerow_constant = | 704 } float_zerow_constant = {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000}; |
| 709 { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000 }; | |
| 710 andps(dst, Address::Absolute(reinterpret_cast<uword>(&float_zerow_constant))); | 705 andps(dst, Address::Absolute(reinterpret_cast<uword>(&float_zerow_constant))); |
| 711 } | 706 } |
| 712 | 707 |
| 713 | 708 |
| 714 void Assembler::cmppseq(XmmRegister dst, XmmRegister src) { | 709 void Assembler::cmppseq(XmmRegister dst, XmmRegister src) { |
| 715 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | 710 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 716 EmitUint8(0x0F); | 711 EmitUint8(0x0F); |
| 717 EmitUint8(0xC2); | 712 EmitUint8(0xC2); |
| 718 EmitXmmRegisterOperand(dst, src); | 713 EmitXmmRegisterOperand(dst, src); |
| 719 EmitUint8(0x0); | 714 EmitUint8(0x0); |
| (...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 865 EmitUint8(0x0F); | 860 EmitUint8(0x0F); |
| 866 EmitUint8(0x58); | 861 EmitUint8(0x58); |
| 867 EmitXmmRegisterOperand(dst, src); | 862 EmitXmmRegisterOperand(dst, src); |
| 868 } | 863 } |
| 869 | 864 |
| 870 | 865 |
| 871 void Assembler::negatepd(XmmRegister dst) { | 866 void Assembler::negatepd(XmmRegister dst) { |
| 872 static const struct ALIGN16 { | 867 static const struct ALIGN16 { |
| 873 uint64_t a; | 868 uint64_t a; |
| 874 uint64_t b; | 869 uint64_t b; |
| 875 } double_negate_constant = | 870 } double_negate_constant = {0x8000000000000000LL, 0x8000000000000000LL}; |
| 876 { 0x8000000000000000LL, 0x8000000000000000LL }; | |
| 877 xorpd(dst, | 871 xorpd(dst, |
| 878 Address::Absolute(reinterpret_cast<uword>(&double_negate_constant))); | 872 Address::Absolute(reinterpret_cast<uword>(&double_negate_constant))); |
| 879 } | 873 } |
| 880 | 874 |
| 881 | 875 |
| 882 void Assembler::subpd(XmmRegister dst, XmmRegister src) { | 876 void Assembler::subpd(XmmRegister dst, XmmRegister src) { |
| 883 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | 877 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 884 EmitUint8(0x66); | 878 EmitUint8(0x66); |
| 885 EmitUint8(0x0F); | 879 EmitUint8(0x0F); |
| 886 EmitUint8(0x5C); | 880 EmitUint8(0x5C); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 903 EmitUint8(0x0F); | 897 EmitUint8(0x0F); |
| 904 EmitUint8(0x5E); | 898 EmitUint8(0x5E); |
| 905 EmitXmmRegisterOperand(dst, src); | 899 EmitXmmRegisterOperand(dst, src); |
| 906 } | 900 } |
| 907 | 901 |
| 908 | 902 |
| 909 void Assembler::abspd(XmmRegister dst) { | 903 void Assembler::abspd(XmmRegister dst) { |
| 910 static const struct ALIGN16 { | 904 static const struct ALIGN16 { |
| 911 uint64_t a; | 905 uint64_t a; |
| 912 uint64_t b; | 906 uint64_t b; |
| 913 } double_absolute_constant = | 907 } double_absolute_constant = {0x7FFFFFFFFFFFFFFFLL, 0x7FFFFFFFFFFFFFFFLL}; |
| 914 { 0x7FFFFFFFFFFFFFFFLL, 0x7FFFFFFFFFFFFFFFLL }; | |
| 915 andpd(dst, | 908 andpd(dst, |
| 916 Address::Absolute(reinterpret_cast<uword>(&double_absolute_constant))); | 909 Address::Absolute(reinterpret_cast<uword>(&double_absolute_constant))); |
| 917 } | 910 } |
| 918 | 911 |
| 919 | 912 |
| 920 void Assembler::minpd(XmmRegister dst, XmmRegister src) { | 913 void Assembler::minpd(XmmRegister dst, XmmRegister src) { |
| 921 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | 914 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 922 EmitUint8(0x66); | 915 EmitUint8(0x66); |
| 923 EmitUint8(0x0F); | 916 EmitUint8(0x0F); |
| 924 EmitUint8(0x5D); | 917 EmitUint8(0x5D); |
| (...skipping 1320 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2245 // For the value we are only interested in the new/old bit and the tag bit. | 2238 // For the value we are only interested in the new/old bit and the tag bit. |
| 2246 andl(value, Immediate(kNewObjectAlignmentOffset | kHeapObjectTag)); | 2239 andl(value, Immediate(kNewObjectAlignmentOffset | kHeapObjectTag)); |
| 2247 // Shift the tag bit into the carry. | 2240 // Shift the tag bit into the carry. |
| 2248 shrl(value, Immediate(1)); | 2241 shrl(value, Immediate(1)); |
| 2249 // Add the tag bits together, if the value is not a Smi the addition will | 2242 // Add the tag bits together, if the value is not a Smi the addition will |
| 2250 // overflow into the next bit, leaving us with a zero low bit. | 2243 // overflow into the next bit, leaving us with a zero low bit. |
| 2251 adcl(value, object); | 2244 adcl(value, object); |
| 2252 // Mask out higher, uninteresting bits which were polluted by dest. | 2245 // Mask out higher, uninteresting bits which were polluted by dest. |
| 2253 andl(value, Immediate(kObjectAlignment - 1)); | 2246 andl(value, Immediate(kObjectAlignment - 1)); |
| 2254 // Compare with the expected bit pattern. | 2247 // Compare with the expected bit pattern. |
| 2255 cmpl(value, Immediate( | 2248 cmpl(value, Immediate((kNewObjectAlignmentOffset >> 1) + kHeapObjectTag + |
| 2256 (kNewObjectAlignmentOffset >> 1) + kHeapObjectTag + | 2249 kOldObjectAlignmentOffset + kHeapObjectTag)); |
| 2257 kOldObjectAlignmentOffset + kHeapObjectTag)); | |
| 2258 j(NOT_ZERO, no_update, Assembler::kNearJump); | 2250 j(NOT_ZERO, no_update, Assembler::kNearJump); |
| 2259 } | 2251 } |
| 2260 | 2252 |
| 2261 | 2253 |
| 2262 // Destroys the value register. | 2254 // Destroys the value register. |
| 2263 void Assembler::StoreIntoObject(Register object, | 2255 void Assembler::StoreIntoObject(Register object, |
| 2264 const Address& dest, | 2256 const Address& dest, |
| 2265 Register value, | 2257 Register value, |
| 2266 bool can_value_be_smi) { | 2258 bool can_value_be_smi) { |
| 2267 ASSERT(object != value); | 2259 ASSERT(object != value); |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2366 addl(ESP, Immediate(2 * kWordSize)); | 2358 addl(ESP, Immediate(2 * kWordSize)); |
| 2367 } | 2359 } |
| 2368 | 2360 |
| 2369 | 2361 |
| 2370 void Assembler::FloatNegate(XmmRegister f) { | 2362 void Assembler::FloatNegate(XmmRegister f) { |
| 2371 static const struct ALIGN16 { | 2363 static const struct ALIGN16 { |
| 2372 uint32_t a; | 2364 uint32_t a; |
| 2373 uint32_t b; | 2365 uint32_t b; |
| 2374 uint32_t c; | 2366 uint32_t c; |
| 2375 uint32_t d; | 2367 uint32_t d; |
| 2376 } float_negate_constant = | 2368 } float_negate_constant = {0x80000000, 0x00000000, 0x80000000, 0x00000000}; |
| 2377 { 0x80000000, 0x00000000, 0x80000000, 0x00000000 }; | |
| 2378 xorps(f, Address::Absolute(reinterpret_cast<uword>(&float_negate_constant))); | 2369 xorps(f, Address::Absolute(reinterpret_cast<uword>(&float_negate_constant))); |
| 2379 } | 2370 } |
| 2380 | 2371 |
| 2381 | 2372 |
| 2382 void Assembler::DoubleNegate(XmmRegister d) { | 2373 void Assembler::DoubleNegate(XmmRegister d) { |
| 2383 static const struct ALIGN16 { | 2374 static const struct ALIGN16 { |
| 2384 uint64_t a; | 2375 uint64_t a; |
| 2385 uint64_t b; | 2376 uint64_t b; |
| 2386 } double_negate_constant = | 2377 } double_negate_constant = {0x8000000000000000LL, 0x8000000000000000LL}; |
| 2387 {0x8000000000000000LL, 0x8000000000000000LL}; | |
| 2388 xorpd(d, Address::Absolute(reinterpret_cast<uword>(&double_negate_constant))); | 2378 xorpd(d, Address::Absolute(reinterpret_cast<uword>(&double_negate_constant))); |
| 2389 } | 2379 } |
| 2390 | 2380 |
| 2391 | 2381 |
| 2392 void Assembler::DoubleAbs(XmmRegister reg) { | 2382 void Assembler::DoubleAbs(XmmRegister reg) { |
| 2393 static const struct ALIGN16 { | 2383 static const struct ALIGN16 { |
| 2394 uint64_t a; | 2384 uint64_t a; |
| 2395 uint64_t b; | 2385 uint64_t b; |
| 2396 } double_abs_constant = | 2386 } double_abs_constant = {0x7FFFFFFFFFFFFFFFLL, 0x7FFFFFFFFFFFFFFFLL}; |
| 2397 {0x7FFFFFFFFFFFFFFFLL, 0x7FFFFFFFFFFFFFFFLL}; | |
| 2398 andpd(reg, Address::Absolute(reinterpret_cast<uword>(&double_abs_constant))); | 2387 andpd(reg, Address::Absolute(reinterpret_cast<uword>(&double_abs_constant))); |
| 2399 } | 2388 } |
| 2400 | 2389 |
| 2401 | 2390 |
| 2402 void Assembler::EnterFrame(intptr_t frame_size) { | 2391 void Assembler::EnterFrame(intptr_t frame_size) { |
| 2403 if (prologue_offset_ == -1) { | 2392 if (prologue_offset_ == -1) { |
| 2404 Comment("PrologueOffset = %" Pd "", CodeSize()); | 2393 Comment("PrologueOffset = %" Pd "", CodeSize()); |
| 2405 prologue_offset_ = CodeSize(); | 2394 prologue_offset_ = CodeSize(); |
| 2406 } | 2395 } |
| 2407 #ifdef DEBUG | 2396 #ifdef DEBUG |
| (...skipping 23 matching lines...) Expand all Loading... |
| 2431 // the C++ world. | 2420 // the C++ world. |
| 2432 AddImmediate(ESP, Immediate(-frame_space)); | 2421 AddImmediate(ESP, Immediate(-frame_space)); |
| 2433 if (OS::ActivationFrameAlignment() > 1) { | 2422 if (OS::ActivationFrameAlignment() > 1) { |
| 2434 andl(ESP, Immediate(~(OS::ActivationFrameAlignment() - 1))); | 2423 andl(ESP, Immediate(~(OS::ActivationFrameAlignment() - 1))); |
| 2435 } | 2424 } |
| 2436 } | 2425 } |
| 2437 | 2426 |
| 2438 | 2427 |
| 2439 static const intptr_t kNumberOfVolatileCpuRegisters = 3; | 2428 static const intptr_t kNumberOfVolatileCpuRegisters = 3; |
| 2440 static const Register volatile_cpu_registers[kNumberOfVolatileCpuRegisters] = { | 2429 static const Register volatile_cpu_registers[kNumberOfVolatileCpuRegisters] = { |
| 2441 EAX, ECX, EDX | 2430 EAX, ECX, EDX}; |
| 2442 }; | |
| 2443 | 2431 |
| 2444 | 2432 |
| 2445 // XMM0 is used only as a scratch register in the optimized code. No need to | 2433 // XMM0 is used only as a scratch register in the optimized code. No need to |
| 2446 // save it. | 2434 // save it. |
| 2447 static const intptr_t kNumberOfVolatileXmmRegisters = | 2435 static const intptr_t kNumberOfVolatileXmmRegisters = kNumberOfXmmRegisters - 1; |
| 2448 kNumberOfXmmRegisters - 1; | |
| 2449 | 2436 |
| 2450 | 2437 |
| 2451 void Assembler::EnterCallRuntimeFrame(intptr_t frame_space) { | 2438 void Assembler::EnterCallRuntimeFrame(intptr_t frame_space) { |
| 2452 Comment("EnterCallRuntimeFrame"); | 2439 Comment("EnterCallRuntimeFrame"); |
| 2453 EnterFrame(0); | 2440 EnterFrame(0); |
| 2454 | 2441 |
| 2455 // Preserve volatile CPU registers. | 2442 // Preserve volatile CPU registers. |
| 2456 for (intptr_t i = 0; i < kNumberOfVolatileCpuRegisters; i++) { | 2443 for (intptr_t i = 0; i < kNumberOfVolatileCpuRegisters; i++) { |
| 2457 pushl(volatile_cpu_registers[i]); | 2444 pushl(volatile_cpu_registers[i]); |
| 2458 } | 2445 } |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2539 return; | 2526 return; |
| 2540 } | 2527 } |
| 2541 intptr_t bytes_needed = alignment - mod; | 2528 intptr_t bytes_needed = alignment - mod; |
| 2542 while (bytes_needed > MAX_NOP_SIZE) { | 2529 while (bytes_needed > MAX_NOP_SIZE) { |
| 2543 nop(MAX_NOP_SIZE); | 2530 nop(MAX_NOP_SIZE); |
| 2544 bytes_needed -= MAX_NOP_SIZE; | 2531 bytes_needed -= MAX_NOP_SIZE; |
| 2545 } | 2532 } |
| 2546 if (bytes_needed) { | 2533 if (bytes_needed) { |
| 2547 nop(bytes_needed); | 2534 nop(bytes_needed); |
| 2548 } | 2535 } |
| 2549 ASSERT(((offset + buffer_.GetPosition()) & (alignment-1)) == 0); | 2536 ASSERT(((offset + buffer_.GetPosition()) & (alignment - 1)) == 0); |
| 2550 } | 2537 } |
| 2551 | 2538 |
| 2552 | 2539 |
| 2553 void Assembler::Bind(Label* label) { | 2540 void Assembler::Bind(Label* label) { |
| 2554 intptr_t bound = buffer_.Size(); | 2541 intptr_t bound = buffer_.Size(); |
| 2555 ASSERT(!label->IsBound()); // Labels can only be bound once. | 2542 ASSERT(!label->IsBound()); // Labels can only be bound once. |
| 2556 while (label->IsLinked()) { | 2543 while (label->IsLinked()) { |
| 2557 intptr_t position = label->LinkPosition(); | 2544 intptr_t position = label->LinkPosition(); |
| 2558 intptr_t next = buffer_.Load<int32_t>(position); | 2545 intptr_t next = buffer_.Load<int32_t>(position); |
| 2559 buffer_.Store<int32_t>(position, bound - (position + 4)); | 2546 buffer_.Store<int32_t>(position, bound - (position + 4)); |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2635 bool near_jump, | 2622 bool near_jump, |
| 2636 Register instance_reg, | 2623 Register instance_reg, |
| 2637 Register temp_reg) { | 2624 Register temp_reg) { |
| 2638 ASSERT(failure != NULL); | 2625 ASSERT(failure != NULL); |
| 2639 ASSERT(temp_reg != kNoRegister); | 2626 ASSERT(temp_reg != kNoRegister); |
| 2640 if (FLAG_inline_alloc) { | 2627 if (FLAG_inline_alloc) { |
| 2641 // If this allocation is traced, program will jump to failure path | 2628 // If this allocation is traced, program will jump to failure path |
| 2642 // (i.e. the allocation stub) which will allocate the object and trace the | 2629 // (i.e. the allocation stub) which will allocate the object and trace the |
| 2643 // allocation call site. | 2630 // allocation call site. |
| 2644 NOT_IN_PRODUCT( | 2631 NOT_IN_PRODUCT( |
| 2645 MaybeTraceAllocation(cls.id(), temp_reg, failure, near_jump)); | 2632 MaybeTraceAllocation(cls.id(), temp_reg, failure, near_jump)); |
| 2646 const intptr_t instance_size = cls.instance_size(); | 2633 const intptr_t instance_size = cls.instance_size(); |
| 2647 Heap::Space space = Heap::kNew; | 2634 Heap::Space space = Heap::kNew; |
| 2648 movl(temp_reg, Address(THR, Thread::heap_offset())); | 2635 movl(temp_reg, Address(THR, Thread::heap_offset())); |
| 2649 movl(instance_reg, Address(temp_reg, Heap::TopOffset(space))); | 2636 movl(instance_reg, Address(temp_reg, Heap::TopOffset(space))); |
| 2650 addl(instance_reg, Immediate(instance_size)); | 2637 addl(instance_reg, Immediate(instance_size)); |
| 2651 // instance_reg: potential next object start. | 2638 // instance_reg: potential next object start. |
| 2652 cmpl(instance_reg, Address(temp_reg, Heap::EndOffset(space))); | 2639 cmpl(instance_reg, Address(temp_reg, Heap::EndOffset(space))); |
| 2653 j(ABOVE_EQUAL, failure, near_jump); | 2640 j(ABOVE_EQUAL, failure, near_jump); |
| 2654 // Successfully allocated the object, now update top to point to | 2641 // Successfully allocated the object, now update top to point to |
| 2655 // next object start and store the class in the class field of object. | 2642 // next object start and store the class in the class field of object. |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2753 void Assembler::EnterStubFrame() { | 2740 void Assembler::EnterStubFrame() { |
| 2754 EnterDartFrame(0); | 2741 EnterDartFrame(0); |
| 2755 } | 2742 } |
| 2756 | 2743 |
| 2757 | 2744 |
| 2758 void Assembler::Stop(const char* message) { | 2745 void Assembler::Stop(const char* message) { |
| 2759 if (FLAG_print_stop_message) { | 2746 if (FLAG_print_stop_message) { |
| 2760 pushl(EAX); // Preserve EAX. | 2747 pushl(EAX); // Preserve EAX. |
| 2761 movl(EAX, Immediate(reinterpret_cast<int32_t>(message))); | 2748 movl(EAX, Immediate(reinterpret_cast<int32_t>(message))); |
| 2762 Call(*StubCode::PrintStopMessage_entry()); // Passing message in EAX. | 2749 Call(*StubCode::PrintStopMessage_entry()); // Passing message in EAX. |
| 2763 popl(EAX); // Restore EAX. | 2750 popl(EAX); // Restore EAX. |
| 2764 } else { | 2751 } else { |
| 2765 // Emit the message address as immediate operand in the test instruction. | 2752 // Emit the message address as immediate operand in the test instruction. |
| 2766 testl(EAX, Immediate(reinterpret_cast<int32_t>(message))); | 2753 testl(EAX, Immediate(reinterpret_cast<int32_t>(message))); |
| 2767 } | 2754 } |
| 2768 // Emit the int3 instruction. | 2755 // Emit the int3 instruction. |
| 2769 int3(); // Execution can be resumed with the 'cont' command in gdb. | 2756 int3(); // Execution can be resumed with the 'cont' command in gdb. |
| 2770 } | 2757 } |
| 2771 | 2758 |
| 2772 | 2759 |
| 2773 void Assembler::EmitOperand(int rm, const Operand& operand) { | 2760 void Assembler::EmitOperand(int rm, const Operand& operand) { |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2830 | 2817 |
| 2831 | 2818 |
| 2832 void Assembler::EmitNearLabelLink(Label* label) { | 2819 void Assembler::EmitNearLabelLink(Label* label) { |
| 2833 ASSERT(!label->IsBound()); | 2820 ASSERT(!label->IsBound()); |
| 2834 intptr_t position = buffer_.Size(); | 2821 intptr_t position = buffer_.Size(); |
| 2835 EmitUint8(0); | 2822 EmitUint8(0); |
| 2836 label->NearLinkTo(position); | 2823 label->NearLinkTo(position); |
| 2837 } | 2824 } |
| 2838 | 2825 |
| 2839 | 2826 |
| 2840 void Assembler::EmitGenericShift(int rm, | 2827 void Assembler::EmitGenericShift(int rm, Register reg, const Immediate& imm) { |
| 2841 Register reg, | |
| 2842 const Immediate& imm) { | |
| 2843 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | 2828 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 2844 ASSERT(imm.is_int8()); | 2829 ASSERT(imm.is_int8()); |
| 2845 if (imm.value() == 1) { | 2830 if (imm.value() == 1) { |
| 2846 EmitUint8(0xD1); | 2831 EmitUint8(0xD1); |
| 2847 EmitOperand(rm, Operand(reg)); | 2832 EmitOperand(rm, Operand(reg)); |
| 2848 } else { | 2833 } else { |
| 2849 EmitUint8(0xC1); | 2834 EmitUint8(0xC1); |
| 2850 EmitOperand(rm, Operand(reg)); | 2835 EmitOperand(rm, Operand(reg)); |
| 2851 EmitUint8(imm.value() & 0xFF); | 2836 EmitUint8(imm.value() & 0xFF); |
| 2852 } | 2837 } |
| 2853 } | 2838 } |
| 2854 | 2839 |
| 2855 | 2840 |
| 2856 void Assembler::EmitGenericShift(int rm, | 2841 void Assembler::EmitGenericShift(int rm, |
| 2857 const Operand& operand, | 2842 const Operand& operand, |
| 2858 Register shifter) { | 2843 Register shifter) { |
| 2859 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | 2844 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 2860 ASSERT(shifter == ECX); | 2845 ASSERT(shifter == ECX); |
| 2861 EmitUint8(0xD3); | 2846 EmitUint8(0xD3); |
| 2862 EmitOperand(rm, Operand(operand)); | 2847 EmitOperand(rm, Operand(operand)); |
| 2863 } | 2848 } |
| 2864 | 2849 |
| 2865 | 2850 |
| 2866 void Assembler::LoadClassId(Register result, Register object) { | 2851 void Assembler::LoadClassId(Register result, Register object) { |
| 2867 ASSERT(RawObject::kClassIdTagPos == 16); | 2852 ASSERT(RawObject::kClassIdTagPos == 16); |
| 2868 ASSERT(RawObject::kClassIdTagSize == 16); | 2853 ASSERT(RawObject::kClassIdTagSize == 16); |
| 2869 const intptr_t class_id_offset = Object::tags_offset() + | 2854 const intptr_t class_id_offset = |
| 2870 RawObject::kClassIdTagPos / kBitsPerByte; | 2855 Object::tags_offset() + RawObject::kClassIdTagPos / kBitsPerByte; |
| 2871 movzxw(result, FieldAddress(object, class_id_offset)); | 2856 movzxw(result, FieldAddress(object, class_id_offset)); |
| 2872 } | 2857 } |
| 2873 | 2858 |
| 2874 | 2859 |
| 2875 void Assembler::LoadClassById(Register result, Register class_id) { | 2860 void Assembler::LoadClassById(Register result, Register class_id) { |
| 2876 ASSERT(result != class_id); | 2861 ASSERT(result != class_id); |
| 2877 LoadIsolate(result); | 2862 LoadIsolate(result); |
| 2878 const intptr_t offset = | 2863 const intptr_t offset = |
| 2879 Isolate::class_table_offset() + ClassTable::table_offset(); | 2864 Isolate::class_table_offset() + ClassTable::table_offset(); |
| 2880 movl(result, Address(result, offset)); | 2865 movl(result, Address(result, offset)); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 2897 } | 2882 } |
| 2898 | 2883 |
| 2899 | 2884 |
| 2900 void Assembler::SmiUntagOrCheckClass(Register object, | 2885 void Assembler::SmiUntagOrCheckClass(Register object, |
| 2901 intptr_t class_id, | 2886 intptr_t class_id, |
| 2902 Register scratch, | 2887 Register scratch, |
| 2903 Label* is_smi) { | 2888 Label* is_smi) { |
| 2904 ASSERT(kSmiTagShift == 1); | 2889 ASSERT(kSmiTagShift == 1); |
| 2905 ASSERT(RawObject::kClassIdTagPos == 16); | 2890 ASSERT(RawObject::kClassIdTagPos == 16); |
| 2906 ASSERT(RawObject::kClassIdTagSize == 16); | 2891 ASSERT(RawObject::kClassIdTagSize == 16); |
| 2907 const intptr_t class_id_offset = Object::tags_offset() + | 2892 const intptr_t class_id_offset = |
| 2908 RawObject::kClassIdTagPos / kBitsPerByte; | 2893 Object::tags_offset() + RawObject::kClassIdTagPos / kBitsPerByte; |
| 2909 | 2894 |
| 2910 // Untag optimistically. Tag bit is shifted into the CARRY. | 2895 // Untag optimistically. Tag bit is shifted into the CARRY. |
| 2911 SmiUntag(object); | 2896 SmiUntag(object); |
| 2912 j(NOT_CARRY, is_smi, kNearJump); | 2897 j(NOT_CARRY, is_smi, kNearJump); |
| 2913 // Load cid: can't use LoadClassId, object is untagged. Use TIMES_2 scale | 2898 // Load cid: can't use LoadClassId, object is untagged. Use TIMES_2 scale |
| 2914 // factor in the addressing mode to compensate for this. | 2899 // factor in the addressing mode to compensate for this. |
| 2915 movzxw(scratch, Address(object, TIMES_2, class_id_offset)); | 2900 movzxw(scratch, Address(object, TIMES_2, class_id_offset)); |
| 2916 cmpl(scratch, Immediate(class_id)); | 2901 cmpl(scratch, Immediate(class_id)); |
| 2917 } | 2902 } |
| 2918 | 2903 |
| (...skipping 24 matching lines...) Expand all Loading... |
| 2943 | 2928 |
| 2944 Address Assembler::ElementAddressForIntIndex(bool is_external, | 2929 Address Assembler::ElementAddressForIntIndex(bool is_external, |
| 2945 intptr_t cid, | 2930 intptr_t cid, |
| 2946 intptr_t index_scale, | 2931 intptr_t index_scale, |
| 2947 Register array, | 2932 Register array, |
| 2948 intptr_t index) { | 2933 intptr_t index) { |
| 2949 if (is_external) { | 2934 if (is_external) { |
| 2950 return Address(array, index * index_scale); | 2935 return Address(array, index * index_scale); |
| 2951 } else { | 2936 } else { |
| 2952 const int64_t disp = static_cast<int64_t>(index) * index_scale + | 2937 const int64_t disp = static_cast<int64_t>(index) * index_scale + |
| 2953 Instance::DataOffsetFor(cid); | 2938 Instance::DataOffsetFor(cid); |
| 2954 ASSERT(Utils::IsInt(32, disp)); | 2939 ASSERT(Utils::IsInt(32, disp)); |
| 2955 return FieldAddress(array, static_cast<int32_t>(disp)); | 2940 return FieldAddress(array, static_cast<int32_t>(disp)); |
| 2956 } | 2941 } |
| 2957 } | 2942 } |
| 2958 | 2943 |
| 2959 | 2944 |
| 2960 static ScaleFactor ToScaleFactor(intptr_t index_scale) { | 2945 static ScaleFactor ToScaleFactor(intptr_t index_scale) { |
| 2961 // Note that index is expected smi-tagged, (i.e, times 2) for all arrays with | 2946 // Note that index is expected smi-tagged, (i.e, times 2) for all arrays with |
| 2962 // index scale factor > 1. E.g., for Uint8Array and OneByteString the index is | 2947 // index scale factor > 1. E.g., for Uint8Array and OneByteString the index is |
| 2963 // expected to be untagged before accessing. | 2948 // expected to be untagged before accessing. |
| 2964 ASSERT(kSmiTagShift == 1); | 2949 ASSERT(kSmiTagShift == 1); |
| 2965 switch (index_scale) { | 2950 switch (index_scale) { |
| 2966 case 1: return TIMES_1; | 2951 case 1: |
| 2967 case 2: return TIMES_1; | 2952 return TIMES_1; |
| 2968 case 4: return TIMES_2; | 2953 case 2: |
| 2969 case 8: return TIMES_4; | 2954 return TIMES_1; |
| 2970 case 16: return TIMES_8; | 2955 case 4: |
| 2956 return TIMES_2; |
| 2957 case 8: |
| 2958 return TIMES_4; |
| 2959 case 16: |
| 2960 return TIMES_8; |
| 2971 default: | 2961 default: |
| 2972 UNREACHABLE(); | 2962 UNREACHABLE(); |
| 2973 return TIMES_1; | 2963 return TIMES_1; |
| 2974 } | 2964 } |
| 2975 } | 2965 } |
| 2976 | 2966 |
| 2977 | 2967 |
| 2978 Address Assembler::ElementAddressForRegIndex(bool is_external, | 2968 Address Assembler::ElementAddressForRegIndex(bool is_external, |
| 2979 intptr_t cid, | 2969 intptr_t cid, |
| 2980 intptr_t index_scale, | 2970 intptr_t index_scale, |
| 2981 Register array, | 2971 Register array, |
| 2982 Register index) { | 2972 Register index) { |
| 2983 if (is_external) { | 2973 if (is_external) { |
| 2984 return Address(array, index, ToScaleFactor(index_scale), 0); | 2974 return Address(array, index, ToScaleFactor(index_scale), 0); |
| 2985 } else { | 2975 } else { |
| 2986 return FieldAddress(array, | 2976 return FieldAddress(array, index, ToScaleFactor(index_scale), |
| 2987 index, | |
| 2988 ToScaleFactor(index_scale), | |
| 2989 Instance::DataOffsetFor(cid)); | 2977 Instance::DataOffsetFor(cid)); |
| 2990 } | 2978 } |
| 2991 } | 2979 } |
| 2992 | 2980 |
| 2993 | 2981 |
| 2994 static const char* cpu_reg_names[kNumberOfCpuRegisters] = { | 2982 static const char* cpu_reg_names[kNumberOfCpuRegisters] = { |
| 2995 "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi" | 2983 "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi"}; |
| 2996 }; | |
| 2997 | 2984 |
| 2998 | 2985 |
| 2999 const char* Assembler::RegisterName(Register reg) { | 2986 const char* Assembler::RegisterName(Register reg) { |
| 3000 ASSERT((0 <= reg) && (reg < kNumberOfCpuRegisters)); | 2987 ASSERT((0 <= reg) && (reg < kNumberOfCpuRegisters)); |
| 3001 return cpu_reg_names[reg]; | 2988 return cpu_reg_names[reg]; |
| 3002 } | 2989 } |
| 3003 | 2990 |
| 3004 | 2991 |
| 3005 static const char* xmm_reg_names[kNumberOfXmmRegisters] = { | 2992 static const char* xmm_reg_names[kNumberOfXmmRegisters] = { |
| 3006 "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7" | 2993 "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7"}; |
| 3007 }; | |
| 3008 | 2994 |
| 3009 | 2995 |
| 3010 const char* Assembler::FpuRegisterName(FpuRegister reg) { | 2996 const char* Assembler::FpuRegisterName(FpuRegister reg) { |
| 3011 ASSERT((0 <= reg) && (reg < kNumberOfXmmRegisters)); | 2997 ASSERT((0 <= reg) && (reg < kNumberOfXmmRegisters)); |
| 3012 return xmm_reg_names[reg]; | 2998 return xmm_reg_names[reg]; |
| 3013 } | 2999 } |
| 3014 | 3000 |
| 3015 | 3001 |
| 3016 } // namespace dart | 3002 } // namespace dart |
| 3017 | 3003 |
| 3018 #endif // defined TARGET_ARCH_IA32 | 3004 #endif // defined TARGET_ARCH_IA32 |
| OLD | NEW |