Implement local setting.
I've also worked out how to test CreateString and CreateObject, but
not CreateArrayObject yet.
Also stop saying "cnt".
Change-Id: I26569ff6c4fa356fb91e6c22cbf8ced95094fabd
diff --git a/src/debugger.cc b/src/debugger.cc
index a858962..98d501c 100644
--- a/src/debugger.cc
+++ b/src/debugger.cc
@@ -716,13 +716,12 @@
}
JDWP::ObjectId Dbg::CreateString(const char* str) {
- UNIMPLEMENTED(FATAL);
- return 0;
+ return gRegistry->Add(String::AllocFromModifiedUtf8(str));
}
JDWP::ObjectId Dbg::CreateObject(JDWP::RefTypeId classId) {
- UNIMPLEMENTED(FATAL);
- return 0;
+ Class* c = gRegistry->Get<Class*>(classId);
+ return gRegistry->Add(c->AllocObject());
}
JDWP::ObjectId Dbg::CreateArrayObject(JDWP::RefTypeId arrayTypeId, uint32_t length) {
@@ -1295,7 +1294,7 @@
return false;
}
-void Dbg::GetLocalValue(JDWP::ObjectId threadId, JDWP::FrameId frameId, int slot, JDWP::JdwpTag tag, uint8_t* buf, size_t expectedLen) {
+void Dbg::GetLocalValue(JDWP::ObjectId threadId, JDWP::FrameId frameId, int slot, JDWP::JdwpTag tag, uint8_t* buf, size_t width) {
Method** sp = reinterpret_cast<Method**>(frameId);
Frame f;
f.SetSP(sp);
@@ -1311,7 +1310,7 @@
switch (tag) {
case JDWP::JT_BOOLEAN:
{
- CHECK_EQ(expectedLen, 1U);
+ CHECK_EQ(width, 1U);
uint32_t intVal = f.GetVReg(m, reg);
LOG(VERBOSE) << "get boolean local " << reg << " = " << intVal;
JDWP::Set1(buf+1, intVal != 0);
@@ -1319,7 +1318,7 @@
break;
case JDWP::JT_BYTE:
{
- CHECK_EQ(expectedLen, 1U);
+ CHECK_EQ(width, 1U);
uint32_t intVal = f.GetVReg(m, reg);
LOG(VERBOSE) << "get byte local " << reg << " = " << intVal;
JDWP::Set1(buf+1, intVal);
@@ -1328,7 +1327,7 @@
case JDWP::JT_SHORT:
case JDWP::JT_CHAR:
{
- CHECK_EQ(expectedLen, 2U);
+ CHECK_EQ(width, 2U);
uint32_t intVal = f.GetVReg(m, reg);
LOG(VERBOSE) << "get short/char local " << reg << " = " << intVal;
JDWP::Set2BE(buf+1, intVal);
@@ -1337,7 +1336,7 @@
case JDWP::JT_INT:
case JDWP::JT_FLOAT:
{
- CHECK_EQ(expectedLen, 4U);
+ CHECK_EQ(width, 4U);
uint32_t intVal = f.GetVReg(m, reg);
LOG(VERBOSE) << "get int/float local " << reg << " = " << intVal;
JDWP::Set4BE(buf+1, intVal);
@@ -1345,7 +1344,7 @@
break;
case JDWP::JT_ARRAY:
{
- CHECK_EQ(expectedLen, sizeof(JDWP::ObjectId));
+ CHECK_EQ(width, sizeof(JDWP::ObjectId));
Object* o = reinterpret_cast<Object*>(f.GetVReg(m, reg));
LOG(VERBOSE) << "get array local " << reg << " = " << o;
if (o != NULL && !Heap::IsHeapAddress(o)) {
@@ -1356,7 +1355,7 @@
break;
case JDWP::JT_OBJECT:
{
- CHECK_EQ(expectedLen, sizeof(JDWP::ObjectId));
+ CHECK_EQ(width, sizeof(JDWP::ObjectId));
Object* o = reinterpret_cast<Object*>(f.GetVReg(m, reg));
LOG(VERBOSE) << "get object local " << reg << " = " << o;
if (o != NULL && !Heap::IsHeapAddress(o)) {
@@ -1369,7 +1368,7 @@
case JDWP::JT_DOUBLE:
case JDWP::JT_LONG:
{
- CHECK_EQ(expectedLen, 8U);
+ CHECK_EQ(width, 8U);
uint32_t lo = f.GetVReg(m, reg);
uint64_t hi = f.GetVReg(m, reg + 1);
uint64_t longVal = (hi << 32) | lo;
@@ -1387,7 +1386,53 @@
}
void Dbg::SetLocalValue(JDWP::ObjectId threadId, JDWP::FrameId frameId, int slot, JDWP::JdwpTag tag, uint64_t value, size_t width) {
- UNIMPLEMENTED(FATAL);
+ Method** sp = reinterpret_cast<Method**>(frameId);
+ Frame f;
+ f.SetSP(sp);
+ uint16_t reg = DemangleSlot(slot, f);
+ Method* m = f.GetMethod();
+
+ const VmapTable vmap_table(m->GetVmapTableRaw());
+ uint32_t vmap_offset;
+ if (vmap_table.IsInContext(reg, vmap_offset)) {
+ UNIMPLEMENTED(FATAL) << "don't know how to pull locals from callee save frames: " << vmap_offset;
+ }
+
+ switch (tag) {
+ case JDWP::JT_BOOLEAN:
+ case JDWP::JT_BYTE:
+ CHECK_EQ(width, 1U);
+ f.SetVReg(m, reg, static_cast<uint32_t>(value));
+ break;
+ case JDWP::JT_SHORT:
+ case JDWP::JT_CHAR:
+ CHECK_EQ(width, 2U);
+ f.SetVReg(m, reg, static_cast<uint32_t>(value));
+ break;
+ case JDWP::JT_INT:
+ case JDWP::JT_FLOAT:
+ CHECK_EQ(width, 4U);
+ f.SetVReg(m, reg, static_cast<uint32_t>(value));
+ break;
+ case JDWP::JT_ARRAY:
+ case JDWP::JT_OBJECT:
+ case JDWP::JT_STRING:
+ {
+ CHECK_EQ(width, sizeof(JDWP::ObjectId));
+ Object* o = gRegistry->Get<Object*>(static_cast<JDWP::ObjectId>(value));
+ f.SetVReg(m, reg, static_cast<uint32_t>(reinterpret_cast<uintptr_t>(o)));
+ }
+ break;
+ case JDWP::JT_DOUBLE:
+ case JDWP::JT_LONG:
+ CHECK_EQ(width, 8U);
+ f.SetVReg(m, reg, static_cast<uint32_t>(value));
+ f.SetVReg(m, reg + 1, static_cast<uint32_t>(value >> 32));
+ break;
+ default:
+ LOG(FATAL) << "unknown tag " << tag;
+ break;
+ }
}
void Dbg::PostLocationEvent(const Method* method, int pcOffset, Object* thisPtr, int eventFlags) {
@@ -1640,11 +1685,11 @@
DdmSendChunk(type, bytes.size(), &bytes[0]);
}
-void Dbg::DdmSendChunkV(uint32_t type, const struct iovec* iov, int iovcnt) {
+void Dbg::DdmSendChunkV(uint32_t type, const struct iovec* iov, int iov_count) {
if (gJdwpState == NULL) {
LOG(VERBOSE) << "Debugger thread not active, ignoring DDM send: " << type;
} else {
- gJdwpState->DdmSendChunkV(type, iov, iovcnt);
+ gJdwpState->DdmSendChunkV(type, iov, iov_count);
}
}
diff --git a/src/debugger.h b/src/debugger.h
index 3f0f7f6..826c787 100644
--- a/src/debugger.h
+++ b/src/debugger.h
@@ -240,7 +240,7 @@
static void DdmDisconnected();
static void DdmSendChunk(uint32_t type, const std::vector<uint8_t>& bytes);
static void DdmSendChunk(uint32_t type, size_t len, const uint8_t* buf);
- static void DdmSendChunkV(uint32_t type, const struct iovec* iov, int iovcnt);
+ static void DdmSendChunkV(uint32_t type, const struct iovec* iov, int iov_count);
/*
* Recent allocation tracking support.
diff --git a/src/jdwp/jdwp.h b/src/jdwp/jdwp.h
index f138880..b628e6c 100644
--- a/src/jdwp/jdwp.h
+++ b/src/jdwp/jdwp.h
@@ -213,7 +213,7 @@
/*
* Send up a chunk of DDM data.
*/
- void DdmSendChunkV(uint32_t type, const iovec* iov, int iovcnt);
+ void DdmSendChunkV(uint32_t type, const iovec* iov, int iov_count);
/*
* Process a request from the debugger.
diff --git a/src/jdwp/jdwp_adb.cc b/src/jdwp/jdwp_adb.cc
index 5570b53..f6b977e 100644
--- a/src/jdwp/jdwp_adb.cc
+++ b/src/jdwp/jdwp_adb.cc
@@ -670,7 +670,7 @@
*
* Returns "true" if it was sent successfully.
*/
-static bool sendBufferedRequest(JdwpState* state, const iovec* iov, int iovcnt) {
+static bool sendBufferedRequest(JdwpState* state, const iovec* iov, int iov_count) {
JdwpNetState* netState = state->netState;
if (netState->clientSock < 0) {
@@ -680,12 +680,11 @@
}
size_t expected = 0;
- int i;
- for (i = 0; i < iovcnt; i++) {
+ for (int i = 0; i < iov_count; i++) {
expected += iov[i].iov_len;
}
- ssize_t actual = netState->writeBufferedPacket(iov, iovcnt);
+ ssize_t actual = netState->writeBufferedPacket(iov, iov_count);
if ((size_t)actual != expected) {
PLOG(ERROR) << "Failed sending b-req to debugger (" << actual << " of " << expected << ")";
return false;
diff --git a/src/jdwp/jdwp_event.cc b/src/jdwp/jdwp_event.cc
index 9440066..15e1151 100644
--- a/src/jdwp/jdwp_event.cc
+++ b/src/jdwp/jdwp_event.cc
@@ -1091,19 +1091,20 @@
* other debugger traffic, and can't suspend the VM, so we skip all of
* the fun event token gymnastics.
*/
-void JdwpState::DdmSendChunkV(uint32_t type, const iovec* iov, int iovcnt) {
+void JdwpState::DdmSendChunkV(uint32_t type, const iovec* iov, int iov_count) {
uint8_t header[kJDWPHeaderLen + 8];
size_t dataLen = 0;
CHECK(iov != NULL);
- CHECK(iovcnt > 0 && iovcnt < 10);
+ CHECK_GT(iov_count, 0);
+ CHECK_LT(iov_count, 10);
/*
* "Wrap" the contents of the iovec with a JDWP/DDMS header. We do
* this by creating a new copy of the vector with space for the header.
*/
- iovec wrapiov[iovcnt+1];
- for (int i = 0; i < iovcnt; i++) {
+ iovec wrapiov[iov_count+1];
+ for (int i = 0; i < iov_count; i++) {
wrapiov[i+1].iov_base = iov[i].iov_base;
wrapiov[i+1].iov_len = iov[i].iov_len;
dataLen += iov[i].iov_len;
@@ -1125,7 +1126,7 @@
* Make sure we're in VMWAIT in case the write blocks.
*/
int old_state = Dbg::ThreadWaiting();
- (*transport->sendBufferedRequest)(this, wrapiov, iovcnt + 1);
+ (*transport->sendBufferedRequest)(this, wrapiov, iov_count + 1);
Dbg::ThreadContinuing(old_state);
}
diff --git a/src/jdwp/jdwp_main.cc b/src/jdwp/jdwp_main.cc
index 28ea303..07ffc52 100644
--- a/src/jdwp/jdwp_main.cc
+++ b/src/jdwp/jdwp_main.cc
@@ -53,9 +53,9 @@
/*
* Write a buffered packet. Grabs a mutex to assure atomicity.
*/
-ssize_t JdwpNetStateBase::writeBufferedPacket(const iovec* iov, int iovcnt) {
+ssize_t JdwpNetStateBase::writeBufferedPacket(const iovec* iov, int iov_count) {
MutexLock mu(socket_lock_);
- return writev(clientSock, iov, iovcnt);
+ return writev(clientSock, iov, iov_count);
}
bool JdwpState::IsConnected() {
diff --git a/src/jdwp/jdwp_priv.h b/src/jdwp/jdwp_priv.h
index 45d70f8..d2c35dd 100644
--- a/src/jdwp/jdwp_priv.h
+++ b/src/jdwp/jdwp_priv.h
@@ -62,7 +62,7 @@
bool (*awaitingHandshake)(JdwpState* state);
bool (*processIncoming)(JdwpState* state);
bool (*sendRequest)(JdwpState* state, ExpandBuf* pReq);
- bool (*sendBufferedRequest)(JdwpState* state, const iovec* iov, int iovcnt);
+ bool (*sendBufferedRequest)(JdwpState* state, const iovec* iov, int iov_count);
};
const JdwpTransport* SocketTransport();
@@ -77,7 +77,7 @@
JdwpNetStateBase();
ssize_t writePacket(ExpandBuf* pReply);
- ssize_t writeBufferedPacket(const iovec* iov, int iovcnt);
+ ssize_t writeBufferedPacket(const iovec* iov, int iov_count);
private:
Mutex socket_lock_;
diff --git a/src/jdwp/jdwp_socket.cc b/src/jdwp/jdwp_socket.cc
index aba893d..351e456 100644
--- a/src/jdwp/jdwp_socket.cc
+++ b/src/jdwp/jdwp_socket.cc
@@ -822,7 +822,7 @@
*
* Returns "true" if it was sent successfully.
*/
-static bool sendBufferedRequest(JdwpState* state, const iovec* iov, int iovcnt) {
+static bool sendBufferedRequest(JdwpState* state, const iovec* iov, int iov_count) {
JdwpNetState* netState = state->netState;
if (netState->clientSock < 0) {
@@ -832,11 +832,11 @@
}
size_t expected = 0;
- for (int i = 0; i < iovcnt; i++) {
+ for (int i = 0; i < iov_count; i++) {
expected += iov[i].iov_len;
}
- ssize_t actual = netState->writeBufferedPacket(iov, iovcnt);
+ ssize_t actual = netState->writeBufferedPacket(iov, iov_count);
if ((size_t)actual != expected) {
PLOG(ERROR) << "Failed sending b-req to debugger (" << actual << " of " << expected << ")";
diff --git a/src/object.cc b/src/object.cc
index 3053823..b8d82dc 100644
--- a/src/object.cc
+++ b/src/object.cc
@@ -874,13 +874,11 @@
if (new_reference_offsets != CLASS_WALK_SUPER) {
// Sanity check that the number of bits set in the reference offset bitmap
// agrees with the number of references
- Class* cur = this;
- size_t cnt = 0;
- while (cur) {
- cnt += cur->NumReferenceInstanceFieldsDuringLinking();
- cur = cur->GetSuperClass();
+ size_t count = 0;
+ for (Class* c = this; c != NULL; c = c->GetSuperClass()) {
+ count += c->NumReferenceInstanceFieldsDuringLinking();
}
- CHECK_EQ((size_t)__builtin_popcount(new_reference_offsets), cnt);
+ CHECK_EQ((size_t)__builtin_popcount(new_reference_offsets), count);
}
SetField32(OFFSET_OF_OBJECT_MEMBER(Class, reference_instance_offsets_),
new_reference_offsets, false);
diff --git a/src/stack.cc b/src/stack.cc
index 9589b57..542ac47 100644
--- a/src/stack.cc
+++ b/src/stack.cc
@@ -52,6 +52,13 @@
return *reinterpret_cast<uint32_t*>(vreg_addr);
}
+void Frame::SetVReg(Method* method, int vreg, uint32_t new_value) {
+ DCHECK(method == GetMethod());
+ int offset = oatVRegOffsetFromMethod(method, vreg);
+ byte* vreg_addr = reinterpret_cast<byte*>(sp_) + offset;
+ *reinterpret_cast<uint32_t*>(vreg_addr) = new_value;
+}
+
uintptr_t Frame::LoadCalleeSave(int num) const {
// Callee saves are held at the top of the frame
Method* method = GetMethod();
diff --git a/src/stack.h b/src/stack.h
index 680a69d..a0f13d3 100644
--- a/src/stack.h
+++ b/src/stack.h
@@ -55,6 +55,7 @@
uintptr_t LoadCalleeSave(int num) const;
uint32_t GetVReg(Method* method, int vreg) const;
+ void SetVReg(Method* method, int vreg, uint32_t new_value);
Method** GetSP() const {
return sp_;