MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
NdbInterpretedCode.cpp
1 /*
2  Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
3 
4  This program is free software; you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation; version 2 of the License.
7 
8  This program is distributed in the hope that it will be useful,
9  but WITHOUT ANY WARRANTY; without even the implied warranty of
10  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  GNU General Public License for more details.
12 
13  You should have received a copy of the GNU General Public License
14  along with this program; if not, write to the Free Software
15  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
16 */
17 
18 #include <ndb_global.h>
19 #include "NdbInterpretedCode.hpp"
20 #include "Interpreter.hpp"
21 #include "NdbDictionaryImpl.hpp"
22 
23 /*
24  ToDo: We should add placeholders to this, so that one can use a single
25  InterpretedCode object to create many operations from different embedded
26  constants. Once we do this, we could add more error checks, as the cost
27  would then not be paid for each operation creation.
28  Suggest that fixed-size constants are replaced inline with latest values
29  using instruction checking prior to send and new 'virtual' instructions
30  which are resolved to real instructions at send time. This requires a new
31  interface to send parts of code, parts of placeholders and parts of other
32  words.
33  Var-sized constants can be used via a new branch_attr_op_arg instruction and
34  use of some space in the subroutine section to store the constants.
35  Wait for good use-case for placeholders. Best currently is conflict detection,
36  but the conflict detection programs are very short, so perhaps it's not
37  worthwhile.
38 */
39 
41  Uint32 *buffer, Uint32 buffer_word_size) :
42  m_table_impl(0),
43  m_buffer(buffer),
44  m_buffer_length(buffer_word_size),
45  m_internal_buffer(0),
46  m_number_of_labels(0),
47  m_number_of_subs(0),
48  m_number_of_calls(0),
49  m_last_meta_pos(m_buffer_length),
50  m_instructions_length(0),
51  m_first_sub_instruction_pos(0),
52  m_available_length(m_buffer_length),
53  m_flags(0)
54 {
55  if (table != NULL)
56  m_table_impl= & NdbTableImpl::getImpl(*table);
57  m_error.code= 0;
58 }
59 
60 NdbInterpretedCode::~NdbInterpretedCode()
61 {
62  if (m_internal_buffer != NULL)
63  {
64  delete [] m_internal_buffer;
65  }
66 }
67 
68 
69 
70 int
71 NdbInterpretedCode::error(Uint32 code)
72 {
73  m_flags|= GotError;
74  m_error.code= code;
75  return -1;
76 }
77 
78 /* Make sure there's space for the number of words
79  * specified between the end of the code and the
80  * start of the meta information or return false.
81  * This method dynamically doubles the internal buffer
82  * length if the caller did not supply a buffer.
83  */
84 bool
85 NdbInterpretedCode::have_space_for(Uint32 wordsRequired)
86 {
87  assert(m_last_meta_pos <= m_buffer_length);
88  assert(m_last_meta_pos >= m_instructions_length);
89  assert(m_available_length == m_last_meta_pos - m_instructions_length);
90  if (likely(m_available_length >= wordsRequired))
91  return true;
92 
93  if ((m_internal_buffer != NULL) || (m_buffer_length == 0))
94  {
95  Uint32 newSize= m_buffer_length;
96  const Uint32 extraRequired= wordsRequired - m_available_length;
97 
98  /* Initial allocation of dynamic buffer */
99  if (newSize == 0)
100  newSize= 1;
101 
102  do {
103  /* Double buffer length until there's enough space, or
104  * we reach the maximum size
105  */
106  newSize= newSize << 1;
107  } while (((newSize - m_buffer_length) < extraRequired) &&
108  (newSize < MaxDynamicBufSize));
109 
110  if (newSize > MaxDynamicBufSize)
111  newSize= MaxDynamicBufSize;
112 
113  /* Were we able to get enough extra space? */
114  if ((newSize - m_buffer_length) >= extraRequired)
115  {
116  Uint32 *newBuf= new Uint32[ newSize ];
117 
118  if (newBuf != NULL)
119  {
120  Uint32 metaInfoWords= m_buffer_length - m_last_meta_pos;
121  Uint32 newLastMetaInfoPos= newSize - metaInfoWords;
122 
123  if (m_buffer_length > 0)
124  {
125  /* Copy instruction words to start of new buffer */
126  memcpy(newBuf, m_internal_buffer, m_instructions_length << 2);
127 
128  /* Copy metainfo words to end of new buffer */
129  memcpy(&newBuf[ newLastMetaInfoPos ],
130  &m_buffer[ m_last_meta_pos ],
131  metaInfoWords << 2);
132 
133  delete [] m_internal_buffer;
134  }
135 
136  m_buffer= m_internal_buffer= newBuf;
137  m_available_length+= (newSize - m_buffer_length);
138  m_buffer_length= newSize;
139  m_last_meta_pos= newLastMetaInfoPos;
140 
141  return true;
142  }
143  }
144  }
145  return false;
146 }
147 
148 inline int
149 NdbInterpretedCode::add1(Uint32 x1)
150 {
151  if (unlikely(! have_space_for(1)))
152  return error(TooManyInstructions);
153 
154  Uint32 current = m_instructions_length;
155  m_buffer[current ] = x1;
156  m_instructions_length = current + 1;
157  m_available_length--;
158  return 0;
159 }
160 
161 inline int
162 NdbInterpretedCode::add2(Uint32 x1, Uint32 x2)
163 {
164  if (unlikely(! have_space_for(2)))
165  return error(TooManyInstructions);
166  Uint32 current = m_instructions_length;
167  m_buffer[current ] = x1;
168  m_buffer[current + 1] = x2;
169  m_instructions_length = current + 2;
170  m_available_length-= 2;
171  return 0;
172 }
173 
174 inline int
175 NdbInterpretedCode::add3(Uint32 x1, Uint32 x2, Uint32 x3)
176 {
177  if (unlikely(! have_space_for(3)))
178  return error(TooManyInstructions);
179  Uint32 current = m_instructions_length;
180  m_buffer[current ] = x1;
181  m_buffer[current + 1] = x2;
182  m_buffer[current + 2] = x3;
183  m_instructions_length = current + 3;
184  m_available_length-= 3;
185  return 0;
186 }
187 
188 inline int
189 NdbInterpretedCode::addN(Uint32 *data, Uint32 length)
190 {
191  if (unlikely(! have_space_for(length)))
192  return error(TooManyInstructions);
193 
194  /* data* may be unaligned, so we do a byte copy
195  * using memcpy
196  */
197  memcpy(&m_buffer[m_instructions_length],
198  data,
199  length << 2);
200 
201  m_instructions_length+= length;
202  m_available_length-= length;
203 
204  return 0;
205 }
206 
207 inline int
208 NdbInterpretedCode::addMeta(CodeMetaInfo& info)
209 {
210  if (unlikely(! have_space_for(CODEMETAINFO_WORDS)))
211  return error(TooManyInstructions);
212 
213  m_buffer[--m_last_meta_pos]= (Uint32)info.number << 16 | info.type;
214  m_buffer[--m_last_meta_pos]= info.firstInstrPos;
215 
216  m_available_length-= CODEMETAINFO_WORDS;
217 
218  return 0;
219 }
220 
221 int
222 NdbInterpretedCode::add_reg(Uint32 RegDest,
223  Uint32 RegSource1, Uint32 RegSource2)
224 {
225  return add1(Interpreter::Add(RegDest % MaxReg, RegSource1 % MaxReg,
226  RegSource2 % MaxReg));
227 }
228 
229 int
230 NdbInterpretedCode::sub_reg(Uint32 RegDest,
231  Uint32 RegSource1, Uint32 RegSource2)
232 {
233  return add1(Interpreter::Sub(RegDest % MaxReg, RegSource1 % MaxReg,
234  RegSource2 % MaxReg));
235 }
236 
237 int
238 NdbInterpretedCode::load_const_u32(Uint32 RegDest, Uint32 Constant)
239 {
240  return add2(Interpreter::LoadConst32(RegDest % MaxReg), Constant);
241 }
242 
243 int
244 NdbInterpretedCode::load_const_u64(Uint32 RegDest, Uint64 Constant)
245 {
246  union {
247  Uint64 val64;
248  Uint32 val32[2];
249  };
250  val64 = Constant;
251  return add3(Interpreter::LoadConst64(RegDest % MaxReg), val32[0], val32[1]);
252 }
253 
254 int
255 NdbInterpretedCode::load_const_null(Uint32 RegDest)
256 {
257  return add1(Interpreter::LoadNull(RegDest % MaxReg));
258 }
259 
260 int
261 NdbInterpretedCode::load_const_u16(Uint32 RegDest, Uint32 Constant)
262 {
263  return add1(Interpreter::LoadConst16((RegDest % MaxReg), Constant));
264 }
265 
266 int
267 NdbInterpretedCode::read_attr_impl(const NdbColumnImpl *c, Uint32 RegDest)
268 {
269  if (c->m_storageType == NDB_STORAGETYPE_DISK)
270  m_flags|= UsesDisk;
271  return add1(Interpreter::Read(c->m_attrId, RegDest % MaxReg));
272 }
273 
274 int
275 NdbInterpretedCode::read_attr(Uint32 RegDest, Uint32 attrId)
276 {
277  if (unlikely(m_table_impl == NULL))
278  /* NdbInterpretedCode instruction requires that table is set */
279  return error(4538);
280  const NdbColumnImpl *c= m_table_impl->getColumn(attrId);
281  if (unlikely(c == NULL))
282  return error(BadAttributeId);
283  return read_attr_impl(c, RegDest);
284 }
285 
286 int
287 NdbInterpretedCode::read_attr(Uint32 RegDest,
288  const NdbDictionary::Column *column)
289 {
290  if (unlikely(m_table_impl == NULL))
291  /* NdbInterpretedCode instruction requires that table is set */
292  return error(4538);
293  // TODO : Check column is from the correct table
294  return read_attr_impl(&NdbColumnImpl::getImpl(*column), RegDest);
295 }
296 
297 int
298 NdbInterpretedCode::write_attr_impl(const NdbColumnImpl *c, Uint32 RegSource)
299 {
300  if (c->m_storageType == NDB_STORAGETYPE_DISK)
301  m_flags|= UsesDisk;
302  return add1(Interpreter::Write(c->m_attrId, RegSource % MaxReg));
303 }
304 
305 int
306 NdbInterpretedCode::write_attr(Uint32 attrId, Uint32 RegSource)
307 {
308  if (unlikely(m_table_impl == NULL))
309  /* NdbInterpretedCode instruction requires that table is set */
310  return error(4538);
311  const NdbColumnImpl *c= m_table_impl->getColumn(attrId);
312  if (unlikely(c == NULL))
313  return error(BadAttributeId);
314  return write_attr_impl(c, RegSource);
315 }
316 
317 int
318 NdbInterpretedCode::write_attr(const NdbDictionary::Column *column,
319  Uint32 RegSource)
320 {
321  if (unlikely(m_table_impl == NULL))
322  /* NdbInterpretedCode instruction requires that table is set */
323  return error(4538);
324  // TODO : Check column is from the right table
325  return write_attr_impl(&NdbColumnImpl::getImpl(*column), RegSource);
326 }
327 
328 int
329 NdbInterpretedCode::def_label(int LabelNum)
330 {
331  if (LabelNum < 0 ||
332  (Uint32)LabelNum > MaxLabels)
333  return error(BadLabelNum);
334 
335  m_number_of_labels++;
336 
337  CodeMetaInfo info;
338 
339  info.type= Label;
340  info.number= LabelNum;
341  info.firstInstrPos= m_instructions_length;
342 
343  // Note, no check for whether the label's already defined here.
344  return addMeta(info);
345 }
346 
347 int
348 NdbInterpretedCode::add_branch(Uint32 instruction, Uint32 Label)
349 {
350  /* We store the instruction with the label as the offset
351  * rather than the correct offset.
352  * This is corrected at finalise() time when we know
353  * the correct offset for the code
354  */
355  if (unlikely(Label > 0xffff))
356  return error(BranchToBadLabel);
357  return add1(instruction | Label << 16);
358 }
359 
360 int
361 NdbInterpretedCode::branch_label(Uint32 Label)
362 {
363  return add_branch(Interpreter::BRANCH, Label);
364 }
365 
366 /* For the following inequalities, the order of the
367  * registers passed to Interpreter::Branch is reversed
368  * to correct the reordering done in Interpreter::Branch
369  * This ensures that the comparison is Lvalue <cond> Rvalue,
370  * not Rvalue <cond> Lvalue.
371  */
372 int
373 NdbInterpretedCode::branch_ge(Uint32 RegLvalue, Uint32 RegRvalue,
374  Uint32 Label)
375 {
376  Uint32 instr = Interpreter::Branch(Interpreter::BRANCH_GE_REG_REG,
377  RegRvalue, RegLvalue);
378  return add_branch(instr, Label);
379 }
380 
381 int
382 NdbInterpretedCode::branch_gt(Uint32 RegLvalue, Uint32 RegRvalue,
383  Uint32 Label)
384 {
385  Uint32 instr = Interpreter::Branch(Interpreter::BRANCH_GT_REG_REG,
386  RegRvalue, RegLvalue);
387  return add_branch(instr, Label);
388 }
389 
390 int
391 NdbInterpretedCode::branch_le(Uint32 RegLvalue, Uint32 RegRvalue,
392  Uint32 Label)
393 {
394  Uint32 instr = Interpreter::Branch(Interpreter::BRANCH_LE_REG_REG,
395  RegRvalue, RegLvalue);
396  return add_branch(instr, Label);
397 }
398 
399 int
400 NdbInterpretedCode::branch_lt(Uint32 RegLvalue, Uint32 RegRvalue,
401  Uint32 Label)
402 {
403  Uint32 instr = Interpreter::Branch(Interpreter::BRANCH_LT_REG_REG,
404  RegRvalue, RegLvalue);
405  return add_branch(instr, Label);
406 }
407 
408 int
409 NdbInterpretedCode::branch_eq(Uint32 RegLvalue, Uint32 RegRvalue,
410  Uint32 Label)
411 {
412  Uint32 instr = Interpreter::Branch(Interpreter::BRANCH_EQ_REG_REG,
413  RegLvalue, RegRvalue);
414  return add_branch(instr, Label);
415 }
416 
417 int
418 NdbInterpretedCode::branch_ne(Uint32 RegLvalue, Uint32 RegRvalue,
419  Uint32 Label)
420 {
421  Uint32 instr = Interpreter::Branch(Interpreter::BRANCH_NE_REG_REG,
422  RegLvalue, RegRvalue);
423  return add_branch(instr, Label);
424 }
425 
426 int
427 NdbInterpretedCode::branch_ne_null(Uint32 RegLvalue, Uint32 Label)
428 {
429  return add_branch
430  (((RegLvalue % MaxReg) << 6) | Interpreter::BRANCH_REG_NE_NULL, Label);
431 }
432 
433 int
434 NdbInterpretedCode::branch_eq_null(Uint32 RegLvalue, Uint32 Label)
435 {
436  return add_branch
437  (((RegLvalue % MaxReg) << 6) | Interpreter::BRANCH_REG_EQ_NULL, Label);
438 }
439 
440 int
441 NdbInterpretedCode::branch_col_eq_null(Uint32 attrId, Uint32 Label)
442 {
443  int res= 0;
444 
445  if (unlikely(m_table_impl == NULL))
446  /* NdbInterpretedCode instruction requires that table is set */
447  return error(4538);
448  const NdbColumnImpl *c= m_table_impl->getColumn(attrId);
449 
450  if (unlikely(c == NULL))
451  return error(BadAttributeId);
452 
453  if (c->m_storageType == NDB_STORAGETYPE_DISK)
454  m_flags|= UsesDisk;
455 
456  /* Add instruction and branch label */
457  if ((res= add_branch(Interpreter::BRANCH_ATTR_EQ_NULL, Label)) !=0)
458  return res;
459 
460  /* Add attrId with no length */
461  return add1(Interpreter::BranchCol_2(attrId));
462 }
463 
464 int
465 NdbInterpretedCode::branch_col_ne_null(Uint32 attrId, Uint32 Label)
466 {
467  int res= 0;
468 
469  if (unlikely(m_table_impl == NULL))
470  /* NdbInterpretedCode instruction requires that table is set */
471  return error(4538);
472  const NdbColumnImpl *c= m_table_impl->getColumn(attrId);
473 
474  if (unlikely(c == NULL))
475  return error(BadAttributeId);
476 
477  if (c->m_storageType == NDB_STORAGETYPE_DISK)
478  m_flags|= UsesDisk;
479 
480  /* Add instruction and branch label */
481  if ((res= add_branch(Interpreter::BRANCH_ATTR_NE_NULL, Label)) !=0)
482  return res;
483 
484  /* Add attrId with no length */
485  return add1(Interpreter::BranchCol_2(attrId));
486 }
487 
488 int
489 NdbInterpretedCode::branch_col(Uint32 branch_type,
490  Uint32 attrId,
491  const void * val,
492  Uint32 len,
493  Uint32 Label)
494 {
495  DBUG_ENTER("NdbInterpretedCode::branch_col");
496  DBUG_PRINT("enter", ("type: %u col:%u val: 0x%lx len: %u label: %u",
497  branch_type, attrId, (long) val, len, Label));
498  if (val != NULL)
499  DBUG_DUMP("value", (uchar*)val, len);
500  else
501  DBUG_PRINT("info", ("value == NULL"));
502 
503  Interpreter::BinaryCondition c=
504  (Interpreter::BinaryCondition)branch_type;
505 
506  if (unlikely(m_table_impl == NULL))
507  /* NdbInterpretedCode instruction requires that table is set */
508  DBUG_RETURN(error(4538));
509 
510  const NdbColumnImpl * col =
511  m_table_impl->getColumn(attrId);
512 
513  if(col == NULL){
514  DBUG_RETURN(error(BadAttributeId));
515  }
516 
517  Uint32 lastWordMask= ~0;
518  if (val == NULL)
519  len = 0;
520  else {
521  if (! col->getStringType())
522  {
523  /* Fixed size type */
524  if (col->getType() == NDB_TYPE_BIT)
525  {
526  /* We want to zero out insignificant bits in the
527  * last word of a bit type
528  */
529  Uint32 bitLen= col->getLength();
530  Uint32 lastWordBits= bitLen & 0x1F;
531  if (lastWordBits)
532  lastWordMask= (1 << lastWordBits) -1;
533  }
534  len= col->m_attrSize * col->m_arraySize;
535  }
536  else
537  {
538  /* For Like and Not like we must use the passed in
539  * length. Otherwise we use the length encoded
540  * in the passed string
541  */
542  if ((branch_type != Interpreter::LIKE) &&
543  (branch_type != Interpreter::NOT_LIKE))
544  {
545  if (! col->get_var_length(val, len))
546  {
547  DBUG_RETURN(error(BadLength));
548  }
549  }
550  }
551  }
552 
553  if (col->m_storageType == NDB_STORAGETYPE_DISK)
554  m_flags|= UsesDisk;
555 
556  if (add_branch(Interpreter::BranchCol(c, 0, 0), Label) != 0)
557  DBUG_RETURN(-1);
558 
559  if (add1(Interpreter::BranchCol_2(attrId, len)) != 0)
560  DBUG_RETURN(-1);
561 
562  /* Get value byte length rounded up to nearest 32-bit word */
563  Uint32 len2 = Interpreter::mod4(len);
564  if((len2 == len) && (lastWordMask == (Uint32)~0))
565  {
566  /* Whole number of 32-bit words */
567  DBUG_RETURN(addN((Uint32*)val, len2 >> 2));
568  }
569 
570  /* else */
571  /* Partial last word */
572  len2 -= 4;
573  if (addN((Uint32*)val, len2 >> 2) != 0)
574  DBUG_RETURN(-1);
575 
576  /* Zero insignificant bytes in last word */
577  Uint32 tmp = 0;
578  for (Uint32 i = 0; i < len-len2; i++) {
579  char* p = (char*)&tmp;
580  p[i] = ((char*)val)[len2+i];
581  }
582  DBUG_RETURN(add1((tmp & lastWordMask)));
583 }
584 
585 int
586 NdbInterpretedCode::branch_col_eq(const void * val,
587  Uint32 len,
588  Uint32 attrId,
589  Uint32 Label)
590 {
591  return branch_col(Interpreter::EQ, attrId, val, 0, Label);
592 }
593 
594 int
595 NdbInterpretedCode::branch_col_ne(const void * val,
596  Uint32 len,
597  Uint32 attrId,
598  Uint32 Label)
599 {
600  return branch_col(Interpreter::NE, attrId, val, 0, Label);
601 }
602 
603 int
604 NdbInterpretedCode::branch_col_lt(const void * val,
605  Uint32 len,
606  Uint32 attrId,
607  Uint32 Label)
608 {
609  return branch_col(Interpreter::LT, attrId, val, 0, Label);
610 }
611 
612 int
613 NdbInterpretedCode::branch_col_le(const void * val,
614  Uint32 len,
615  Uint32 attrId,
616  Uint32 Label)
617 {
618  return branch_col(Interpreter::LE, attrId, val, 0, Label);
619 }
620 
621 int
622 NdbInterpretedCode::branch_col_gt(const void * val,
623  Uint32 len,
624  Uint32 attrId,
625  Uint32 Label)
626 {
627  return branch_col(Interpreter::GT, attrId, val, 0, Label);
628 }
629 
630 int
631 NdbInterpretedCode::branch_col_ge(const void * val,
632  Uint32 len,
633  Uint32 attrId,
634  Uint32 Label)
635 {
636  return branch_col(Interpreter::GE, attrId, val, 0, Label);
637 }
638 
639 int
640 NdbInterpretedCode::branch_col_like(const void * val,
641  Uint32 len,
642  Uint32 attrId,
643  Uint32 Label)
644 {
645  return branch_col(Interpreter::LIKE, attrId, val, len, Label);
646 }
647 
648 int
649 NdbInterpretedCode::branch_col_notlike(const void * val,
650  Uint32 len,
651  Uint32 attrId,
652  Uint32 Label)
653 {
654  return branch_col(Interpreter::NOT_LIKE, attrId, val, len, Label);
655 }
656 
657 int
658 NdbInterpretedCode::branch_col_and_mask_eq_mask(const void * mask,
659  Uint32 len,
660  Uint32 attrId,
661  Uint32 label)
662 {
663  return branch_col(Interpreter::AND_EQ_MASK, attrId, mask, 0, Label);
664 }
665 
666 int
667 NdbInterpretedCode::branch_col_and_mask_ne_mask(const void * mask,
668  Uint32 len,
669  Uint32 attrId,
670  Uint32 label)
671 {
672  return branch_col(Interpreter::AND_NE_MASK, attrId, mask, 0, Label);
673 }
674 
675 int
676 NdbInterpretedCode::branch_col_and_mask_eq_zero(const void * mask,
677  Uint32 len,
678  Uint32 attrId,
679  Uint32 label)
680 {
681  return branch_col(Interpreter::AND_EQ_ZERO, attrId, mask, 0, Label);
682 }
683 
684 int
685 NdbInterpretedCode::branch_col_and_mask_ne_zero(const void * mask,
686  Uint32 len,
687  Uint32 attrId,
688  Uint32 label)
689 {
690  return branch_col(Interpreter::AND_NE_ZERO, attrId, mask, 0, Label);
691 }
692 
693 int
694 NdbInterpretedCode::interpret_exit_ok()
695 {
696  return add1(Interpreter::EXIT_OK);
697 }
698 
699 int
700 NdbInterpretedCode::interpret_exit_nok(Uint32 ErrorCode)
701 {
702  return add1((ErrorCode << 16) | Interpreter::EXIT_REFUSE);
703 }
704 
705 int
706 NdbInterpretedCode::interpret_exit_nok()
707 {
708  return add1((626 << 16) | Interpreter::EXIT_REFUSE);
709 }
710 
711 int
712 NdbInterpretedCode::interpret_exit_last_row()
713 {
714  return add1(Interpreter::EXIT_OK_LAST);
715 }
716 
717 int
718 NdbInterpretedCode::add_val(Uint32 attrId, Uint32 aValue)
719 {
720  /* Load attribute into register 6 */
721  int res= 0;
722  if ((res= read_attr(6, attrId) != 0))
723  return res;
724 
725  /* Load constant into register 7 */
726  /* We attempt to use the smallest constant load
727  * instruction
728  */
729  if (aValue < (1 << 16))
730  {
731  if ((res= load_const_u16(7, aValue)) != 0)
732  return res;
733  }
734  else
735  {
736  if ((res= load_const_u32(7, aValue)) != 0)
737  return res;
738  }
739 
740  /* Add registers 6 and 7 -> 7*/
741  if ((res= add_reg(7, 6, 7)) != 0)
742  return res;
743 
744  /* Write back */
745  return write_attr(attrId, 7);
746 }
747 
748 
749 int
750 NdbInterpretedCode::add_val(Uint32 attrId, Uint64 aValue)
751 {
752  /* Load attribute into register 6 */
753  int res= 0;
754  if ((res= read_attr(6, attrId) != 0))
755  return res;
756 
757  /* Load constant into register 7 */
758  /* We attempt to use the smallest constant load
759  * instruction
760  */
761  if ((aValue >> 32) == 0)
762  {
763  if (aValue < (1 << 16))
764  {
765  if ((res= load_const_u16(7, (Uint32)aValue)) != 0)
766  return res;
767  }
768  else
769  {
770  if ((res= load_const_u32(7, (Uint32)aValue)) != 0)
771  return res;
772  }
773  }
774  else
775  if ((res= load_const_u64(7, aValue)) != 0)
776  return res;
777 
778  /* Add registers 6 and 7 -> 7*/
779  if ((res= add_reg(7, 6, 7)) != 0)
780  return res;
781 
782  /* Write back */
783  return write_attr(attrId, 7);
784 }
785 
786 
787 int
788 NdbInterpretedCode::sub_val(Uint32 attrId, Uint32 aValue)
789 {
790  /* Load attribute into register 6 */
791  int res= 0;
792  if ((res= read_attr(6, attrId) != 0))
793  return res;
794 
795  /* Load constant into register 7 */
796  /* We attempt to use the smallest constant load
797  * instruction
798  */
799  if (aValue < (1 << 16))
800  {
801  if ((res= load_const_u16(7, aValue)) != 0)
802  return res;
803  }
804  else
805  {
806  if ((res= load_const_u32(7, aValue)) != 0)
807  return res;
808  }
809 
810  /* Subtract register (R7=R6-R7)*/
811  if ((res= sub_reg(7, 6, 7)) != 0)
812  return res;
813 
814  /* Write back */
815  return write_attr(attrId, 7);
816 }
817 
818 
819 int
820 NdbInterpretedCode::sub_val(Uint32 attrId, Uint64 aValue)
821 {
822  /* Load attribute into register 6 */
823  int res= 0;
824  if ((res= read_attr(6, attrId) != 0))
825  return res;
826 
827  /* Load constant into register 7 */
828  /* We attempt to use the smallest constant load
829  * instruction
830  */
831  if ((aValue >> 32) == 0)
832  {
833  if (aValue < (1 << 16))
834  {
835  if ((res= load_const_u16(7, (Uint32)aValue)) != 0)
836  return res;
837  }
838  else
839  {
840  if ((res= load_const_u32(7, (Uint32)aValue)) != 0)
841  return res;
842  }
843  }
844  else
845  {
846  if ((res= load_const_u64(7, aValue)) != 0)
847  return res;
848  }
849 
850  /* Subtract register (R7=R6-R7)*/
851  if ((res= sub_reg(7, 6, 7)) != 0)
852  return res;
853 
854  /* Write back */
855  return write_attr(attrId, 7);
856 }
857 
858 int
859 NdbInterpretedCode::def_sub(Uint32 SubroutineNumber)
860 {
861  if (SubroutineNumber > MaxSubs)
862  return error(BadSubNumber);
863 
864  if (m_flags & InSubroutineDef)
865  return error(BadState);
866 
867  if (m_number_of_calls == 0)
868  return error(BadState);
869 
870  /* Record where subroutines start */
871  if (m_number_of_subs == 0)
872  m_first_sub_instruction_pos= m_instructions_length;
873 
874  m_number_of_subs++;
875  m_flags|= InSubroutineDef;
876 
877  CodeMetaInfo info;
878 
879  info.type= Subroutine;
880  info.number= SubroutineNumber;
881  info.firstInstrPos=
882  m_instructions_length - m_first_sub_instruction_pos;
883 
884  // Note, no check for whether the label's already defined here.
885  return addMeta(info);
886 }
887 
888 int
889 NdbInterpretedCode::call_sub(Uint32 SubroutineNumber)
890 {
891  if (SubroutineNumber > MaxSubs)
892  return error(BadState);
893 
894  m_number_of_calls ++;
895 
896  return add1(Interpreter::CALL | (SubroutineNumber << 16));
897 }
898 
899 int
901 {
902  if ((m_flags & InSubroutineDef) == 0)
903  return error(BadState);
904 
905  m_flags&= ~(InSubroutineDef);
906 
907  return add1(Interpreter::RETURN);
908 }
909 
910 /* Get a CodeMetaInfo object given a number
911  * Label numbers start from 0. Subroutine numbers start from
912  * the highest label number
913  */
914 int
915 NdbInterpretedCode::getInfo(Uint32 number, CodeMetaInfo &info) const
916 {
917  if (number >= (m_number_of_labels + m_number_of_subs))
918  return -1;
919 
920  Uint32 pos= m_buffer_length
921  - ((number+1) * CODEMETAINFO_WORDS);
922 
923  info.number= (m_buffer[pos + 1] >> 16) & 0xffff;
924  info.type= m_buffer[pos + 1] & 0xffff;
925  info.firstInstrPos= m_buffer[pos];
926 
927  return 0;
928 }
929 
930 /* Update internal NdbError object based on its code */
931 static void
932 update(const NdbError & _err){
933  NdbError & error = (NdbError &) _err;
934  ndberror_struct ndberror = (ndberror_struct)error;
935  ndberror_update(&ndberror);
936  error = NdbError(ndberror);
937 }
938 
939 const NdbDictionary::Table *
941 {
942  return (m_table_impl == NULL) ?
943  NULL :
944  m_table_impl->m_facade;
945 }
946 
947 
948 const NdbError &
950 {
951  /* Set the correct error info before returning to
952  * caller
953  */
954  update(m_error);
955  return m_error;
956 }
957 
958 Uint32
960 {
961  return (m_buffer_length - m_available_length);
962 
963 }
964 
965 
966 int
968 {
969  m_table_impl = src.m_table_impl;
970  m_buffer_length = src.m_buffer_length;
971 
975  if (m_internal_buffer!=NULL)
976  {
977  delete[] m_internal_buffer;
978  m_internal_buffer = NULL;
979  }
980 
981  if (src.m_internal_buffer==NULL)
982  {
983  // External buffer with externaly managed life cycle.
984  m_buffer = src.m_buffer;
985  }
986  else
987  {
988  m_buffer = m_internal_buffer = new Uint32[m_buffer_length];
989  if (unlikely(m_internal_buffer==NULL))
990  {
991  return 4000; // Alllocation failed.
992  }
993  memcpy(m_internal_buffer,
994  src.m_internal_buffer,
995  m_buffer_length*sizeof(Uint32));
996  }
997 
998  m_number_of_labels = src.m_number_of_labels;
999  m_number_of_subs = src.m_number_of_subs;
1000  m_number_of_calls = src.m_number_of_calls;
1001  m_last_meta_pos = src.m_last_meta_pos;
1002  m_instructions_length = src.m_instructions_length;
1003  m_first_sub_instruction_pos = src.m_first_sub_instruction_pos;
1004  m_available_length = src.m_available_length;
1005  m_flags = src.m_flags;
1006  m_error = src.m_error;
1007  return 0;
1008 }
1009 
1010 
1011 /* CodeMetaInfo comparator for qsort
1012  * Sort order is highest numbered sub to lowest,
1013  * then highest numbered label to lowest
1014  * *va < *vb : -1 *va first
1015  * *va == *vb : 0
1016  * *va > *vb : 1 *vb first
1017  */
1018 int
1019 NdbInterpretedCode::compareMetaInfo(const void *va,
1020  const void *vb)
1021 {
1022  Uint32 aWord= *(((Uint32 *) va) + 1); // number || type
1023  Uint32 bWord= *(((Uint32 *) vb) + 1); // number || type
1024  Uint16 aType= aWord & 0xffff;
1025  Uint16 bType= bWord & 0xffff;
1026  const int AFirst= -1;
1027  const int BFirst= 1;
1028 
1029  /* Sort in order (Subs, Labels) */
1030  if (aType != bType)
1031  return (aType == Subroutine)? AFirst : BFirst;
1032 
1033  Uint16 aNumber= (aWord >> 16) & 0xffff;
1034  Uint16 bNumber= (bWord >> 16) & 0xffff;
1035 
1036  /* Sort in reverse order within type, highest number
1037  * first.
1038  */
1039  if (aNumber != bNumber)
1040  return (bNumber > aNumber)? BFirst : AFirst;
1041 
1042  return 0; // Should never happen
1043 }
1044 
1045 
1046 int
1048 {
1049  if (m_instructions_length == 0)
1050  {
1051  /* We will attempt to add a single EXIT_OK instruction
1052  * rather than returning an error.
1053  * This may simplify client code.
1054  */
1055  int res= 0;
1056  if (0 != (res= interpret_exit_ok()))
1057  return -1;
1058  }
1059 
1060  assert (m_buffer != NULL);
1061 
1062  /* Use label and subroutine meta-info at
1063  * the end of the code buffer to determine
1064  * the correct offsets for label branches and
1065  * subroutine calls
1066  */
1067  Uint32 numOfMetaInfos= m_number_of_labels +
1068  m_number_of_subs;
1069  Uint32 sizeOfMetaInfo= numOfMetaInfos * CODEMETAINFO_WORDS;
1070  Uint32 startOfMetaInfo= m_buffer_length - sizeOfMetaInfo;
1071 
1072  /* Sort different types of meta info into order in place */
1073  qsort( &m_buffer[ startOfMetaInfo ],
1074  numOfMetaInfos,
1075  CODEMETAINFO_WORDS << 2,
1076  &compareMetaInfo);
1077 
1078  /* Loop over instructions, patching up branches
1079  * and calls
1080  */
1081  Uint32 *ip= m_buffer;
1082  Uint32* nextIp= ip;
1083  Uint32 const* firstInstruction= m_buffer;
1084  Uint32 const* endOfProgram= m_buffer + m_instructions_length;
1085 
1086  while (ip < endOfProgram)
1087  {
1089  nextIp= Interpreter::getInstructionPreProcessingInfo(ip,
1090  action);
1091  if (nextIp == NULL)
1092  {
1093  m_error.code= 4516; // Illegal instruction in interpreted program
1094  return -1;
1095  }
1096 
1097  switch (action) {
1098  case Interpreter::NONE:
1099  /* Normal instruction, skip over */
1100  break;
1101  case Interpreter::LABEL_ADDRESS_REPLACEMENT:
1102  {
1103  /* Have a branch needing a relative label address replacement */
1104  Uint32 label= Interpreter::getLabel(*ip);
1105 
1106  if (label > m_number_of_labels)
1107  {
1108  m_error.code= 4517; // Bad label in branch instruction
1109  return -1;
1110  }
1111 
1112  CodeMetaInfo info;
1113  if (getInfo(label, info) != 0)
1114  {
1115  m_error.code= 4222; // Label was not found, internal error
1116  return -1;
1117  }
1118 
1119  assert(info.type == Label);
1120 
1121  Uint32 currOffset = Uint32(ip - firstInstruction);
1122  Uint32 labelOffset= info.firstInstrPos;
1123 
1124  if (labelOffset >= m_instructions_length)
1125  {
1126  m_error.code= 4517; // Bad label in branch instruction
1127  return -1;
1128  }
1129 
1130  /* Remove the label info */
1131  Uint32 patchedInstruction= (*ip) & 0xffff;
1132 
1133  if (labelOffset < currOffset)
1134  /* Backwards branch */
1135  patchedInstruction |= (((currOffset - labelOffset) << 16) |
1136  ((Uint32) 1 << 31));
1137  else
1138  /* Forwards branch */
1139  patchedInstruction |= ((labelOffset - currOffset) <<16);
1140 
1141  *ip= patchedInstruction;
1142  break;
1143  }
1144  case Interpreter::SUB_ADDRESS_REPLACEMENT:
1145  {
1146  /* Have a call to a subtoutine that needs to become
1147  * an offset within the subroutines section
1148  */
1149  Uint32 subroutine= Interpreter::getLabel(*ip);
1150 
1151  if (subroutine > m_number_of_subs)
1152  {
1153  m_error.code= 4520; // Call to undefined subroutine
1154  return -1;
1155  }
1156 
1157  CodeMetaInfo info;
1158  if (getInfo(m_number_of_labels + subroutine, info) != 0)
1159  {
1160  m_error.code= 4521; // Call to undefined subroutine, internal error
1161  return -1;
1162  }
1163 
1164  assert(info.type == Subroutine);
1165 
1166  Uint32 subOffset= info.firstInstrPos;
1167 
1168  if (subOffset > (m_instructions_length -
1169  m_first_sub_instruction_pos))
1170  {
1171  m_error.code= 4521; // Call to undefined subroutine, internal error
1172  return -1;
1173  }
1174 
1175  /* Replace the label in the call with the subroutine
1176  * offset
1177  */
1178  Uint32 patchedInstruction= (*ip) & 0xffff;
1179  patchedInstruction |= subOffset << 16;
1180  *ip= patchedInstruction;
1181 
1182  break;
1183  }
1184  default:
1185  m_error.code= 4516; // Illegal instruction in interpreted program
1186  return -1;
1187  }
1188 
1189  ip= nextIp;
1190  }
1191 
1192  /* Code has been patched-up */
1193  m_flags |= Finalised;
1194 
1195  return 0;
1196 }