Skip to content

Commit

Permalink
Use extern templates in RLOperation.
Browse files Browse the repository at this point in the history
Theoretically, C++11 standardized this feature and it should speed
up compilation time.
  • Loading branch information
eglaysher committed May 3, 2015
1 parent aba9c0d commit 824c078
Show file tree
Hide file tree
Showing 11 changed files with 321 additions and 56 deletions.
9 changes: 6 additions & 3 deletions SConscript
Original file line number Diff line number Diff line change
Expand Up @@ -102,17 +102,20 @@ librlvm_files = [
"src/machine/memory.cc",
"src/machine/memory_intmem.cc",
"src/machine/opcode_log.cc",
"src/machine/reallive_dll.cc",
"src/machine/reference.cc",
"src/machine/rlmachine.cc",
"src/machine/rlmodule.cc",
"src/machine/rloperation.cc",
"src/machine/reallive_dll.cc",
"src/machine/rloperation/argc_t.cc",
"src/machine/rloperation/complex_t.cc",
"src/machine/rloperation/rlop_store.cc",
"src/machine/save_game_header.cc",
"src/machine/serialization_global.cc",
"src/machine/serialization_local.cc",
"src/machine/stack_frame.cc",
"src/machine/reference.cc",
"src/modules/object_mutator_operations.cc",
"src/modules/module_bgm.cc",
"src/modules/object_mutator_operations.cc",
"src/modules/module_bgr.cc",
"src/modules/module_dll.cc",
"src/modules/module_debug.cc",
Expand Down
12 changes: 12 additions & 0 deletions src/machine/general_operations.cc
Original file line number Diff line number Diff line change
Expand Up @@ -169,3 +169,15 @@ void UndefinedFunction::operator()(RLMachine& machine,
const libreallive::CommandElement& f) {
throw rlvm::UnimplementedOpcode(machine, name(), f);
}

// Template instantiations.
template RLOperation* CallFunction<EventSystem>(void (EventSystem::*)(int));
template RLOperation* CallFunction<GraphicsSystem>(void (GraphicsSystem::*)(int));
template RLOperation* CallFunction<SoundSystem>(void (SoundSystem::*)(int));
template RLOperation* CallFunction<System>(void (System::*)(int));
template RLOperation* CallFunction<TextSystem>(void (TextSystem::*)(int));
template RLOperation* ReturnIntValue<EventSystem, int>(int (EventSystem::*)() const);
template RLOperation* ReturnIntValue<GraphicsSystem, int>(int (GraphicsSystem::*)() const);
template RLOperation* ReturnIntValue<RLMachine, int>(int (RLMachine::*)() const);
template RLOperation* ReturnIntValue<SoundSystem, int>(int (SoundSystem::*)() const);
template RLOperation* ReturnIntValue<TextSystem, int>(int (TextSystem::*)() const);
12 changes: 12 additions & 0 deletions src/machine/general_operations.h
Original file line number Diff line number Diff line change
Expand Up @@ -207,4 +207,16 @@ class UndefinedFunction : public RLOp_SpecialCase {
int overload_;
};

// extern template declarations; manually instantiated in the cc file.
extern template RLOperation* CallFunction<EventSystem>(void (EventSystem::*)(int));
extern template RLOperation* CallFunction<GraphicsSystem>(void (GraphicsSystem::*)(int));
extern template RLOperation* CallFunction<SoundSystem>(void (SoundSystem::*)(int));
extern template RLOperation* CallFunction<System>(void (System::*)(int));
extern template RLOperation* CallFunction<TextSystem>(void (TextSystem::*)(int));
extern template RLOperation* ReturnIntValue<EventSystem, int>(int (EventSystem::*)() const);
extern template RLOperation* ReturnIntValue<GraphicsSystem, int>(int (GraphicsSystem::*)() const);
extern template RLOperation* ReturnIntValue<RLMachine, int>(int (RLMachine::*)() const);
extern template RLOperation* ReturnIntValue<SoundSystem, int>(int (SoundSystem::*)() const);
extern template RLOperation* ReturnIntValue<TextSystem, int>(int (TextSystem::*)() const);

#endif // SRC_MACHINE_GENERAL_OPERATIONS_H_
36 changes: 28 additions & 8 deletions src/machine/rloperation.cc
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@

#include "libreallive/bytecode.h"
#include "machine/rloperation/references.h"
#include "machine/rloperation/rlop_store.h"
#include "machine/rlmachine.h"
#include "machine/rlmodule.h"
#include "utilities/exception.h"
Expand Down Expand Up @@ -291,10 +290,31 @@ void RLOpcode<>::Dispatch(
operator()(machine);
}

template <>
void RLStoreOpcode<>::Dispatch(
RLMachine& machine,
const libreallive::ExpressionPiecesVector& parameters) {
int store = operator()(machine);
machine.set_store_register(store);
}
// Default instantiations.
template class RLNormalOpcode<>;
template class RLNormalOpcode<IntConstant_T>;
template class RLNormalOpcode<IntConstant_T, IntConstant_T>;
template class RLNormalOpcode<IntConstant_T, StrConstant_T>;
template class RLNormalOpcode<IntConstant_T, IntConstant_T, IntConstant_T>;
template class RLNormalOpcode<IntConstant_T, IntConstant_T, IntConstant_T,
IntConstant_T>;
template class RLNormalOpcode<IntReference_T>;
template class RLNormalOpcode<IntReference_T, IntReference_T>;
template class RLNormalOpcode<StrConstant_T>;
template class RLNormalOpcode<StrConstant_T, IntConstant_T>;
template class RLNormalOpcode<StrConstant_T, StrConstant_T>;
template class RLNormalOpcode<StrReference_T>;

template class RLOpcode<>;
template class RLOpcode<IntConstant_T>;
template class RLOpcode<IntConstant_T, IntConstant_T>;
template class RLOpcode<IntConstant_T, StrConstant_T>;
template class RLOpcode<IntConstant_T, IntConstant_T, IntConstant_T>;
template class RLOpcode<IntConstant_T, IntConstant_T, IntConstant_T,
IntConstant_T>;
template class RLOpcode<IntReference_T>;
template class RLOpcode<IntReference_T, IntReference_T>;
template class RLOpcode<StrConstant_T>;
template class RLOpcode<StrConstant_T, IntConstant_T>;
template class RLOpcode<StrConstant_T, StrConstant_T>;
template class RLOpcode<StrReference_T>;
101 changes: 82 additions & 19 deletions src/machine/rloperation.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@

#include "libreallive/bytecode_fwd.h"
#include "libreallive/expression.h"
#include "machine/rloperation/references.h"

class MappedRLModule;
class RLModule;
Expand Down Expand Up @@ -304,15 +305,29 @@ struct make_indexes : make_indexes_impl<0, index_tuple<>, Types...>
template <typename... Args>
class RLNormalOpcode : public RLOperation {
public:
RLNormalOpcode();
virtual ~RLNormalOpcode();

virtual void ParseParameters(
const std::vector<std::string>& input,
libreallive::ExpressionPiecesVector& output) final {
unsigned int position = 0;
internal::ParseEachParameter<Args..., internal::_sentinel_type>(
position, input, output);
}
libreallive::ExpressionPiecesVector& output) final;
};

