Exemple #1
0
static void testSetIterator()
{
	// Add 1..9 to a HashSet.
	HashSet<Uptr> a;
	for(Uptr i = 1;i < 10;++i)
	{
		a.add(i);
	}

	// 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 = 45
	{
		Uptr sum = 0;
		for(Uptr i : a)
		{
			sum += i;
		}
		errorUnless(sum == 45);
	}

	// Remove 5.
	a.remove(5);
	
	// 1 + 2 + 3 + 4 + 6 + 7 + 8 + 9 = 40
	{
		Uptr sum = 0;
		for(Uptr i : a)
		{
			sum += i;
		}
		errorUnless(sum == 40);
	}
}
Exemple #2
0
	Runtime::ModuleInstance* instantiateModule(
		Runtime::Compartment* compartment,
		const Intrinsics::Module& moduleRef,
		std::string&& debugName,
		const HashMap<std::string,Runtime::Object*>& extraExports)
	{
		auto moduleInstance = new Runtime::ModuleInstance(compartment,{},{},{},{},{},std::move(debugName));

		if(moduleRef.impl)
		{
			for(const auto& pair : moduleRef.impl->functionMap)
			{
				auto functionInstance = pair.value->instantiate(compartment);
				moduleInstance->functions.push_back(functionInstance);
				errorUnless(moduleInstance->exportMap.add(pair.key, functionInstance));
			}

			for(const auto& pair : moduleRef.impl->tableMap)
			{
				auto tableInstance = pair.value->instantiate(compartment);
				moduleInstance->tables.push_back(tableInstance);
				errorUnless(moduleInstance->exportMap.add(pair.key, tableInstance));
			}

			for(const auto& pair : moduleRef.impl->memoryMap)
			{
				auto memoryInstance = pair.value->instantiate(compartment);
				moduleInstance->memories.push_back(memoryInstance);
				errorUnless(moduleInstance->exportMap.add(pair.key, memoryInstance));
			}

			for(const auto& pair : moduleRef.impl->globalMap)
			{
				auto globalInstance = pair.value->instantiate(compartment);
				moduleInstance->globals.push_back(globalInstance);
				errorUnless(moduleInstance->exportMap.add(pair.key, globalInstance));
			}

			for(const auto& pair : extraExports)
			{
				Runtime::Object* object = pair.value;
				moduleInstance->exportMap.set(pair.key, object);

				switch(object->kind)
				{
				case Runtime::ObjectKind::function: moduleInstance->functions.push_back(asFunction(object)); break;
				case Runtime::ObjectKind::table: moduleInstance->tables.push_back(asTable(object)); break;
				case Runtime::ObjectKind::memory: moduleInstance->memories.push_back(asMemory(object)); break;
				case Runtime::ObjectKind::global: moduleInstance->globals.push_back(asGlobal(object)); break;
				case Runtime::ObjectKind::exceptionTypeInstance: moduleInstance->exceptionTypeInstances.push_back(asExceptionTypeInstance(object)); break;
				default: Errors::unreachable();
				};
			}
		}

		return moduleInstance;
	}
