From 824c0788468bf19ab4d1a3297804210b8fe17ab0 Mon Sep 17 00:00:00 2001 From: Elliot Glaysher Date: Sun, 26 Apr 2015 14:19:42 -0700 Subject: [PATCH] Use extern templates in RLOperation. Theoretically, C++11 standardized this feature and it should speed up compilation time. --- SConscript | 9 ++- src/machine/general_operations.cc | 12 +++ src/machine/general_operations.h | 12 +++ src/machine/rloperation.cc | 36 +++++++-- src/machine/rloperation.h | 101 +++++++++++++++++++++----- src/machine/rloperation/argc_t.cc | 31 ++++++++ src/machine/rloperation/argc_t.h | 6 ++ src/machine/rloperation/complex_t.cc | 34 +++++++++ src/machine/rloperation/complex_t.h | 46 +++++++++--- src/machine/rloperation/rlop_store.cc | 42 +++++++++++ src/machine/rloperation/rlop_store.h | 48 ++++++++---- 11 files changed, 321 insertions(+), 56 deletions(-) create mode 100644 src/machine/rloperation/argc_t.cc create mode 100644 src/machine/rloperation/complex_t.cc create mode 100644 src/machine/rloperation/rlop_store.cc diff --git a/SConscript b/SConscript index f26ee549c..c56c02dcb 100644 --- a/SConscript +++ b/SConscript @@ -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", diff --git a/src/machine/general_operations.cc b/src/machine/general_operations.cc index 4e1e2183c..f07484fe1 100644 --- a/src/machine/general_operations.cc +++ b/src/machine/general_operations.cc @@ -169,3 +169,15 @@ void UndefinedFunction::operator()(RLMachine& machine, const libreallive::CommandElement& f) { throw rlvm::UnimplementedOpcode(machine, name(), f); } + +// Template instantiations. +template RLOperation* CallFunction(void (EventSystem::*)(int)); +template RLOperation* CallFunction(void (GraphicsSystem::*)(int)); +template RLOperation* CallFunction(void (SoundSystem::*)(int)); +template RLOperation* CallFunction(void (System::*)(int)); +template RLOperation* CallFunction(void (TextSystem::*)(int)); +template RLOperation* ReturnIntValue(int (EventSystem::*)() const); +template RLOperation* ReturnIntValue(int (GraphicsSystem::*)() const); +template RLOperation* ReturnIntValue(int (RLMachine::*)() const); +template RLOperation* ReturnIntValue(int (SoundSystem::*)() const); +template RLOperation* ReturnIntValue(int (TextSystem::*)() const); diff --git a/src/machine/general_operations.h b/src/machine/general_operations.h index 2966cb739..4c615ae0a 100644 --- a/src/machine/general_operations.h +++ b/src/machine/general_operations.h @@ -207,4 +207,16 @@ class UndefinedFunction : public RLOp_SpecialCase { int overload_; }; +// extern template declarations; manually instantiated in the cc file. +extern template RLOperation* CallFunction(void (EventSystem::*)(int)); +extern template RLOperation* CallFunction(void (GraphicsSystem::*)(int)); +extern template RLOperation* CallFunction(void (SoundSystem::*)(int)); +extern template RLOperation* CallFunction(void (System::*)(int)); +extern template RLOperation* CallFunction(void (TextSystem::*)(int)); +extern template RLOperation* ReturnIntValue(int (EventSystem::*)() const); +extern template RLOperation* ReturnIntValue(int (GraphicsSystem::*)() const); +extern template RLOperation* ReturnIntValue(int (RLMachine::*)() const); +extern template RLOperation* ReturnIntValue(int (SoundSystem::*)() const); +extern template RLOperation* ReturnIntValue(int (TextSystem::*)() const); + #endif // SRC_MACHINE_GENERAL_OPERATIONS_H_ diff --git a/src/machine/rloperation.cc b/src/machine/rloperation.cc index 74afa7a96..e823ac336 100644 --- a/src/machine/rloperation.cc +++ b/src/machine/rloperation.cc @@ -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" @@ -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; +template class RLNormalOpcode; +template class RLNormalOpcode; +template class RLNormalOpcode; +template class RLNormalOpcode; +template class RLNormalOpcode; +template class RLNormalOpcode; +template class RLNormalOpcode; +template class RLNormalOpcode; +template class RLNormalOpcode; +template class RLNormalOpcode; + +template class RLOpcode<>; +template class RLOpcode; +template class RLOpcode; +template class RLOpcode; +template class RLOpcode; +template class RLOpcode; +template class RLOpcode; +template class RLOpcode; +template class RLOpcode; +template class RLOpcode; +template class RLOpcode; +template class RLOpcode; diff --git a/src/machine/rloperation.h b/src/machine/rloperation.h index 87e54a7fd..47ebf56c4 100644 --- a/src/machine/rloperation.h +++ b/src/machine/rloperation.h @@ -35,6 +35,7 @@ #include "libreallive/bytecode_fwd.h" #include "libreallive/expression.h" +#include "machine/rloperation/references.h" class MappedRLModule; class RLModule; @@ -304,15 +305,29 @@ struct make_indexes : make_indexes_impl<0, index_tuple<>, Types...> template class RLNormalOpcode : public RLOperation { public: + RLNormalOpcode(); + virtual ~RLNormalOpcode(); + virtual void ParseParameters( const std::vector& input, - libreallive::ExpressionPiecesVector& output) final { - unsigned int position = 0; - internal::ParseEachParameter( - position, input, output); - } + libreallive::ExpressionPiecesVector& output) final; }; +template +RLNormalOpcode::RLNormalOpcode() {} + +template +RLNormalOpcode::~RLNormalOpcode() {} + +template +void RLNormalOpcode::ParseParameters( + const std::vector& input, + libreallive::ExpressionPiecesVector& output) { + unsigned int position = 0; + internal::ParseEachParameter( + position, input, output); +} + // Specialization for empty template list template <> void RLNormalOpcode<>::ParseParameters( @@ -322,22 +337,12 @@ void RLNormalOpcode<>::ParseParameters( template class RLOpcode : public RLNormalOpcode { 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 tuple = - std::tuple{ - Args::getData(machine, parameters, position)... - }; - DispatchImpl(machine, tuple, - typename internal::make_indexes::type()); - } + const libreallive::ExpressionPiecesVector& parameters) final; virtual void operator()(RLMachine&, typename Args::type...) = 0; @@ -350,9 +355,67 @@ class RLOpcode : public RLNormalOpcode { } }; +template +RLOpcode::RLOpcode() {} + +template +RLOpcode::~RLOpcode() {} + +template +void RLOpcode::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 tuple = + std::tuple{ + Args::getData(machine, parameters, position)... + }; + DispatchImpl(machine, tuple, + typename internal::make_indexes::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; +extern template class RLNormalOpcode; +extern template class RLNormalOpcode; +extern template class RLNormalOpcode; +extern template class RLNormalOpcode; +extern template class RLNormalOpcode; +extern template class RLNormalOpcode; +extern template class RLNormalOpcode; +extern template class RLNormalOpcode; +extern template class RLNormalOpcode; +extern template class RLNormalOpcode; + +extern template class RLOpcode<>; +extern template class RLOpcode; +extern template class RLOpcode; +extern template class RLOpcode; +extern template class RLOpcode; +extern template class RLOpcode; +extern template class RLOpcode; +extern template class RLOpcode; +extern template class RLOpcode; +extern template class RLOpcode; +extern template class RLOpcode; +extern template class RLOpcode; + #endif // SRC_MACHINE_RLOPERATION_H_ diff --git a/src/machine/rloperation/argc_t.cc b/src/machine/rloperation/argc_t.cc new file mode 100644 index 000000000..25305fede --- /dev/null +++ b/src/machine/rloperation/argc_t.cc @@ -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; +template struct Argc_T; diff --git a/src/machine/rloperation/argc_t.h b/src/machine/rloperation/argc_t.h index 954bbc954..6096f3da4 100644 --- a/src/machine/rloperation/argc_t.h +++ b/src/machine/rloperation/argc_t.h @@ -26,6 +26,9 @@ #include #include +#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 @@ -73,4 +76,7 @@ void Argc_T::ParseParameters(unsigned int& position, } } +extern template struct Argc_T; +extern template struct Argc_T; + #endif // SRC_MACHINE_RLOPERATION_ARGC_T_H_ diff --git a/src/machine/rloperation/complex_t.cc b/src/machine/rloperation/complex_t.cc new file mode 100644 index 000000000..df774da0b --- /dev/null +++ b/src/machine/rloperation/complex_t.cc @@ -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; +template struct Complex_T; +template struct Complex_T; +template struct Complex_T; +template struct Complex_T; diff --git a/src/machine/rloperation/complex_t.h b/src/machine/rloperation/complex_t.h index 7e0a1323d..af468ed29 100644 --- a/src/machine/rloperation/complex_t.h +++ b/src/machine/rloperation/complex_t.h @@ -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. // @@ -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& 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 Complex_T::type +Complex_T::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 +void Complex_T::ParseParameters( + unsigned int& position, + const std::vector& 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; +extern template struct Complex_T; +extern template struct Complex_T; +extern template struct Complex_T; +extern template struct Complex_T; + #endif // SRC_MACHINE_RLOPERATION_COMPLEX_T_H_ diff --git a/src/machine/rloperation/rlop_store.cc b/src/machine/rloperation/rlop_store.cc new file mode 100644 index 000000000..1644c4265 --- /dev/null +++ b/src/machine/rloperation/rlop_store.cc @@ -0,0 +1,42 @@ +// -*- 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/rlop_store.h" + +template <> +void RLStoreOpcode<>::Dispatch( + RLMachine& machine, + const libreallive::ExpressionPiecesVector& parameters) { + int store = operator()(machine); + machine.set_store_register(store); +} + +template class RLStoreOpcode<>; +template class RLStoreOpcode; +template class RLStoreOpcode; +template class RLStoreOpcode; +template class RLStoreOpcode; diff --git a/src/machine/rloperation/rlop_store.h b/src/machine/rloperation/rlop_store.h index 14cf3561a..c34e2d70f 100644 --- a/src/machine/rloperation/rlop_store.h +++ b/src/machine/rloperation/rlop_store.h @@ -29,22 +29,12 @@ template class RLStoreOpcode : public RLNormalOpcode { public: + RLStoreOpcode(); + virtual ~RLStoreOpcode(); + 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 tuple = - std::tuple{ - Args::getData(machine, parameters, position)... - }; - DispatchImpl(machine, tuple, - typename internal::make_indexes::type()); - } + const libreallive::ExpressionPiecesVector& parameters); virtual int operator()(RLMachine&, typename Args::type...) = 0; @@ -58,9 +48,39 @@ class RLStoreOpcode : public RLNormalOpcode { } }; +template +RLStoreOpcode::RLStoreOpcode() {} + +template +RLStoreOpcode::~RLStoreOpcode() {} + +template +void RLStoreOpcode::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 tuple = + std::tuple{ + Args::getData(machine, parameters, position)... + }; + DispatchImpl(machine, tuple, + typename internal::make_indexes::type()); +} + template <> void RLStoreOpcode<>::Dispatch( RLMachine& machine, const libreallive::ExpressionPiecesVector& parameters); +extern template class RLStoreOpcode<>; +extern template class RLStoreOpcode; +extern template class RLStoreOpcode; +extern template class RLStoreOpcode; +extern template class RLStoreOpcode; + #endif // SRC_MACHINE_RLOPERATION_RLOP_STORE_H_