template <typename... Args>
RLNormalOpcode<Args...>::RLNormalOpcode() {}

template <typename... Args>
RLNormalOpcode<Args...>::~RLNormalOpcode() {}

template <typename... Args>
void RLNormalOpcode<Args...>::ParseParameters(
const std::vector<std::string>& input,
libreallive::ExpressionPiecesVector& output) {
unsigned int position = 0;
internal::ParseEachParameter<Args..., internal::_sentinel_type>(
position, input, output);
}

// Specialization for empty template list
template <>
void RLNormalOpcode<>::ParseParameters(
Expand All @@ -322,22 +337,12 @@ void RLNormalOpcode<>::ParseParameters(
template <typename... Args>
class RLOpcode : public RLNormalOpcode<Args...> {
public:
RLOpcode();
virtual ~RLOpcode() override;

virtual void Dispatch(
RLMachine& machine,
const libreallive::ExpressionPiecesVector& parameters) final {
// The following does not work in gcc 4.8.2, but it's supposed to!
// Parameter unpacking inside an initializer-clause is supposed to always
// be evaluated in the order it appears.
//
// http://stackoverflow.com/questions/12048221/c11-variadic-template-function-parameter-pack-expansion-execution-order
unsigned int position = 0;
std::tuple<typename Args::type...> tuple =
std::tuple<typename Args::type...>{
Args::getData(machine, parameters, position)...
};
DispatchImpl(machine, tuple,
typename internal::make_indexes<Args...>::type());
}
const libreallive::ExpressionPiecesVector& parameters) final;

virtual void operator()(RLMachine&, typename Args::type...) = 0;

Expand All @@ -350,9 +355,67 @@ class RLOpcode : public RLNormalOpcode<Args...> {
}
};

template <typename... Args>
RLOpcode<Args...>::RLOpcode() {}

template <typename... Args>
RLOpcode<Args...>::~RLOpcode() {}

template <typename... Args>
void RLOpcode<Args...>::Dispatch(
RLMachine& machine,
const libreallive::ExpressionPiecesVector& parameters) {
// The following does not work in gcc 4.8.2, but it's supposed to!
// Parameter unpacking inside an initializer-clause is supposed to always
// be evaluated in the order it appears.
//
// http://stackoverflow.com/questions/12048221/c11-variadic-template-function-parameter-pack-expansion-execution-order
unsigned int position = 0;
std::tuple<typename Args::type...> tuple =
std::tuple<typename Args::type...>{
Args::getData(machine, parameters, position)...
};
DispatchImpl(machine, tuple,
typename internal::make_indexes<Args...>::type());
}

template <>
void RLOpcode<>::Dispatch(
RLMachine& machine,
const libreallive::ExpressionPiecesVector& parameters);

// Extern template declarations.
//
// These tell the compiler to not expand these templates; they are explicitly
// instantiated in the cc file as these are the most common variants. Note that
// we must explicitly instantiate both RLNormalOpcode and RLOpcode separately.
extern template class RLNormalOpcode<>;
extern template class RLNormalOpcode<IntConstant_T>;
extern template class RLNormalOpcode<IntConstant_T, IntConstant_T>;
extern template class RLNormalOpcode<IntConstant_T, StrConstant_T>;
extern template class RLNormalOpcode<IntConstant_T, IntConstant_T,
IntConstant_T>;
extern template class RLNormalOpcode<IntConstant_T, IntConstant_T,
IntConstant_T, IntConstant_T>;
extern template class RLNormalOpcode<IntReference_T>;
extern template class RLNormalOpcode<IntReference_T, IntReference_T>;
extern template class RLNormalOpcode<StrConstant_T>;
extern template class RLNormalOpcode<StrConstant_T, IntConstant_T>;
extern template class RLNormalOpcode<StrConstant_T, StrConstant_T>;
extern template class RLNormalOpcode<StrReference_T>;

extern template class RLOpcode<>;
extern template class RLOpcode<IntConstant_T>;
extern template class RLOpcode<IntConstant_T, IntConstant_T>;
extern template class RLOpcode<IntConstant_T, StrConstant_T>;
extern template class RLOpcode<IntConstant_T, IntConstant_T, IntConstant_T>;
extern template class RLOpcode<IntConstant_T, IntConstant_T, IntConstant_T,
IntConstant_T>;
extern template class RLOpcode<IntReference_T>;
extern template class RLOpcode<IntReference_T, IntReference_T>;
extern template class RLOpcode<StrConstant_T>;
extern template class RLOpcode<StrConstant_T, IntConstant_T>;
extern template class RLOpcode<StrConstant_T, StrConstant_T>;
extern template class RLOpcode<StrReference_T>;

#endif // SRC_MACHINE_RLOPERATION_H_
31 changes: 31 additions & 0 deletions src/machine/rloperation/argc_t.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// -*- Mode: C++; tab-width:2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
// vi:tw=80:et:ts=2:sts=2
//
// -----------------------------------------------------------------------
//
// This file is part of RLVM, a RealLive virtual machine clone.
//
// -----------------------------------------------------------------------
//
// Copyright (C) 2015 Elliot Glaysher
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
//
// -----------------------------------------------------------------------

#include "machine/rloperation/argc_t.h"

template struct Argc_T<IntConstant_T>;
template struct Argc_T<IntReference_T>;
6 changes: 6 additions & 0 deletions src/machine/rloperation/argc_t.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@
#include <string>
#include <vector>

#include "machine/rloperation.h"
#include "machine/rloperation/references.h"

// Type struct that implements the argc concept.
//
// This type struct can only be used as the last element in a type
Expand Down Expand Up @@ -73,4 +76,7 @@ void Argc_T<CON>::ParseParameters(unsigned int& position,
}
}