Exemple #3
0
static void testMapSet()
{
	HashMap<Uptr, Uptr> map;
	
	errorUnless(!map.get(0));
	errorUnless(map.set(0, 1) == 1);
	errorUnless(*map.get(0) == 1);
	errorUnless(map.set(0, 3) == 3);
	errorUnless(*map.get(0) == 3);
}
Exemple #4
0
static void testSetMove()
{
	// Add 1000..1999 to a HashSet.
	HashSet<Uptr> a;
	for(Uptr i = 0;i < 1000;++i)
	{
		a.add(i + 1000);
	}

	// Move the set to a new HashSet.
	HashSet<Uptr> b {std::move(a)};

	// Test that the new HashSet contains the expected numbers.
	for(Uptr i = 0;i < 1000;++i)
	{
		errorUnless(!b.contains(i));
		errorUnless(b.contains(i + 1000));
		errorUnless(!b.contains(i + 2000));
	}

	// Test moving the set to itself.
	b = std::move(b);
	
	// Test that the set wasn't changed by the move-to-self.
	for(Uptr i = 0;i < 1000;++i)
	{
		errorUnless(!b.contains(i));
		errorUnless(b.contains(i + 1000));
		errorUnless(!b.contains(i + 2000));
	}
}
Exemple #5
0
static void testMapMove()
{
	// Add 1000..1999 to a HashMap.
	HashMap<Uptr, Uptr> a;
	for(Uptr i = 0;i < 1000;++i)
	{
		a.add(i + 1000, i);
	}

	// Move the map to a new HashMap.
	HashMap<Uptr, Uptr> b {std::move(a)};

	// Test that the new HashMap contains the expected numbers.
	for(Uptr i = 0;i < 1000;++i)
	{
		errorUnless(!b.get(i));
		errorUnless(*b.get(i + 1000) == i);
		errorUnless(!b.get(i + 2000));
	}

	// Test moving the map to itself.
	b = std::move(b);
	
	// Test that the map wasn't changed by the move-to-self.
	for(Uptr i = 0;i < 1000;++i)
	{
		errorUnless(!b.get(i));
		errorUnless(*b.get(i + 1000) == i);
		errorUnless(!b.get(i + 2000));
	}
}
Exemple #6
0
static void testMapBracketOperator()
{
	HashMap<Uptr, Uptr> map {{1,1},{3,2},{5,3},{7,4},{11,5},{13,6},{17,7}};
	errorUnless(map[1] == 1);
	errorUnless(map[3] == 2);
	errorUnless(map[5] == 3);
	errorUnless(map[7] == 4);
	errorUnless(map[11] == 5);
	errorUnless(map[13] == 6);
	errorUnless(map[17] == 7);
}
Exemple #7
0
static void testSetBracketOperator()
{
	HashSet<Uptr> set {1,3,5,7,11,13,17};
	errorUnless(set[1] == 1);
	errorUnless(set[3] == 3);
	errorUnless(set[5] == 5);
	errorUnless(set[7] == 7);
	errorUnless(set[11] == 11);
	errorUnless(set[13] == 13);
	errorUnless(set[17] == 17);
}
Exemple #8
0
static void testMapIterator()
{
	// Add 1..9 to a HashMap.
	HashMap<Uptr, Uptr> a;
	for(Uptr i = 1;i < 10;++i)
	{
		a.add(i, i * 2);
	}

	// 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 = 45
	{
		Uptr keySum = 0;
		Uptr valueSum = 0;
		for(const auto& pair : a)
		{
			keySum += pair.key;
			valueSum += pair.value;
		}
		errorUnless(keySum == 45);
		errorUnless(valueSum == 90);
	}

	// Remove 5.
	a.remove(5);
	
	// 1 + 2 + 3 + 4 + 6 + 7 + 8 + 9 = 40
	{
		Uptr keySum = 0;
		Uptr valueSum = 0;
		for(const auto& pair : a)
		{
			keySum += pair.key;
			valueSum += pair.value;
		}
		errorUnless(keySum == 40);
		errorUnless(valueSum == 80);
	}
}
Exemple #9
0
static void testMapGetOrAdd()
{
	HashMap<Uptr, Uptr> map;

	errorUnless(!map.get(0));
	errorUnless(map.getOrAdd(0, 1) == 1);
	errorUnless(*map.get(0) == 1);
	errorUnless(map.getOrAdd(0, 3) == 1);
	errorUnless(*map.get(0) == 1);
	errorUnless((map.getOrAdd(0, 5) += 7) == 8);
	errorUnless(*map.get(0) == 8);
}
Exemple #10
0
static void testStringSet()
{
	enum { numStrings = 1000 };

	HashSet<std::string> set;
	std::vector<std::string> strings;

	srand(0);

	for(Uptr i = 0;i < numStrings;++i)
	{
		while(true)
		{
			std::string randomString = generateRandomString();

			bool alreadySawString = false;
			for(const std::string& string : strings)
			{
				if(string == randomString)
				{
					alreadySawString = true;
					break;
				}
			}

			if(!alreadySawString)
			{
				strings.push_back(std::move(randomString));
				break;
			}
		};
	}

	for(Uptr i = 0;i < strings.size();++i)
	{
		errorUnless(set.add(strings[i]));
		errorUnless(!set.add(strings[i]));

		for(Uptr j = 0;j < strings.size();++j)
		{
			const bool expectedContains = j <= i;
			errorUnless(set.contains(strings[j]) == expectedContains);
		}
	}

	for(Uptr i = 0;i < strings.size();++i)
	{
		errorUnless(set.remove(strings[i]));
		errorUnless(!set.remove(strings[i]));

		for(Uptr j = 0;j < strings.size();++j)
		{
			const bool expectedContains = j > i;
			errorUnless(set.contains(strings[j]) == expectedContains);
		}
	}
}
Exemple #11
0
static void testMapEmplace()
{
	HashMap<Uptr, EmplacedValue> map;

	EmplacedValue& a = map.getOrAdd(0, "a", "b");
	errorUnless(a.a == "a");
	errorUnless(a.b == "b");
	
	errorUnless(map.add(1, "c", "d"));
	const EmplacedValue& b = *map.get(1);
	errorUnless(b.a == "c");
	errorUnless(b.b == "d");
	
	EmplacedValue& c = map.set(2, "e", "f");
	errorUnless(c.a == "e");
	errorUnless(c.b == "f");
	
	EmplacedValue& d = map.getOrAdd(2, "g", "h");
	errorUnless(d.a == "e");
	errorUnless(d.b == "f");
}
Exemple #12
0
	Value evaluateInitializer(ModuleInstance* moduleInstance,InitializerExpression expression)
	{
		switch(expression.type)
		{
		case InitializerExpression::Type::i32_const: return expression.i32;
		case InitializerExpression::Type::i64_const: return expression.i64;
		case InitializerExpression::Type::f32_const: return expression.f32;
		case InitializerExpression::Type::f64_const: return expression.f64;
		case InitializerExpression::Type::get_global:
		{
			// Find the import this refers to.
			errorUnless(expression.globalIndex < moduleInstance->globals.size());
			GlobalInstance* globalInstance = moduleInstance->globals[expression.globalIndex];
			return Runtime::Value(globalInstance->type.valueType,globalInstance->value);
		}
		default: Errors::unreachable();
		};
	}
