X-Boost  2.3.8
JITHaarFeature.h
Go to the documentation of this file.
1 /* XBoost: Ada-Boost and Friends on Haar/ICF/HOG Features, Library and ToolBox
2  *
3  * Copyright (c) 2008-2014 Paolo Medici <medici@ce.unipr.it>
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18  * Boston, MA 02111-1307, USA.
19  */
20 
21 #ifndef _XBOOST_HAAR_FEATURE_JIT_H
22 #define _XBOOST_HAAR_FEATURE_JIT_H
23 
28 #include <vector>
29 // #include <cmath>
30 #include <sys/mman.h>
31 #include <malloc.h>
32 #include <unistd.h>
33 #include <string.h>
34 #include <stdexcept>
35 
37 class jit {
38 public:
39  typedef int (* callback)(const unsigned int *) __attribute__((fastcall));
40 
41 private:
42 
43  std::vector<unsigned char *> m_pages;
44 
45  unsigned char *m_proc;
46  int index;
47  int pagesize;
48 
49  void push_back(unsigned char c)
50  {
51  if(index>=pagesize)
52  {
53  std::cerr << "Exceed " << pagesize << " bytes" << std::endl;
54  throw std::runtime_error("too large application");
55  }
56  m_proc[index]=c;
57  index++;
58  }
59 
60  int is_8bit(int offset)
61  {
62  return (offset<128) && (offset>-129);
63  }
64 
65  void reserve_page()
66  {
67  if(posix_memalign((void**) &m_proc, pagesize,pagesize)!=0)
68  throw std::runtime_error("posix_memalign failed");
69  memset(m_proc, 0x90, pagesize);
70  if(mprotect(m_proc, pagesize, PROT_EXEC|PROT_READ|PROT_WRITE)!=0)
71  throw std::runtime_error("mprotect failed");
72  m_pages.push_back(m_proc);
73  }
74 
75 public:
76 
77  jit() {
78  index = 0;
79  pagesize = sysconf(_SC_PAGE_SIZE)*4;
80  reserve_page();
81  }
82 
83  ~jit()
84  {
85  for(std::vector<unsigned char *>::const_iterator i = m_pages.begin(); i!= m_pages.end(); ++i)
86  ::free(*i);
87  }
88 
89  void clear()
90  {
91  for(std::vector<unsigned char *>::const_iterator i = m_pages.begin(); i!= m_pages.end(); ++i)
92  ::free(*i);
93  m_pages.clear();
94  reserve_page();
95  index = 0;
96  }
97 
98 
99 /***********************************************************/
100 
102  callback GetProcAddr() const
103  {
104  return reinterpret_cast<callback>(&m_proc[index]);
105  }
106 
109  void move(int offset)
110  {
111  if(is_8bit(offset))
112  {
113  // 8b 47 xx
114  push_back(0x8b);
115  push_back(0x47);
116  push_back(offset & 0xff);
117  }
118  else
119  {
120  // 8b 87 xx xx xx xx
121  push_back(0x8b);
122  push_back(0x87);
123  push_back(offset & 0xff);
124  push_back((offset & 0xff00)>>8);
125  push_back((offset & 0xff0000)>>16);
126  push_back((offset & 0xff000000)>>24);
127  }
128  }
129 
132  void add(int offset)
133  {
134  if(is_8bit(offset))
135  {
136  // 03 47 xx add -0x4(%rdi),%eax
137  push_back(0x03);
138  push_back(0x47);
139  push_back(offset & 0xff);
140  }
141  else
142  {
143  // 03 87 xx xx xx xx add 0x1f40(%rdi),%eax
144  push_back(0x03);
145  push_back(0x87);
146  push_back(offset & 0xff);
147  push_back((offset & 0xff00)>>8);
148  push_back((offset & 0xff0000)>>16);
149  push_back((offset & 0xff000000)>>24);
150  }
151 
152  }
153 
156  void sub(int offset)
157  {
158  if(is_8bit(offset))
159  {
160  // 2b 47 xx sub 0x8(%rdi),%eax
161  push_back(0x2b);
162  push_back(0x47);
163  push_back(offset&0xff);
164  }
165  else
166  {
167  // 2b 87 xx xx xx xx sub 0x1f40(%rdi),%eax
168  push_back(0x2b);
169  push_back(0x87);
170  push_back(offset & 0xff);
171  push_back((offset & 0xff00)>>8);
172  push_back((offset & 0xff0000)>>16);
173  push_back((offset & 0xff000000)>>24);
174  }
175  }
176 
178  void mul(int f)
179  {
180  if(f==4)
181  {
182  // c1 e0 02 shl $0x2,%eax
183  push_back(0xc1);
184  push_back(0xe0);
185  push_back(0x02);
186  }
187  else
188  if(f==3)
189  {
190  // 8d 04 40 lea (%rax,%rax,2),%eax
191  push_back(0x8d);
192  push_back(0x04);
193  push_back(0x40);
194  }
195  else
196  if(f==2)
197  {
198  // 01 c0 add %eax,%eax
199  push_back(0x01);
200  push_back(0xc0);
201  }
202  }
203 
205  void retq()
206  {
207  push_back(0xc3);
208 // std::cout << "index:" <<index << std::endl;
209 
210  // align 16byte boundaries
211  index = (index+15)&(~0xF);
212  }
213 
214 };
215 
216 extern jit op;
217 
219  jit::callback proc;
220 
222 public:
223 JITHaarFeature(const HaarFeature &src, long offset, long stride) : test(src, offset, stride)
224 {
225  int mul[4];
226  mul[0]=0; // 1
227  mul[1]=0; // 2
228  mul[2]=0; // 3
229  mul[3]=0; // 4
230 
231  // MULTIPLYER
232  for(std::vector<HaarNode>::const_iterator i=src.begin();i!=src.end();++i)
233  mul[ std::abs(i->sign) - 1] = 1;
234 
235  int factor = 1;
236 
237  if(mul[1]!=0)
238  factor = 2;
239  if(mul[2]!=0)
240  factor = 3;
241  if(mul[3]!=0)
242  factor = 4;
243 
244  proc = op.GetProcAddr();
245 
246  if((mul[1]+mul[2]+mul[3])>1)
247  {
248  bool first = true;
249 // std::cout << "Slow Feature" << std::endl;
250  // POSITIVI
251  for(std::vector<HaarNode>::const_iterator i=src.begin();i!=src.end();++i)
252  if( i->sign > 0)
253  {
254  int __offset = (offset + i->x + i->y * stride)*4;
255  if(first)
256  {
257  op.move( __offset );
258  op.mul( i->sign );
259  first = false;
260  }
261  else
262  {
263  for(int j=0;j<i->sign;++j)
264  op.add ( __offset);
265  }
266  }
267  // NEGATIVI
268  for(std::vector<HaarNode>::const_iterator i=src.begin();i!=src.end();++i)
269  if( i->sign < 0)
270  {
271  int __offset = (offset + i->x + i->y * stride)*4;
272  for(int j=0;j<std::abs(i->sign);++j)
273  op.sub ( __offset);
274  }
275  }
276  else
277  if(factor!=1)
278  {
279  bool first = true;
280  // POSITIVI
281  for(std::vector<HaarNode>::const_iterator i=src.begin();i!=src.end();++i)
282  if( i->sign == factor)
283  {
284  int __offset = (offset + i->x + i->y * stride)*4;
285  if(first)
286  {
287  op.move( __offset );
288  first = false;
289  }
290  else
291  op.add ( __offset);
292  }
293  // NEGATIVI
294  for(std::vector<HaarNode>::const_iterator i=src.begin();i!=src.end();++i)
295  if( i->sign == -factor)
296  {
297  int __offset = (offset + i->x + i->y * stride)*4;
298  op.sub(__offset);
299  }
300 
301  // MULTIPLICA
302  op.mul(factor);
303 
304  // +1-1
305  for(std::vector<HaarNode>::const_iterator i=src.begin();i!=src.end();++i)
306  {
307  int __offset = (offset + i->x + i->y * stride)*4;
308  if( i->sign == 1)
309  op.add( __offset);
310  else
311  if( i->sign == -1)
312  op.sub( __offset);
313  }
314  }
315  else
316  {
317  bool first = true;
318  // POSITIVI
319  for(std::vector<HaarNode>::const_iterator i=src.begin();i!=src.end();++i)
320  if( i->sign == 1)
321  {
322  int __offset = (offset + i->x + i->y * stride)*4;
323  if(first)
324  {
325  op.move( __offset );
326  first = false;
327  }
328  else
329  op.add ( __offset );
330  }
331  // NEGATIVI
332  for(std::vector<HaarNode>::const_iterator i=src.begin();i!=src.end();++i)
333  if( i->sign == -1)
334  {
335  int __offset = (offset + i->x + i->y * stride)*4;
336  op.sub(__offset);
337  }
338  }
339 
340  op.retq();
341 }
342 
343 
345  inline int response(const unsigned int *pIntImage) const
346  {
347 // int a =proc(pIntImage);
348 // int b = test.response(pIntImage);
349 // if(a!=b)
350 // std::cout << "error: " << a << ' ' << b << std::endl;
351 // return b;
352  return proc(pIntImage);
353  }
354 
355  inline int operator() (const unsigned int *pIntImage) const
356  {
357  return response(pIntImage);
358  }
359 
360 };
361 
362 #endif
Definition: JITHaarFeature.h:37
int response(const unsigned int *pIntImage) const
compute the response
Definition: JITHaarFeature.h:345
void retq()
complete and return the procedure
Definition: JITHaarFeature.h:205
an optimized HaarFeature
Definition: CollapsedHaarFeature.h:50
An haar Feature: a collection of weighted HaarNode.
Definition: HaarFeature.h:63
Definition: JITHaarFeature.h:218
callback GetProcAddr() const
Return the current procedure addres.
Definition: JITHaarFeature.h:102
void add(int offset)
Definition: JITHaarFeature.h:132
void mul(int f)
NOTE: offset in bytes and not in uint32_t!!!
Definition: JITHaarFeature.h:178
void move(int offset)
Definition: JITHaarFeature.h:109
void sub(int offset)
Definition: JITHaarFeature.h:156