extern template struct Argc_T<IntConstant_T>;
extern template struct Argc_T<IntReference_T>;

#endif // SRC_MACHINE_RLOPERATION_ARGC_T_H_
34 changes: 34 additions & 0 deletions src/machine/rloperation/complex_t.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// -*- Mode: C++; tab-width:2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
// vi:tw=80:et:ts=2:sts=2
//
// -----------------------------------------------------------------------
//
// This file is part of RLVM, a RealLive virtual machine clone.
//
// -----------------------------------------------------------------------
//
// Copyright (C) 2015 Elliot Glaysher
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
//
// -----------------------------------------------------------------------

#include "machine/rloperation/complex_t.h"

template struct Complex_T<IntConstant_T, IntConstant_T>;
template struct Complex_T<IntConstant_T, IntReference_T>;
template struct Complex_T<IntReference_T, IntReference_T>;
template struct Complex_T<StrConstant_T, IntConstant_T, IntConstant_T>;
template struct Complex_T<StrConstant_T, IntConstant_T>;
46 changes: 34 additions & 12 deletions src/machine/rloperation/complex_t.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@

#include "libreallive/bytecode_fwd.h"
#include "libreallive/expression.h"
#include "machine/rloperation.h"
#include "machine/rloperation/references.h"

// Type definition that implements the complex parameter concept.
//
Expand All @@ -42,23 +44,43 @@ struct Complex_T {
// Convert the incoming parameter objects into the resulting type.
static type getData(RLMachine& machine,
const libreallive::ExpressionPiecesVector& p,
unsigned int& position) {
unsigned int pos_in_expression = 0;
const libreallive::ExpressionPiecesVector& pieces =
p[position++].GetContainedPieces();
return type { Args::getData(machine, pieces, pos_in_expression)... };
}
unsigned int& position);

