From bd4ef415b534a862bed078aec661f352a2a77d93 Mon Sep 17 00:00:00 2001 From: Jakob Olesen Date: Mon, 23 Nov 2015 15:28:46 -0800 Subject: [PATCH] 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. --- js/src/jit/shared/IonAssemblerBuffer.h | 28 +++--- js/src/jsapi-tests/moz.build | 5 + js/src/jsapi-tests/testAssemblerBuffer.cpp | 112 +++++++++++++++++++++ 3 files changed, 132 insertions(+), 13 deletions(-) create mode 100644 js/src/jsapi-tests/testAssemblerBuffer.cpp diff --git a/js/src/jit/shared/IonAssemblerBuffer.h b/js/src/jit/shared/IonAssemblerBuffer.h index aa4b4dfdddc..da40a5e8026 100644 --- a/js/src/jit/shared/IonAssemblerBuffer.h +++ b/js/src/jit/shared/IonAssemblerBuffer.h @@ -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(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) { diff --git a/js/src/jsapi-tests/moz.build b/js/src/jsapi-tests/moz.build index c62193e2d3a..40b15dbc417 100644 --- a/js/src/jsapi-tests/moz.build +++ b/js/src/jsapi-tests/moz.build @@ -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', diff --git a/js/src/jsapi-tests/testAssemblerBuffer.cpp b/js/src/jsapi-tests/testAssemblerBuffer.cpp new file mode 100644 index 00000000000..26742a83c32 --- /dev/null +++ b/js/src/jsapi-tests/testAssemblerBuffer.cpp @@ -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 + +#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)