Skip to content

Commit 61ac61a

Browse files
committed
Merge pull request #1548 from mgreter/bugfix/memory-alignment
Fix and prepare memory manager for reference counting
2 parents 681b511 + 6492096 commit 61ac61a

13 files changed

+63
-67
lines changed

src/ast.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -585,7 +585,7 @@ namespace Sass {
585585
}
586586

587587
// create complex selector (ancestor of) from compound selector
588-
Complex_Selector* Compound_Selector::to_complex(Memory_Manager<AST_Node>& mem)
588+
Complex_Selector* Compound_Selector::to_complex(Memory_Manager& mem)
589589
{
590590
// create an intermediate complex selector
591591
return SASS_MEMORY_NEW(mem, Complex_Selector,

src/ast.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ namespace Sass {
6666
//////////////////////////////////////////////////////////
6767
// Abstract base class for all abstract syntax tree nodes.
6868
//////////////////////////////////////////////////////////
69-
class AST_Node {
69+
class AST_Node : public Memory_Object {
7070
ADD_PROPERTY(ParserState, pstate)
7171
public:
7272
AST_Node(ParserState pstate)
@@ -2040,7 +2040,7 @@ namespace Sass {
20402040
return length() == 1 && (*this)[0]->is_universal();
20412041
}
20422042

2043-
Complex_Selector* to_complex(Memory_Manager<AST_Node>& mem);
2043+
Complex_Selector* to_complex(Memory_Manager& mem);
20442044
Compound_Selector* unify_with(Compound_Selector* rhs, Context& ctx);
20452045
// virtual Selector_Placeholder* find_placeholder();
20462046
virtual bool has_parent_ref();

src/context.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ namespace Sass {
5151
Context::Context(Context::Data initializers)
5252
: // Output(this),
5353
head_imports(0),
54-
mem(Memory_Manager<AST_Node>()),
54+
mem(Memory_Manager()),
5555
c_options (initializers.c_options()),
5656
c_compiler (initializers.c_compiler()),
5757
source_c_str (initializers.source_c_str()),

src/context.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ namespace Sass {
2626
class Context {
2727
public:
2828
size_t head_imports;
29-
Memory_Manager<AST_Node> mem;
29+
Memory_Manager mem;
3030

3131
struct Sass_Options* c_options;
3232
struct Sass_Compiler* c_compiler;

src/environment.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ namespace Sass {
1717
ADD_PROPERTY(Environment*, parent)
1818

1919
public:
20-
Memory_Manager<AST_Node> mem;
20+
Memory_Manager mem;
2121
Environment();
2222
Environment(Environment* env);
2323
Environment(Environment& env);

src/eval.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1162,7 +1162,7 @@ namespace Sass {
11621162
return *l < *r;
11631163
}
11641164

1165-
Value* Eval::op_numbers(Memory_Manager<AST_Node>& mem, enum Sass_OP op, const Number& l, const Number& r, bool compressed, int precision)
1165+
Value* Eval::op_numbers(Memory_Manager& mem, enum Sass_OP op, const Number& l, const Number& r, bool compressed, int precision)
11661166
{
11671167
double lv = l.value();
11681168
double rv = r.value();
@@ -1213,7 +1213,7 @@ namespace Sass {
12131213
return v;
12141214
}
12151215

1216-
Value* Eval::op_number_color(Memory_Manager<AST_Node>& mem, enum Sass_OP op, const Number& l, const Color& rh, bool compressed, int precision)
1216+
Value* Eval::op_number_color(Memory_Manager& mem, enum Sass_OP op, const Number& l, const Color& rh, bool compressed, int precision)
12171217
{
12181218
Color r(rh);
12191219
r.disp("");
@@ -1247,7 +1247,7 @@ namespace Sass {
12471247
return SASS_MEMORY_NEW(mem, Color, rh);
12481248
}
12491249

1250-
Value* Eval::op_color_number(Memory_Manager<AST_Node>& mem, enum Sass_OP op, const Color& l, const Number& r, bool compressed, int precision)
1250+
Value* Eval::op_color_number(Memory_Manager& mem, enum Sass_OP op, const Color& l, const Number& r, bool compressed, int precision)
12511251
{
12521252
double rv = r.value();
12531253
if (op == Sass_OP::DIV && !rv) error("division by zero", r.pstate());
@@ -1259,7 +1259,7 @@ namespace Sass {
12591259
l.a());
12601260
}
12611261

1262-
Value* Eval::op_colors(Memory_Manager<AST_Node>& mem, enum Sass_OP op, const Color& l, const Color& r, bool compressed, int precision)
1262+
Value* Eval::op_colors(Memory_Manager& mem, enum Sass_OP op, const Color& l, const Color& r, bool compressed, int precision)
12631263
{
12641264
if (l.a() != r.a()) {
12651265
error("alpha channels must be equal when combining colors", r.pstate());
@@ -1275,7 +1275,7 @@ namespace Sass {
12751275
l.a());
12761276
}
12771277

1278-
Value* Eval::op_strings(Memory_Manager<AST_Node>& mem, enum Sass_OP op, Value& lhs, Value& rhs, bool compressed, int precision)
1278+
Value* Eval::op_strings(Memory_Manager& mem, enum Sass_OP op, Value& lhs, Value& rhs, bool compressed, int precision)
12791279
{
12801280
Expression::Concrete_Type ltype = lhs.concrete_type();
12811281
Expression::Concrete_Type rtype = rhs.concrete_type();
@@ -1340,7 +1340,7 @@ namespace Sass {
13401340
return SASS_MEMORY_NEW(mem, String_Constant, lhs.pstate(), (lstr) + sep + quote(rstr));
13411341
}
13421342

1343-
Expression* cval_to_astnode(Memory_Manager<AST_Node>& mem, union Sass_Value* v, Context& ctx, Backtrace* backtrace, ParserState pstate)
1343+
Expression* cval_to_astnode(Memory_Manager& mem, union Sass_Value* v, Context& ctx, Backtrace* backtrace, ParserState pstate)
13441344
{
13451345
using std::strlen;
13461346
using std::strcpy;

src/eval.hpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -89,18 +89,18 @@ namespace Sass {
8989
static bool eq(Expression*, Expression*);
9090
static bool lt(Expression*, Expression*);
9191
// -- arithmetic on the combinations that matter
92-
static Value* op_numbers(Memory_Manager<AST_Node>&, enum Sass_OP, const Number&, const Number&, bool compressed = false, int precision = 5);
93-
static Value* op_number_color(Memory_Manager<AST_Node>&, enum Sass_OP, const Number&, const Color&, bool compressed = false, int precision = 5);
94-
static Value* op_color_number(Memory_Manager<AST_Node>&, enum Sass_OP, const Color&, const Number&, bool compressed = false, int precision = 5);
95-
static Value* op_colors(Memory_Manager<AST_Node>&, enum Sass_OP, const Color&, const Color&, bool compressed = false, int precision = 5);
96-
static Value* op_strings(Memory_Manager<AST_Node>&, enum Sass_OP, Value&, Value&, bool compressed = false, int precision = 5);
92+
static Value* op_numbers(Memory_Manager&, enum Sass_OP, const Number&, const Number&, bool compressed = false, int precision = 5);
93+
static Value* op_number_color(Memory_Manager&, enum Sass_OP, const Number&, const Color&, bool compressed = false, int precision = 5);
94+
static Value* op_color_number(Memory_Manager&, enum Sass_OP, const Color&, const Number&, bool compressed = false, int precision = 5);
95+
static Value* op_colors(Memory_Manager&, enum Sass_OP, const Color&, const Color&, bool compressed = false, int precision = 5);
96+
static Value* op_strings(Memory_Manager&, enum Sass_OP, Value&, Value&, bool compressed = false, int precision = 5);
9797

9898
private:
9999
std::string interpolation(Expression* s, bool into_quotes = false);
100100

101101
};
102102

103-
Expression* cval_to_astnode(Memory_Manager<AST_Node>& mem, union Sass_Value* v, Context& ctx, Backtrace* backtrace, ParserState pstate = ParserState("[AST]"));
103+
Expression* cval_to_astnode(Memory_Manager& mem, union Sass_Value* v, Context& ctx, Backtrace* backtrace, ParserState pstate = ParserState("[AST]"));
104104

105105
}
106106

src/memory_manager.cpp

Lines changed: 23 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,16 @@
33

44
namespace Sass {
55

6-
template <typename T>
7-
Memory_Manager<T>::Memory_Manager(size_t size)
8-
: nodes(std::vector<T*>())
6+
Memory_Manager::Memory_Manager(size_t size)
7+
: nodes(std::vector<Memory_Object*>())
98
{
109
size_t init = size;
1110
if (init < 8) init = 8;
1211
// reserve some space
1312
nodes.reserve(init);
1413
}
1514

16-
template <typename T>
17-
Memory_Manager<T>::~Memory_Manager()
15+
Memory_Manager::~Memory_Manager()
1816
{
1917
// release memory for all controlled nodes
2018
// avoid calling erase for every single node
@@ -25,64 +23,54 @@ namespace Sass {
2523
nodes.clear();
2624
}
2725

28-
template <typename T>
29-
T* Memory_Manager<T>::add(T* np)
26+
Memory_Object* Memory_Manager::add(Memory_Object* np)
3027
{
31-
void* heap = (char*)np - 1;
32-
*((char*)((void*)heap)) = 1;
28+
// object has been initialized
29+
// it can be "deleted" from now on
30+
np->refcount = 1;
3331
return np;
3432
}
3533

36-
template <typename T>
37-
bool Memory_Manager<T>::has(T* np)
34+
bool Memory_Manager::has(Memory_Object* np)
3835
{
3936
// check if the pointer is controlled under our pool
4037
return find(nodes.begin(), nodes.end(), np) != nodes.end();
4138
}
4239

43-
template <typename T>
44-
T* Memory_Manager<T>::allocate(size_t size)
40+
Memory_Object* Memory_Manager::allocate(size_t size)
4541
{
46-
// need additional memory for status header
47-
void* heap = malloc(sizeof(char) + size);
48-
// init internal status to zero
49-
*(static_cast<char*>(heap)) = 0;
50-
// the object lives on char further
51-
void* object = static_cast<char*>(heap) + 1;
42+
// allocate requested memory
43+
void* heap = malloc(size);
44+
// init internal refcount status to zero
45+
(static_cast<Memory_Object*>(heap))->refcount = 0;
5246
// add the memory under our management
53-
nodes.push_back(static_cast<T*>(object));
54-
// cast object to its final type
55-
return static_cast<T*>(object);
47+
nodes.push_back(static_cast<Memory_Object*>(heap));
48+
// cast object to its initial type
49+
return static_cast<Memory_Object*>(heap);
5650
}
5751

58-
template <typename T>
59-
void Memory_Manager<T>::deallocate(T* np)
52+
void Memory_Manager::deallocate(Memory_Object* np)
6053
{
61-
void* object = static_cast<void*>(np);
62-
char* heap = static_cast<char*>(object) - 1;
63-
if (heap[0]) np->~T();
64-
free(heap);
54+
// only call destructor if initialized
55+
if (np->refcount) np->~Memory_Object();
56+
// always free the memory
57+
free(np);
6558
}
6659

67-
template <typename T>
68-
void Memory_Manager<T>::remove(T* np)
60+
void Memory_Manager::remove(Memory_Object* np)
6961
{
7062
// remove node from pool (no longer active)
7163
nodes.erase(find(nodes.begin(), nodes.end(), np));
7264
// you are now in control of the memory
7365
}
7466

75-
template <typename T>
76-
void Memory_Manager<T>::destroy(T* np)
67+
void Memory_Manager::destroy(Memory_Object* np)
7768
{
7869
// remove from pool
7970
remove(np);
8071
// release memory
8172
deallocate(np);
8273
}
8374

84-
// compile implementation for AST_Node
85-
template class Memory_Manager<AST_Node>;
86-
8775
}
8876

src/memory_manager.hpp

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,27 +4,35 @@
44
#include <vector>
55

66
namespace Sass {
7+
8+
class Memory_Object {
9+
friend class Memory_Manager;
10+
long refcount;
11+
public:
12+
Memory_Object() { refcount = 0; };
13+
virtual ~Memory_Object() {};
14+
};
15+
716
/////////////////////////////////////////////////////////////////////////////
817
// A class for tracking allocations of AST_Node objects. The intended usage
918
// is something like: Some_Node* n = new (mem_mgr) Some_Node(...);
1019
// Then, at the end of the program, the memory manager will delete all of the
1120
// allocated nodes that have been passed to it.
1221
// In the future, this class may implement a custom allocator.
1322
/////////////////////////////////////////////////////////////////////////////
14-
template <typename T>
1523
class Memory_Manager {
16-
std::vector<T*> nodes;
24+
std::vector<Memory_Object*> nodes;
1725

1826
public:
1927
Memory_Manager(size_t size = 0);
2028
~Memory_Manager();
2129

22-
bool has(T* np);
23-
T* allocate(size_t size);
24-
void deallocate(T* np);
25-
void remove(T* np);
26-
void destroy(T* np);
27-
T* add(T* np);
30+
bool has(Memory_Object* np);
31+
Memory_Object* allocate(size_t size);
32+
void deallocate(Memory_Object* np);
33+
void remove(Memory_Object* np);
34+
void destroy(Memory_Object* np);
35+
Memory_Object* add(Memory_Object* np);
2836

2937
};
3038
}

src/sass_values.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -348,7 +348,7 @@ extern "C" {
348348

349349
union Sass_Value* ADDCALL sass_value_stringify (const union Sass_Value* v, bool compressed, int precision)
350350
{
351-
Memory_Manager<AST_Node> mem;
351+
Memory_Manager mem;
352352
Value* val = sass_value_to_ast_node(mem, v);
353353
std::string str(val->to_string(compressed, precision));
354354
return sass_make_qstring(str.c_str());
@@ -358,7 +358,7 @@ extern "C" {
358358
{
359359

360360
Sass::Value* rv = 0;
361-
Memory_Manager<AST_Node> mem;
361+
Memory_Manager mem;
362362

363363
try {
364364

0 commit comments

Comments
 (0)