static void ParseParameters(unsigned int& position,
const std::vector<std::string>& input,
libreallive::ExpressionPiecesVector& output) {
const char* data = input.at(position).c_str();
libreallive::ExpressionPiece ep(libreallive::GetComplexParam(data));
output.push_back(std::move(ep));
position++;
}
libreallive::ExpressionPiecesVector& output);

enum { is_complex = true };
};

// static
template <typename... Args>
typename Complex_T<Args...>::type
Complex_T<Args...>::getData(RLMachine& machine,
const libreallive::ExpressionPiecesVector& p,
unsigned int& position) {
unsigned int pos_in_expression = 0;
const libreallive::ExpressionPiecesVector& pieces =
p[position++].GetContainedPieces();
return type { Args::getData(machine, pieces, pos_in_expression)... };
}

// static
template <typename... Args>
void Complex_T<Args...>::ParseParameters(
unsigned int& position,
const std::vector<std::string>& input,
libreallive::ExpressionPiecesVector& output) {
const char* data = input.at(position).c_str();
libreallive::ExpressionPiece ep(libreallive::GetComplexParam(data));
output.push_back(std::move(ep));
position++;
}

extern template struct Complex_T<IntConstant_T, IntConstant_T>;
extern template struct Complex_T<IntConstant_T, IntReference_T>;
extern template struct Complex_T<IntReference_T, IntReference_T>;
extern template struct Complex_T<StrConstant_T, IntConstant_T, IntConstant_T>;
extern template struct Complex_T<StrConstant_T, IntConstant_T>;

#endif // SRC_MACHINE_RLOPERATION_COMPLEX_T_H_
Loading

0 comments on commit 824c078

Please sign in to comment.