Exemple #13
0
static void testU32Set()
{
	HashSet<U32> set;

	enum { maxI = 1024 * 1024 };

	for(Uptr i = 0;i < maxI;++i)
	{
		errorUnless(!set.contains(U32(i)));
	}

	errorUnless(set.size() == 0);
	for(Uptr i = 0;i < maxI;++i)
	{
		errorUnless(!set.contains(U32(i)));
		errorUnless(!set.get(U32(i)));
		errorUnless(set.add(U32(i)));
		errorUnless(set.contains(U32(i)));
		errorUnless(set.get(U32(i)));
		errorUnless(set.size() == i + 1);
	}

	for(Uptr i = 0;i < maxI;++i)
	{
		errorUnless(set.contains(U32(i)));
		errorUnless(set.remove(U32(i)));
		errorUnless(!set.contains(U32(i)));
		errorUnless(set.size() == maxI - i - 1);
	}

	for(Uptr i = 0;i < maxI;++i)
	{
		errorUnless(!set.contains(U32(i)));
	}
}
Exemple #14
0
static void testStringMap()
{
	enum { numStrings = 1000 };

	HashMap<std::string, U32> map;
	std::vector<HashMapPair<std::string, U32>> pairs;

	srand(0);

	for(Uptr i = 0;i < numStrings;++i)
	{
		while(true)
		{
			std::string randomString = generateRandomString();

			bool alreadySawString = false;
			for(const HashMapPair<std::string, U32>& pair : pairs)
			{
				if(pair.key == randomString)
				{
					alreadySawString = true;
					break;
				}
			}

			if(!alreadySawString)
			{
				pairs.emplace_back(std::move(randomString), rand());
				break;
			}
		};
	}

	for(Uptr i = 0;i < pairs.size();++i)
	{
		errorUnless(map.add(pairs[i].key, pairs[i].value));
		errorUnless(!map.add(pairs[i].key, pairs[i].value));

		for(Uptr j = 0;j < pairs.size();++j)
		{
			const U32* valuePtr = map.get(pairs[j].key);
			if(j <= i)
			{
				errorUnless(valuePtr && *valuePtr == pairs[j].value);
			}
			else
			{
				errorUnless(!valuePtr);
			}
		}
	}

	for(Uptr i = 0;i < pairs.size();++i)
	{
		errorUnless(map.remove(pairs[i].key));
		errorUnless(!map.remove(pairs[i].key));

		for(Uptr j = 0;j < pairs.size();++j)
		{
			const U32* valuePtr = map.get(pairs[j].key);
			if(j > i)
			{
				errorUnless(valuePtr && *valuePtr == pairs[j].value);
			}
			else
			{
				errorUnless(!valuePtr);
			}
		}
	}
}
Exemple #15
0
static void testSetInitializerList()
{
	HashSet<Uptr> set {1,3,5,7,11,13,17};
	errorUnless(!set.contains(0));
	errorUnless( set.contains(1));
	errorUnless(!set.contains(2));
	errorUnless( set.contains(3));
	errorUnless(!set.contains(4));
	errorUnless( set.contains(5));
	errorUnless(!set.contains(6));
	errorUnless( set.contains(7));
	errorUnless(!set.contains(8));
	errorUnless(!set.contains(9));
	errorUnless(!set.contains(10));
	errorUnless( set.contains(11));
	errorUnless(!set.contains(12));
	errorUnless( set.contains(13));
	errorUnless(!set.contains(14));
	errorUnless(!set.contains(15));
	errorUnless(!set.contains(16));
	errorUnless( set.contains(17));
}
Exemple #16
0
static void testMapInitializerList()
{
	HashMap<Uptr, Uptr> map {{1,1},{3,2},{5,3},{7,4},{11,5},{13,6},{17,7}};
	errorUnless(!map.get(0));
	errorUnless(*map.get(1) == 1);
	errorUnless(!map.get(2));
	errorUnless(*map.get(3) == 2);
	errorUnless(!map.get(4));
	errorUnless(*map.get(5) == 3);
	errorUnless(!map.get(6));
	errorUnless(*map.get(7) == 4);
	errorUnless(!map.get(8));
	errorUnless(!map.get(9));
	errorUnless(!map.get(10));
	errorUnless(*map.get(11) == 5);
	errorUnless(!map.get(12));
	errorUnless(*map.get(13) == 6);
	errorUnless(!map.get(14));
	errorUnless(!map.get(15));
	errorUnless(!map.get(16));
	errorUnless(*map.get(17) == 7);
}
Exemple #17
0
static void testSetCopy()
{
	// Add 1000..1999 to a HashSet.
	HashSet<Uptr> a;
	for(Uptr i = 0;i < 1000;++i)
	{
		a.add(i + 1000);
	}

	// Copy the set to a new HashSet.
	HashSet<Uptr> b {a};

	// Test that both the new and old HashSet contain the expected numbers.
	for(Uptr i = 0;i < 1000;++i)
	{
		errorUnless(!a.contains(i));
		errorUnless(a.contains(i + 1000));
		errorUnless(!a.contains(i + 2000));
		
		errorUnless(!b.contains(i));
		errorUnless(b.contains(i + 1000));
		errorUnless(!b.contains(i + 2000));
	}
	
	// Test copying a set from itself.
	b = b;
	
	// Test that the set wasn't changed by the copy-to-self.
	for(Uptr i = 0;i < 1000;++i)
	{
		errorUnless(!b.contains(i));
		errorUnless(b.contains(i + 1000));
		errorUnless(!b.contains(i + 2000));
	}

	// Test removing an element from the set.
	b.remove(1000);
	errorUnless(a.contains(1000));
	errorUnless(!b.contains(1000));
}
Exemple #18
0
	static Uptr getLineOffset(const LineInfo* lineInfo,Uptr lineIndex)
	{
		errorUnless(lineIndex < lineInfo->numLineStarts);
		return lineInfo->lineStarts[lineIndex];
	}
