VM: Clean up and fix bugs in instructions patterns
Fix bug in DecodeLoadWordFromPool: used Array::element_offset instead of ObjectPool::element_offset. This only worked because they accidentally return the same value. Remove virtual methods from InstructionsPatterns on ia32 and x64. Instead use a template for code reuse. This avoids among others vtables for the *Pattern classes and saves >= 4K in VM binary code size. BUG= R=rmacnak@google.com Review URL: https://codereview.chromium.org//1301963003 .
This commit is contained in:
@@ -178,11 +178,11 @@ void CodePatcher::PatchInstanceCallAt(uword return_address,
|
||||
|
||||
void CodePatcher::InsertCallAt(uword start, uword target) {
|
||||
// The inserted call should not overlap the lazy deopt jump code.
|
||||
ASSERT(start + CallPattern::InstructionLength() <= target);
|
||||
ASSERT(start + CallPattern::pattern_length_in_bytes() <= target);
|
||||
*reinterpret_cast<uint8_t*>(start) = 0xE8;
|
||||
CallPattern call(start);
|
||||
call.SetTargetAddress(target);
|
||||
CPU::FlushICache(start, CallPattern::InstructionLength());
|
||||
CPU::FlushICache(start, CallPattern::pattern_length_in_bytes());
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -41,17 +41,17 @@ class UnoptimizedCall : public ValueObject {
|
||||
}
|
||||
|
||||
RawObject* ic_data() const {
|
||||
intptr_t index = InstructionPattern::IndexFromPPLoad(start_ + 3);
|
||||
intptr_t index = IndexFromPPLoad(start_ + 3);
|
||||
return object_pool_.ObjectAt(index);
|
||||
}
|
||||
|
||||
uword target() const {
|
||||
intptr_t index = InstructionPattern::IndexFromPPLoad(start_ + 10);
|
||||
intptr_t index = IndexFromPPLoad(start_ + 10);
|
||||
return object_pool_.RawValueAt(index);
|
||||
}
|
||||
|
||||
void set_target(uword target) const {
|
||||
intptr_t index = InstructionPattern::IndexFromPPLoad(start_ + 10);
|
||||
intptr_t index = IndexFromPPLoad(start_ + 10);
|
||||
object_pool_.SetRawValueAt(index, target);
|
||||
// No need to flush the instruction cache, since the code is not modified.
|
||||
}
|
||||
@@ -117,7 +117,7 @@ class PoolPointerCall : public ValueObject {
|
||||
}
|
||||
|
||||
intptr_t pp_index() const {
|
||||
return InstructionPattern::IndexFromPPLoad(start_ + 3);
|
||||
return IndexFromPPLoad(start_ + 3);
|
||||
}
|
||||
|
||||
uword Target() const {
|
||||
@@ -190,11 +190,11 @@ intptr_t CodePatcher::InstanceCallSizeInBytes() {
|
||||
|
||||
void CodePatcher::InsertCallAt(uword start, uword target) {
|
||||
// The inserted call should not overlap the lazy deopt jump code.
|
||||
ASSERT(start + ShortCallPattern::InstructionLength() <= target);
|
||||
ASSERT(start + ShortCallPattern::pattern_length_in_bytes() <= target);
|
||||
*reinterpret_cast<uint8_t*>(start) = 0xE8;
|
||||
ShortCallPattern call(start);
|
||||
call.SetTargetAddress(target);
|
||||
CPU::FlushICache(start, ShortCallPattern::InstructionLength());
|
||||
CPU::FlushICache(start, ShortCallPattern::pattern_length_in_bytes());
|
||||
}
|
||||
|
||||
|
||||
@@ -227,7 +227,7 @@ class EdgeCounter : public ValueObject {
|
||||
}
|
||||
|
||||
RawObject* edge_counter() const {
|
||||
return object_pool_.ObjectAt(InstructionPattern::IndexFromPPLoad(end_ - 4));
|
||||
return object_pool_.ObjectAt(IndexFromPPLoad(end_ - 4));
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
@@ -150,9 +150,7 @@ uword InstructionPattern::DecodeLoadWordFromPool(uword end,
|
||||
end = DecodeLoadWordImmediate(end, reg, &offset);
|
||||
}
|
||||
}
|
||||
offset += kHeapObjectTag;
|
||||
ASSERT(Utils::IsAligned(offset, 4));
|
||||
*index = (offset - Array::data_offset()) / 4;
|
||||
*index = ObjectPool::IndexFromOffset(offset);
|
||||
return start;
|
||||
}
|
||||
|
||||
|
||||
@@ -208,8 +208,9 @@ uword InstructionPattern::DecodeLoadWordFromPool(uword end,
|
||||
offset |= instr->Imm16Field();
|
||||
}
|
||||
}
|
||||
// PP is untagged on ARM64.
|
||||
ASSERT(Utils::IsAligned(offset, 8));
|
||||
*index = (offset - Array::data_offset()) / 8;
|
||||
*index = ObjectPool::IndexFromOffset(offset - kHeapObjectTag);
|
||||
return start;
|
||||
}
|
||||
|
||||
|
||||
@@ -11,61 +11,6 @@
|
||||
|
||||
namespace dart {
|
||||
|
||||
bool InstructionPattern::TestBytesWith(const int* data, int num_bytes) const {
|
||||
ASSERT(data != NULL);
|
||||
const uint8_t* byte_array = reinterpret_cast<const uint8_t*>(start_);
|
||||
for (int i = 0; i < num_bytes; i++) {
|
||||
// Skip comparison for data[i] < 0.
|
||||
if ((data[i] >= 0) && (byte_array[i] != (0xFF & data[i]))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
uword CallOrJumpPattern::TargetAddress() const {
|
||||
ASSERT(IsValid());
|
||||
return start() + kLengthInBytes + *reinterpret_cast<uword*>(start() + 1);
|
||||
}
|
||||
|
||||
|
||||
void CallOrJumpPattern::SetTargetAddress(uword target) const {
|
||||
ASSERT(IsValid());
|
||||
*reinterpret_cast<uword*>(start() + 1) = target - start() - kLengthInBytes;
|
||||
CPU::FlushICache(start() + 1, kWordSize);
|
||||
}
|
||||
|
||||
|
||||
const int* CallPattern::pattern() const {
|
||||
static const int kCallPattern[kLengthInBytes] = {0xE8, -1, -1, -1, -1};
|
||||
return kCallPattern;
|
||||
}
|
||||
|
||||
|
||||
const int* JumpPattern::pattern() const {
|
||||
static const int kJumpPattern[kLengthInBytes] = {0xE9, -1, -1, -1, -1};
|
||||
return kJumpPattern;
|
||||
}
|
||||
|
||||
|
||||
const int* ReturnPattern::pattern() const {
|
||||
static const int kReturnPattern[kLengthInBytes] = { 0xC3 };
|
||||
return kReturnPattern;
|
||||
}
|
||||
|
||||
|
||||
const int* ProloguePattern::pattern() const {
|
||||
static const int kProloguePattern[kLengthInBytes] = { 0x55, 0x89, 0xe5 };
|
||||
return kProloguePattern;
|
||||
}
|
||||
|
||||
|
||||
const int* SetFramePointerPattern::pattern() const {
|
||||
static const int kFramePointerPattern[kLengthInBytes] = { 0x89, 0xe5 };
|
||||
return kFramePointerPattern;
|
||||
}
|
||||
|
||||
} // namespace dart
|
||||
|
||||
#endif // defined TARGET_ARCH_IA32
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#endif
|
||||
|
||||
#include "vm/allocation.h"
|
||||
#include "vm/cpu.h"
|
||||
#include "vm/object.h"
|
||||
|
||||
namespace dart {
|
||||
@@ -20,24 +21,22 @@ class RawClass;
|
||||
class Immediate;
|
||||
class RawObject;
|
||||
|
||||
// Abstract class for all instruction pattern classes.
|
||||
class InstructionPattern : public ValueObject {
|
||||
// Template class for all instruction pattern classes.
|
||||
// P has to specify a static pattern and a pattern length method.
|
||||
template<class P> class InstructionPattern : public ValueObject {
|
||||
public:
|
||||
explicit InstructionPattern(uword pc) : start_(pc) {
|
||||
ASSERT(pc != 0);
|
||||
}
|
||||
virtual ~InstructionPattern() {}
|
||||
|
||||
// Call to check if the instruction pattern at 'pc' match the instruction.
|
||||
virtual bool IsValid() const {
|
||||
return TestBytesWith(pattern(), pattern_length_in_bytes());
|
||||
// 'P::pattern()' returns the expected byte pattern in form of an integer
|
||||
// array with length of 'P::pattern_length_in_bytes()'. A '-1' element means
|
||||
// 'any byte'.
|
||||
bool IsValid() const {
|
||||
return TestBytesWith(P::pattern(), P::pattern_length_in_bytes());
|
||||
}
|
||||
|
||||
// 'pattern' returns the expected byte pattern in form of an integer array
|
||||
// with length of 'pattern_length_in_bytes'. A '-1' element means 'any byte'.
|
||||
virtual const int* pattern() const = 0;
|
||||
virtual int pattern_length_in_bytes() const = 0;
|
||||
|
||||
protected:
|
||||
uword start() const { return start_; }
|
||||
|
||||
@@ -45,7 +44,17 @@ class InstructionPattern : public ValueObject {
|
||||
// Returns true if the 'num_bytes' bytes at 'start_' correspond to
|
||||
// array of integers 'data'. 'data' elements are either a byte or -1, which
|
||||
// represents any byte.
|
||||
bool TestBytesWith(const int* data, int num_bytes) const;
|
||||
bool TestBytesWith(const int* data, int num_bytes) const {
|
||||
ASSERT(data != NULL);
|
||||
const uint8_t* byte_array = reinterpret_cast<const uint8_t*>(start_);
|
||||
for (int i = 0; i < num_bytes; i++) {
|
||||
// Skip comparison for data[i] < 0.
|
||||
if ((data[i] >= 0) && (byte_array[i] != (0xFF & data[i]))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
const uword start_;
|
||||
|
||||
@@ -53,54 +62,74 @@ class InstructionPattern : public ValueObject {
|
||||
};
|
||||
|
||||
|
||||
class CallOrJumpPattern : public InstructionPattern {
|
||||
template<class P>
|
||||
class CallOrJumpPattern : public InstructionPattern<P> {
|
||||
public:
|
||||
virtual int pattern_length_in_bytes() const {
|
||||
return kLengthInBytes;
|
||||
uword TargetAddress() const {
|
||||
ASSERT(this->IsValid());
|
||||
return this->start() +
|
||||
P::pattern_length_in_bytes() +
|
||||
*reinterpret_cast<uword*>(this->start() + 1);
|
||||
}
|
||||
|
||||
void SetTargetAddress(uword new_target) const {
|
||||
ASSERT(this->IsValid());
|
||||
*reinterpret_cast<uword*>(this->start() + 1) =
|
||||
new_target - this->start() - P::pattern_length_in_bytes();
|
||||
CPU::FlushICache(this->start() + 1, kWordSize);
|
||||
}
|
||||
uword TargetAddress() const;
|
||||
void SetTargetAddress(uword new_target) const;
|
||||
|
||||
protected:
|
||||
explicit CallOrJumpPattern(uword pc) : InstructionPattern(pc) {}
|
||||
static const int kLengthInBytes = 5;
|
||||
explicit CallOrJumpPattern(uword pc) : InstructionPattern<P>(pc) {}
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(CallOrJumpPattern);
|
||||
};
|
||||
|
||||
|
||||
class CallPattern : public CallOrJumpPattern {
|
||||
class CallPattern : public CallOrJumpPattern<CallPattern> {
|
||||
public:
|
||||
explicit CallPattern(uword pc) : CallOrJumpPattern(pc) {}
|
||||
static int InstructionLength() {
|
||||
return kLengthInBytes;
|
||||
|
||||
static int pattern_length_in_bytes() { return kLengthInBytes; }
|
||||
static const int* pattern() {
|
||||
static const int kCallPattern[kLengthInBytes] = {0xE8, -1, -1, -1, -1};
|
||||
return kCallPattern;
|
||||
}
|
||||
|
||||
private:
|
||||
virtual const int* pattern() const;
|
||||
static const int kLengthInBytes = 5;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(CallPattern);
|
||||
};
|
||||
|
||||
|
||||
class JumpPattern : public CallOrJumpPattern {
|
||||
class JumpPattern : public CallOrJumpPattern<JumpPattern> {
|
||||
public:
|
||||
JumpPattern(uword pc, const Code& code) : CallOrJumpPattern(pc) {}
|
||||
|
||||
static int pattern_length_in_bytes() { return kLengthInBytes; }
|
||||
static const int* pattern() {
|
||||
static const int kJumpPattern[kLengthInBytes] = {0xE9, -1, -1, -1, -1};
|
||||
return kJumpPattern;
|
||||
}
|
||||
|
||||
private:
|
||||
virtual const int* pattern() const;
|
||||
static const int kLengthInBytes = 5;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(JumpPattern);
|
||||
};
|
||||
|
||||
|
||||
class ReturnPattern : public InstructionPattern {
|
||||
class ReturnPattern : public InstructionPattern<ReturnPattern> {
|
||||
public:
|
||||
explicit ReturnPattern(uword pc) : InstructionPattern(pc) {}
|
||||
|
||||
virtual const int* pattern() const;
|
||||
virtual int pattern_length_in_bytes() const { return kLengthInBytes; }
|
||||
static const int* pattern() {
|
||||
static const int kReturnPattern[kLengthInBytes] = { 0xC3 };
|
||||
return kReturnPattern;
|
||||
}
|
||||
static int pattern_length_in_bytes() { return kLengthInBytes; }
|
||||
|
||||
private:
|
||||
static const int kLengthInBytes = 1;
|
||||
@@ -109,12 +138,16 @@ class ReturnPattern : public InstructionPattern {
|
||||
|
||||
// push ebp
|
||||
// mov ebp, esp
|
||||
class ProloguePattern : public InstructionPattern {
|
||||
class ProloguePattern : public InstructionPattern<ProloguePattern> {
|
||||
public:
|
||||
explicit ProloguePattern(uword pc) : InstructionPattern(pc) {}
|
||||
|
||||
virtual const int* pattern() const;
|
||||
virtual int pattern_length_in_bytes() const { return kLengthInBytes; }
|
||||
static const int* pattern() {
|
||||
static const int kProloguePattern[kLengthInBytes] = { 0x55, 0x89, 0xe5 };
|
||||
return kProloguePattern;
|
||||
}
|
||||
|
||||
static int pattern_length_in_bytes() { return kLengthInBytes; }
|
||||
|
||||
private:
|
||||
static const int kLengthInBytes = 3;
|
||||
@@ -122,12 +155,17 @@ class ProloguePattern : public InstructionPattern {
|
||||
|
||||
|
||||
// mov ebp, esp
|
||||
class SetFramePointerPattern : public InstructionPattern {
|
||||
class SetFramePointerPattern :
|
||||
public InstructionPattern<SetFramePointerPattern> {
|
||||
public:
|
||||
explicit SetFramePointerPattern(uword pc) : InstructionPattern(pc) {}
|
||||
|
||||
virtual const int* pattern() const;
|
||||
virtual int pattern_length_in_bytes() const { return kLengthInBytes; }
|
||||
static const int* pattern() {
|
||||
static const int kFramePointerPattern[kLengthInBytes] = { 0x89, 0xe5 };
|
||||
return kFramePointerPattern;
|
||||
}
|
||||
|
||||
static int pattern_length_in_bytes() { return kLengthInBytes; }
|
||||
|
||||
private:
|
||||
static const int kLengthInBytes = 2;
|
||||
|
||||
@@ -118,9 +118,7 @@ uword InstructionPattern::DecodeLoadWordFromPool(uword end,
|
||||
// Offset is signed, so add the upper 16 bits.
|
||||
offset += (instr->UImmField() << 16);
|
||||
}
|
||||
offset += kHeapObjectTag;
|
||||
ASSERT(Utils::IsAligned(offset, 4));
|
||||
*index = (offset - Array::data_offset()) / 4;
|
||||
*index = ObjectPool::IndexFromOffset(offset);
|
||||
return start;
|
||||
}
|
||||
|
||||
|
||||
@@ -11,54 +11,27 @@
|
||||
|
||||
namespace dart {
|
||||
|
||||
intptr_t InstructionPattern::IndexFromPPLoad(uword start) {
|
||||
intptr_t IndexFromPPLoad(uword start) {
|
||||
int32_t offset = *reinterpret_cast<int32_t*>(start);
|
||||
return ObjectPool::IndexFromOffset(offset);
|
||||
}
|
||||
|
||||
|
||||
intptr_t InstructionPattern::OffsetFromPPIndex(intptr_t index) {
|
||||
intptr_t offset = ObjectPool::element_offset(index);
|
||||
return offset - kHeapObjectTag;
|
||||
}
|
||||
|
||||
|
||||
bool InstructionPattern::TestBytesWith(const int* data, int num_bytes) const {
|
||||
ASSERT(data != NULL);
|
||||
const uint8_t* byte_array = reinterpret_cast<const uint8_t*>(start_);
|
||||
for (int i = 0; i < num_bytes; i++) {
|
||||
// Skip comparison for data[i] < 0.
|
||||
if ((data[i] >= 0) && (byte_array[i] != (0xFF & data[i]))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
uword JumpPattern::TargetAddress() const {
|
||||
ASSERT(IsValid());
|
||||
int index = InstructionPattern::IndexFromPPLoad(start() + 3);
|
||||
int index = IndexFromPPLoad(start() + 3);
|
||||
return object_pool_.RawValueAt(index);
|
||||
}
|
||||
|
||||
|
||||
void JumpPattern::SetTargetAddress(uword target) const {
|
||||
ASSERT(IsValid());
|
||||
int index = InstructionPattern::IndexFromPPLoad(start() + 3);
|
||||
int index = IndexFromPPLoad(start() + 3);
|
||||
object_pool_.SetRawValueAt(index, target);
|
||||
// No need to flush the instruction cache, since the code is not modified.
|
||||
}
|
||||
|
||||
|
||||
const int* JumpPattern::pattern() const {
|
||||
// 07: 41 ff a7 imm32 jmpq [reg + off]
|
||||
static const int kJumpPattern[kLengthInBytes] =
|
||||
{0x41, 0xFF, -1, -1, -1, -1, -1};
|
||||
return kJumpPattern;
|
||||
}
|
||||
|
||||
|
||||
void ShortCallPattern::SetTargetAddress(uword target) const {
|
||||
ASSERT(IsValid());
|
||||
*reinterpret_cast<uint32_t*>(start() + 1) = target - start() - kLengthInBytes;
|
||||
@@ -66,30 +39,6 @@ void ShortCallPattern::SetTargetAddress(uword target) const {
|
||||
}
|
||||
|
||||
|
||||
const int* ShortCallPattern::pattern() const {
|
||||
static const int kCallPattern[kLengthInBytes] = {0xE8, -1, -1, -1, -1};
|
||||
return kCallPattern;
|
||||
}
|
||||
|
||||
|
||||
const int* ReturnPattern::pattern() const {
|
||||
static const int kReturnPattern[kLengthInBytes] = { 0xC3 };
|
||||
return kReturnPattern;
|
||||
}
|
||||
|
||||
|
||||
const int* ProloguePattern::pattern() const {
|
||||
static const int kProloguePattern[kLengthInBytes] =
|
||||
{ 0x55, 0x48, 0x89, 0xe5 };
|
||||
return kProloguePattern;
|
||||
}
|
||||
|
||||
|
||||
const int* SetFramePointerPattern::pattern() const {
|
||||
static const int kFramePointerPattern[kLengthInBytes] = { 0x48, 0x89, 0xe5 };
|
||||
return kFramePointerPattern;
|
||||
}
|
||||
|
||||
} // namespace dart
|
||||
|
||||
#endif // defined TARGET_ARCH_X64
|
||||
|
||||
@@ -20,27 +20,26 @@ class RawClass;
|
||||
class Immediate;
|
||||
class RawObject;
|
||||
|
||||
// Abstract class for all instruction pattern classes.
|
||||
class InstructionPattern : public ValueObject {
|
||||
|
||||
intptr_t IndexFromPPLoad(uword start);
|
||||
|
||||
|
||||
// Template class for all instruction pattern classes.
|
||||
// P has to specify a static pattern and a pattern length method.
|
||||
template<class P> class InstructionPattern : public ValueObject {
|
||||
public:
|
||||
explicit InstructionPattern(uword pc) : start_(pc) {
|
||||
ASSERT(pc != 0);
|
||||
}
|
||||
virtual ~InstructionPattern() {}
|
||||
|
||||
// Call to check if the instruction pattern at 'pc' match the instruction.
|
||||
virtual bool IsValid() const {
|
||||
return TestBytesWith(pattern(), pattern_length_in_bytes());
|
||||
// 'P::pattern()' returns the expected byte pattern in form of an integer
|
||||
// array with length of 'P::pattern_length_in_bytes()'. A '-1' element means
|
||||
// 'any byte'.
|
||||
bool IsValid() const {
|
||||
return TestBytesWith(P::pattern(), P::pattern_length_in_bytes());
|
||||
}
|
||||
|
||||
// 'pattern' returns the expected byte pattern in form of an integer array
|
||||
// with length of 'pattern_length_in_bytes'. A '-1' element means 'any byte'.
|
||||
virtual const int* pattern() const = 0;
|
||||
virtual int pattern_length_in_bytes() const = 0;
|
||||
|
||||
static intptr_t IndexFromPPLoad(uword start);
|
||||
static intptr_t OffsetFromPPIndex(intptr_t index);
|
||||
|
||||
protected:
|
||||
uword start() const { return start_; }
|
||||
|
||||
@@ -48,7 +47,17 @@ class InstructionPattern : public ValueObject {
|
||||
// Returns true if the 'num_bytes' bytes at 'start_' correspond to
|
||||
// array of integers 'data'. 'data' elements are either a byte or -1, which
|
||||
// represents any byte.
|
||||
bool TestBytesWith(const int* data, int num_bytes) const;
|
||||
bool TestBytesWith(const int* data, int num_bytes) const {
|
||||
ASSERT(data != NULL);
|
||||
const uint8_t* byte_array = reinterpret_cast<const uint8_t*>(start_);
|
||||
for (int i = 0; i < num_bytes; i++) {
|
||||
// Skip comparison for data[i] < 0.
|
||||
if ((data[i] >= 0) && (byte_array[i] != (0xFF & data[i]))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
const uword start_;
|
||||
|
||||
@@ -56,23 +65,24 @@ class InstructionPattern : public ValueObject {
|
||||
};
|
||||
|
||||
|
||||
class JumpPattern : public InstructionPattern {
|
||||
class JumpPattern : public InstructionPattern<JumpPattern> {
|
||||
public:
|
||||
JumpPattern(uword pc, const Code& code)
|
||||
: InstructionPattern(pc),
|
||||
object_pool_(ObjectPool::Handle(code.GetObjectPool())) {}
|
||||
static int InstructionLength() {
|
||||
return kLengthInBytes;
|
||||
}
|
||||
|
||||
uword TargetAddress() const;
|
||||
void SetTargetAddress(uword new_target) const;
|
||||
virtual int pattern_length_in_bytes() const {
|
||||
return kLengthInBytes;
|
||||
}
|
||||
|
||||
static const int kLengthInBytes = 7;
|
||||
static int pattern_length_in_bytes() { return kLengthInBytes; }
|
||||
static const int* pattern() {
|
||||
// 07: 41 ff a7 imm32 jmpq [reg + off]
|
||||
static const int kJumpPattern[kLengthInBytes] =
|
||||
{0x41, 0xFF, -1, -1, -1, -1, -1};
|
||||
return kJumpPattern;
|
||||
}
|
||||
private:
|
||||
virtual const int* pattern() const;
|
||||
const ObjectPool& object_pool_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(JumpPattern);
|
||||
@@ -80,33 +90,34 @@ class JumpPattern : public InstructionPattern {
|
||||
|
||||
|
||||
// 5 byte call instruction.
|
||||
class ShortCallPattern : public InstructionPattern {
|
||||
class ShortCallPattern : public InstructionPattern<ShortCallPattern> {
|
||||
public:
|
||||
explicit ShortCallPattern(uword pc) : InstructionPattern(pc) {}
|
||||
static int InstructionLength() {
|
||||
return kLengthInBytes;
|
||||
}
|
||||
|
||||
virtual int pattern_length_in_bytes() const {
|
||||
return kLengthInBytes;
|
||||
}
|
||||
|
||||
void SetTargetAddress(uword new_target) const;
|
||||
|
||||
static int pattern_length_in_bytes() { return kLengthInBytes; }
|
||||
static const int* pattern() {
|
||||
static const int kCallPattern[kLengthInBytes] = {0xE8, -1, -1, -1, -1};
|
||||
return kCallPattern;
|
||||
}
|
||||
|
||||
private:
|
||||
static const int kLengthInBytes = 5;
|
||||
virtual const int* pattern() const;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(ShortCallPattern);
|
||||
};
|
||||
|
||||
|
||||
class ReturnPattern : public InstructionPattern {
|
||||
class ReturnPattern : public InstructionPattern<ReturnPattern> {
|
||||
public:
|
||||
explicit ReturnPattern(uword pc) : InstructionPattern(pc) {}
|
||||
|
||||
virtual const int* pattern() const;
|
||||
virtual int pattern_length_in_bytes() const { return kLengthInBytes; }
|
||||
static const int* pattern() {
|
||||
static const int kReturnPattern[kLengthInBytes] = { 0xC3 };
|
||||
return kReturnPattern;
|
||||
}
|
||||
|
||||
static int pattern_length_in_bytes() { return kLengthInBytes; }
|
||||
|
||||
private:
|
||||
static const int kLengthInBytes = 1;
|
||||
@@ -115,12 +126,17 @@ class ReturnPattern : public InstructionPattern {
|
||||
|
||||
// push rbp
|
||||
// mov rbp, rsp
|
||||
class ProloguePattern : public InstructionPattern {
|
||||
class ProloguePattern : public InstructionPattern<ProloguePattern> {
|
||||
public:
|
||||
explicit ProloguePattern(uword pc) : InstructionPattern(pc) {}
|
||||
|
||||
virtual const int* pattern() const;
|
||||
virtual int pattern_length_in_bytes() const { return kLengthInBytes; }
|
||||
static const int* pattern() {
|
||||
static const int kProloguePattern[kLengthInBytes] =
|
||||
{ 0x55, 0x48, 0x89, 0xe5 };
|
||||
return kProloguePattern;
|
||||
}
|
||||
|
||||
static int pattern_length_in_bytes() { return kLengthInBytes; }
|
||||
|
||||
private:
|
||||
static const int kLengthInBytes = 4;
|
||||
@@ -128,12 +144,18 @@ class ProloguePattern : public InstructionPattern {
|
||||
|
||||
|
||||
// mov rbp, rsp
|
||||
class SetFramePointerPattern : public InstructionPattern {
|
||||
class SetFramePointerPattern :
|
||||
public InstructionPattern<SetFramePointerPattern> {
|
||||
public:
|
||||
explicit SetFramePointerPattern(uword pc) : InstructionPattern(pc) {}
|
||||
|
||||
virtual const int* pattern() const;
|
||||
virtual int pattern_length_in_bytes() const { return kLengthInBytes; }
|
||||
static const int* pattern() {
|
||||
static const int kFramePointerPattern[kLengthInBytes] =
|
||||
{ 0x48, 0x89, 0xe5 };
|
||||
return kFramePointerPattern;
|
||||
}
|
||||
|
||||
static int pattern_length_in_bytes() { return kLengthInBytes; }
|
||||
|
||||
private:
|
||||
static const int kLengthInBytes = 3;
|
||||
|
||||
@@ -3625,10 +3625,16 @@ class ObjectPool : public Object {
|
||||
|
||||
static RawObjectPool* New(intptr_t len);
|
||||
|
||||
// Returns the pool index from the offset relative to a tagged RawObjectPool*,
|
||||
// adjusting for the tag-bit.
|
||||
static intptr_t IndexFromOffset(intptr_t offset) {
|
||||
return (offset + kHeapObjectTag - data_offset()) / kBytesPerElement;
|
||||
}
|
||||
|
||||
static intptr_t OffsetFromIndex(intptr_t index) {
|
||||
return element_offset(index) - kHeapObjectTag;
|
||||
}
|
||||
|
||||
void DebugPrint() const;
|
||||
|
||||
private:
|
||||
|
||||
@@ -458,7 +458,7 @@ void StubCode::GenerateDeoptimizeLazyStub(Assembler* assembler) {
|
||||
// Correct return address to point just after the call that is being
|
||||
// deoptimized.
|
||||
__ popl(EBX);
|
||||
__ subl(EBX, Immediate(CallPattern::InstructionLength()));
|
||||
__ subl(EBX, Immediate(CallPattern::pattern_length_in_bytes()));
|
||||
__ pushl(EBX);
|
||||
GenerateDeoptimizationSequence(assembler, true); // Preserve EAX.
|
||||
}
|
||||
|
||||
@@ -479,7 +479,7 @@ void StubCode::GenerateDeoptimizeLazyStub(Assembler* assembler) {
|
||||
// Correct return address to point just after the call that is being
|
||||
// deoptimized.
|
||||
__ popq(RBX);
|
||||
__ subq(RBX, Immediate(ShortCallPattern::InstructionLength()));
|
||||
__ subq(RBX, Immediate(ShortCallPattern::pattern_length_in_bytes()));
|
||||
__ pushq(RBX);
|
||||
GenerateDeoptimizationSequence(assembler, true); // Preserve RAX.
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user