Bug 1210554 - Add testAssemblerBuffer to jsapi-tests. r=sstangl

Also minor fixes to the AssemblerBuffer class:

- Tighten encapsulation / data hiding.
- Use consistent types size_t + void* for raw byte data.
This commit is contained in:
Jakob Olesen 2015-11-23 15:28:46 -08:00
parent f039e968c0
commit bd4ef415b5
3 changed files with 132 additions and 13 deletions

View File

@ -88,7 +88,7 @@ class BufferSlice
next->prev_ = this;
}
void putBytes(size_t numBytes, const uint8_t* source) {
void putBytes(size_t numBytes, const void* source) {
MOZ_ASSERT(bytelength_ + numBytes <= SliceSize);
if (source)
memcpy(&instructions[length()], source, numBytes);
@ -107,7 +107,6 @@ class AssemblerBuffer
Slice* head;
Slice* tail;
public:
bool m_oom;
bool m_bail;
@ -139,6 +138,7 @@ class AssemblerBuffer
return !(size() & (alignment - 1));
}
protected:
virtual Slice* newSlice(LifoAlloc& a) {
Slice* tmp = static_cast<Slice*>(a.alloc(sizeof(Slice)));
if (!tmp) {
@ -148,7 +148,8 @@ class AssemblerBuffer
return new (tmp) Slice;
}
bool ensureSpace(int size) {
public:
bool ensureSpace(size_t size) {
// Space can exist in the most recent Slice.
if (tail && tail->length() + size <= tail->Capacity()) {
// Simulate allocation failure even when we don't need a new slice.
@ -181,32 +182,32 @@ class AssemblerBuffer
}
BufferOffset putByte(uint8_t value) {
return putBytes(sizeof(value), (uint8_t*)&value);
return putBytes(sizeof(value), &value);
}
BufferOffset putShort(uint16_t value) {
return putBytes(sizeof(value), (uint8_t*)&value);
return putBytes(sizeof(value), &value);
}
BufferOffset putInt(uint32_t value) {
return putBytes(sizeof(value), (uint8_t*)&value);
return putBytes(sizeof(value), &value);
}
// Add instSize bytes to this buffer.
// Add numBytes bytes to this buffer.
// The data must fit in a single slice.
BufferOffset putBytes(uint32_t instSize, uint8_t* inst) {
if (!ensureSpace(instSize))
BufferOffset putBytes(size_t numBytes, const void* inst) {
if (!ensureSpace(numBytes))
return BufferOffset();
BufferOffset ret = nextOffset();
tail->putBytes(instSize, inst);
tail->putBytes(numBytes, inst);
return ret;
}
// Add a potentially large amount of data to this buffer.
// The data may be distrubuted across multiple slices.
// Return the buffer offset of the first added byte.
BufferOffset putBytesLarge(size_t numBytes, const uint8_t* data)
BufferOffset putBytesLarge(size_t numBytes, const void* data)
{
BufferOffset ret = nextOffset();
while (numBytes > 0) {
@ -216,7 +217,7 @@ class AssemblerBuffer
size_t xfer = numBytes < avail ? numBytes : avail;
MOZ_ASSERT(xfer > 0, "ensureSpace should have allocated a slice");
tail->putBytes(xfer, data);
data += xfer;
data = (const uint8_t*)data + xfer;
numBytes -= xfer;
}
return ret;
@ -239,12 +240,13 @@ class AssemblerBuffer
m_bail = true;
return false;
}
private:
void update_finger(Slice* finger_, int fingerOffset_) {
finger = finger_;
finger_offset = fingerOffset_;
}
private:
static const unsigned SliceDistanceRequiringFingerUpdate = 3;
Inst* getInstForwards(BufferOffset off, Slice* start, int startOffset, bool updateFinger = false) {

View File

@ -90,6 +90,11 @@ UNIFIED_SOURCES += [
'testXDR.cpp',
]
SOURCES += [
# There are clashing definitions of js::jit::AssemblerBuffer.
'testAssemblerBuffer.cpp',
]
if CONFIG['ENABLE_ION']:
UNIFIED_SOURCES += [
'testJitDCEinGVN.cpp',

View File

@ -0,0 +1,112 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include <stdlib.h>
#include "jsatom.h"
#include "jit/shared/IonAssemblerBufferWithConstantPools.h"
#include "jsapi-tests/tests.h"
// Tests for classes in:
//
// jit/shared/IonAssemblerBuffer.h
// jit/shared/IonAssemblerBufferWithConstantPools.h
//
// Classes in js::jit tested:
//
// BufferOffset
// BufferSlice (implicitly)
// AssemblerBuffer
//
// BranchDeadlineSet
// Pool (implicitly)
// AssemblerBufferWithConstantPools
//
BEGIN_TEST(testAssemblerBuffer_BufferOffset)
{
using js::jit::BufferOffset;
BufferOffset off1;
BufferOffset off2(10);
CHECK(!off1.assigned());
CHECK(off2.assigned());
CHECK_EQUAL(off2.getOffset(), 10);
off1 = off2;
CHECK(off1.assigned());
CHECK_EQUAL(off1.getOffset(), 10);
return true;
}
END_TEST(testAssemblerBuffer_BufferOffset)
BEGIN_TEST(testAssemblerBuffer_AssemblerBuffer)
{
using js::jit::BufferOffset;
typedef js::jit::AssemblerBuffer<5 * sizeof(uint32_t), uint32_t> AsmBuf;
AsmBuf ab;
CHECK(ab.isAligned(16));
CHECK_EQUAL(ab.size(), 0u);
CHECK_EQUAL(ab.nextOffset().getOffset(), 0);
CHECK(!ab.oom());
CHECK(!ab.bail());
BufferOffset off1 = ab.putInt(1000017);
CHECK_EQUAL(off1.getOffset(), 0);
CHECK_EQUAL(ab.size(), 4u);
CHECK_EQUAL(ab.nextOffset().getOffset(), 4);
CHECK(!ab.isAligned(16));
CHECK(ab.isAligned(4));
CHECK(ab.isAligned(1));
CHECK_EQUAL(*ab.getInst(off1), 1000017u);
BufferOffset off2 = ab.putInt(1000018);
CHECK_EQUAL(off2.getOffset(), 4);
BufferOffset off3 = ab.putInt(1000019);
CHECK_EQUAL(off3.getOffset(), 8);
BufferOffset off4 = ab.putInt(1000020);
CHECK_EQUAL(off4.getOffset(), 12);
CHECK_EQUAL(ab.size(), 16u);
CHECK_EQUAL(ab.nextOffset().getOffset(), 16);
// Last one in the slice.
BufferOffset off5 = ab.putInt(1000021);
CHECK_EQUAL(off5.getOffset(), 16);
CHECK_EQUAL(ab.size(), 20u);
CHECK_EQUAL(ab.nextOffset().getOffset(), 20);
BufferOffset off6 = ab.putInt(1000022);
CHECK_EQUAL(off6.getOffset(), 20);
CHECK_EQUAL(ab.size(), 24u);
CHECK_EQUAL(ab.nextOffset().getOffset(), 24);
// Reference previous slice. Excercise the finger.
CHECK_EQUAL(*ab.getInst(off1), 1000017u);
CHECK_EQUAL(*ab.getInst(off6), 1000022u);
CHECK_EQUAL(*ab.getInst(off1), 1000017u);
CHECK_EQUAL(*ab.getInst(off5), 1000021u);
// Too much data for one slice.
const uint32_t fixdata[] = { 2000036, 2000037, 2000038, 2000039, 2000040, 2000041 };
// Split payload across multiple slices.
CHECK_EQUAL(ab.nextOffset().getOffset(), 24);
BufferOffset good1 = ab.putBytesLarge(sizeof(fixdata), fixdata);
CHECK_EQUAL(good1.getOffset(), 24);
CHECK_EQUAL(ab.nextOffset().getOffset(), 48);
CHECK_EQUAL(*ab.getInst(good1), 2000036u);
CHECK_EQUAL(*ab.getInst(BufferOffset(32)), 2000038u);
CHECK_EQUAL(*ab.getInst(BufferOffset(36)), 2000039u);
CHECK_EQUAL(*ab.getInst(BufferOffset(40)), 2000040u);
CHECK_EQUAL(*ab.getInst(BufferOffset(44)), 2000041u);
return true;
}
END_TEST(testAssemblerBuffer_AssemblerBuffer)