Exemple #19
0
static void testMapCopy()
{
	// Add 1000..1999 to a HashMap.
	HashMap<Uptr, Uptr> a;
	for(Uptr i = 0;i < 1000;++i)
	{
		a.add(i + 1000,i);
	}

	// Copy the map to a new HashMap.
	HashMap<Uptr, Uptr> b {a};

	// Test that both the new and old HashMap contain the expected numbers.
	for(Uptr i = 0;i < 1000;++i)
	{
		errorUnless(!a.get(i));
		errorUnless(*a.get(i + 1000) == i);
		errorUnless(!a.get(i + 2000));
		
		errorUnless(!b.get(i));
		errorUnless(*b.get(i + 1000) == i);
		errorUnless(!b.get(i + 2000));
	}
	
	// Test copying a map from itself.
	b = b;
	
	// Test that the map wasn't changed by the copy-to-self.
	for(Uptr i = 0;i < 1000;++i)
	{
		errorUnless(!b.get(i));
		errorUnless(*b.get(i + 1000) == i);
		errorUnless(!b.get(i + 2000));
	}

	// Test removing an element from the map.
	b.remove(1000);
	errorUnless(*a.get(1000) == 0);
	errorUnless(!b.get(1000));
}
Exemple #20
0
	ModuleInstance* instantiateModule(const IR::Module& module,ImportBindings&& imports)
	{
		ModuleInstance* moduleInstance = new ModuleInstance(
			std::move(imports.functions),
			std::move(imports.tables),
			std::move(imports.memories),
			std::move(imports.globals)
			);
		
		// Get disassembly names for the module's objects.
		DisassemblyNames disassemblyNames;
		IR::getDisassemblyNames(module,disassemblyNames);

		// Check the type of the ModuleInstance's imports.
		errorUnless(moduleInstance->functions.size() == module.functions.imports.size());
		for(Uptr importIndex = 0;importIndex < module.functions.imports.size();++importIndex)
		{
			errorUnless(isA(moduleInstance->functions[importIndex],module.types[module.functions.imports[importIndex].type.index]));
		}
		errorUnless(moduleInstance->tables.size() == module.tables.imports.size());
		for(Uptr importIndex = 0;importIndex < module.tables.imports.size();++importIndex)
		{
			errorUnless(isA(moduleInstance->tables[importIndex],module.tables.imports[importIndex].type));
		}
		errorUnless(moduleInstance->memories.size() == module.memories.imports.size());
		for(Uptr importIndex = 0;importIndex < module.memories.imports.size();++importIndex)
		{
			errorUnless(isA(moduleInstance->memories[importIndex],module.memories.imports[importIndex].type));
		}
		errorUnless(moduleInstance->globals.size() == module.globals.imports.size());
		for(Uptr importIndex = 0;importIndex < module.globals.imports.size();++importIndex)
		{
			errorUnless(isA(moduleInstance->globals[importIndex],module.globals.imports[importIndex].type));
		}

		// Instantiate the module's memory and table definitions.
		for(const TableDef& tableDef : module.tables.defs)
		{
			auto table = createTable(tableDef.type);
			if(!table) { causeException(Exception::Cause::outOfMemory); }
			moduleInstance->tables.push_back(table);
		}
		for(const MemoryDef& memoryDef : module.memories.defs)
		{
			if(!MemoryInstance::theMemoryInstance) {
				MemoryInstance::theMemoryInstance = createMemory(memoryDef.type);
				if(!MemoryInstance::theMemoryInstance) { causeException(Exception::Cause::outOfMemory); }
			}
			moduleInstance->memories.push_back(MemoryInstance::theMemoryInstance);
		}

		// Find the default memory and table for the module.
		if(moduleInstance->memories.size() != 0)
		{
			assert(moduleInstance->memories.size() == 1);
			moduleInstance->defaultMemory = moduleInstance->memories[0];
		}
		if(moduleInstance->tables.size() != 0)
		{
			assert(moduleInstance->tables.size() == 1);
			moduleInstance->defaultTable = moduleInstance->tables[0];
		}

		// If any memory or table segment doesn't fit, throw an exception before mutating any memory/table.
		for(auto& tableSegment : module.tableSegments)
		{
			TableInstance* table = moduleInstance->tables[tableSegment.tableIndex];
			const Value baseOffsetValue = evaluateInitializer(moduleInstance,tableSegment.baseOffset);
			errorUnless(baseOffsetValue.type == ValueType::i32);
			const U32 baseOffset = baseOffsetValue.i32;
			if(baseOffset > table->elements.size()
			|| table->elements.size() - baseOffset < tableSegment.indices.size())
			{ causeException(Exception::Cause::invalidSegmentOffset); }
		}

		//Previously, the module instantiation would write in to the memoryInstance here. Don't do that
      //since the memoryInstance is shared across all moduleInstances and we could be compiling
      //a new instance while another instance is running
		
		// Instantiate the module's global definitions.
		for(const GlobalDef& globalDef : module.globals.defs)
		{
			const Value initialValue = evaluateInitializer(moduleInstance,globalDef.initializer);
			errorUnless(initialValue.type == globalDef.type.valueType);
			moduleInstance->globals.push_back(new GlobalInstance(globalDef.type,initialValue));
		}
		
		// Create the FunctionInstance objects for the module's function definitions.
		for(Uptr functionDefIndex = 0;functionDefIndex < module.functions.defs.size();++functionDefIndex)
		{
			const Uptr functionIndex = moduleInstance->functions.size();
			const DisassemblyNames::Function& functionNames = disassemblyNames.functions[functionIndex];
			std::string debugName = functionNames.name;
			if(!debugName.size()) { debugName = "<function #" + std::to_string(functionDefIndex) + ">"; }
			auto functionInstance = new FunctionInstance(moduleInstance,module.types[module.functions.defs[functionDefIndex].type.index],nullptr,debugName.c_str());
			moduleInstance->functionDefs.push_back(functionInstance);
			moduleInstance->functions.push_back(functionInstance);
		}

		// Generate machine code for the module.
		LLVMJIT::instantiateModule(module,moduleInstance);

		// Set up the instance's exports.
		for(const Export& exportIt : module.exports)
		{
			ObjectInstance* exportedObject = nullptr;
			switch(exportIt.kind)
			{
			case ObjectKind::function: exportedObject = moduleInstance->functions[exportIt.index]; break;
			case ObjectKind::table: exportedObject = moduleInstance->tables[exportIt.index]; break;
			case ObjectKind::memory: exportedObject = moduleInstance->memories[exportIt.index]; break;
			case ObjectKind::global: exportedObject = moduleInstance->globals[exportIt.index]; break;
			default: Errors::unreachable();
			}
			moduleInstance->exportMap[exportIt.name] = exportedObject;
		}
		
		// Copy the module's table segments into the module's default table.
		for(const TableSegment& tableSegment : module.tableSegments)
		{
			TableInstance* table = moduleInstance->tables[tableSegment.tableIndex];
			
			const Value baseOffsetValue = evaluateInitializer(moduleInstance,tableSegment.baseOffset);
			errorUnless(baseOffsetValue.type == ValueType::i32);
			const U32 baseOffset = baseOffsetValue.i32;
			assert(baseOffset + tableSegment.indices.size() <= table->elements.size());

			for(Uptr index = 0;index < tableSegment.indices.size();++index)
			{
				const Uptr functionIndex = tableSegment.indices[index];
				assert(functionIndex < moduleInstance->functions.size());
				setTableElement(table,baseOffset + index,moduleInstance->functions[functionIndex]);
			}
		}

		// Call the module's start function.
		if(module.startFunctionIndex != UINTPTR_MAX)
		{
			assert(moduleInstance->functions[module.startFunctionIndex]->type == IR::FunctionType::get());
			moduleInstance->startFunctionIndex = module.startFunctionIndex;
		}

		moduleInstances.push_back(moduleInstance);
		return moduleInstance;
	}
Exemple #21
0
static void testU32Map()
{
	HashMap<U32, U32> map;

	enum { maxI = 1024 * 1024 };

	for(Uptr i = 0;i < maxI;++i)
	{
		errorUnless(!map.contains(U32(i)));
	}

	errorUnless(map.size() == 0);
	for(Uptr i = 0;i < maxI;++i)
	{
		errorUnless(!map.contains(U32(i)));
		errorUnless(!map.get(U32(i)));
		errorUnless(map.add(U32(i),U32(i * 2)));
		errorUnless(map.contains(U32(i)));
		errorUnless(map.get(U32(i)));
		errorUnless(*map.get(U32(i)) == U32(i * 2));
		errorUnless(map.size() == i + 1);
	}

	for(Uptr i = 0;i < maxI;++i)
	{
		errorUnless(map.contains(U32(i)));
		errorUnless(map.remove(U32(i)));
		errorUnless(!map.contains(U32(i)));
		errorUnless(map.size() == maxI - i - 1);
	}

	for(Uptr i = 0;i < maxI;++i)
	{
		errorUnless(!map.contains(U32(i)));
	}
}