Qt 4.8
qscriptcontextinfo.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the QtScript module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL-ONLY$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser
11 ** General Public License version 2.1 as published by the Free Software
12 ** Foundation and appearing in the file LICENSE.LGPL included in the
13 ** packaging of this file. Please review the following information to
14 ** ensure the GNU Lesser General Public License version 2.1 requirements
15 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
16 **
17 ** If you have questions regarding the use of this file, please contact
18 ** us via http://www.qt-project.org/.
19 **
20 ** $QT_END_LICENSE$
21 **
22 ****************************************************************************/
23 
24 #include "config.h"
25 #include "qscriptcontextinfo.h"
26 
27 #include "qscriptcontext_p.h"
28 #include "qscriptengine.h"
29 #include "qscriptengine_p.h"
30 #include "../bridge/qscriptqobject_p.h"
31 #include <QtCore/qdatastream.h>
32 #include <QtCore/qmetaobject.h>
33 #include "CodeBlock.h"
34 #include "JSFunction.h"
35 #if ENABLE(JIT)
36 #include "MacroAssemblerCodeRef.h"
37 #endif
38 
40 
91 {
93 public:
97 
102 
105 
109 
111 
113 
115 };
116 
121 {
122  ref = 0;
124  functionMetaIndex = -1;
127  scriptId = -1;
128  lineNumber = -1;
129  columnNumber = -1;
130 }
131 
136 {
137  Q_ASSERT(context);
138  ref = 0;
140  functionMetaIndex = -1;
143  scriptId = -1;
144  lineNumber = -1;
145  columnNumber = -1;
146 
148 
149  // Get the line number:
150 
151  //We need to know the context directly up in the backtrace, in order to get the line number, and adjust the global context
152  JSC::CallFrame *rewindContext = QScriptEnginePrivate::get(context->engine())->currentFrame;
153  if (QScriptEnginePrivate::contextForFrame(rewindContext) == context) { //top context
154  frame = rewindContext; //for retreiving the global context's "fake" frame
155  // An agent might have provided the line number.
157  } else {
158  // rewind the stack from the top in order to find the frame from the caller where the returnPC is stored
159  while (rewindContext && QScriptEnginePrivate::contextForFrame(rewindContext->callerFrame()->removeHostCallFrameFlag()) != context)
160  rewindContext = rewindContext->callerFrame()->removeHostCallFrameFlag();
161  if (rewindContext) {
162  frame = rewindContext->callerFrame()->removeHostCallFrameFlag(); //for retreiving the global context's "fake" frame
163 
164  JSC::Instruction *returnPC = rewindContext->returnPC();
165  JSC::CodeBlock *codeBlock = frame->codeBlock();
166  if (returnPC && codeBlock && QScriptEnginePrivate::hasValidCodeBlockRegister(frame)) {
167 #if ENABLE(JIT)
168  JSC::JITCode code = codeBlock->getJITCode();
169  uintptr_t jitOffset = reinterpret_cast<uintptr_t>(JSC::ReturnAddressPtr(returnPC).value()) - reinterpret_cast<uintptr_t>(code.addressForCall().executableAddress());
170  // We can only use the JIT code offset if it's smaller than the JIT size;
171  // otherwise calling getBytecodeIndex() is meaningless.
172  if (jitOffset < code.size()) {
173  unsigned bytecodeOffset = codeBlock->getBytecodeIndex(frame, JSC::ReturnAddressPtr(returnPC));
174 #else
175  unsigned bytecodeOffset = returnPC - codeBlock->instructions().begin();
176 #endif
177  bytecodeOffset--; //because returnPC is on the next instruction. We want the current one
178  lineNumber = codeBlock->lineNumberForBytecodeOffset(const_cast<JSC::ExecState *>(frame), bytecodeOffset);
179 #if ENABLE(JIT)
180  }
181 #endif
182  }
183  }
184  }
185 
186  // Get the filename and the scriptId:
187  JSC::CodeBlock *codeBlock = frame->codeBlock();
188  if (codeBlock && QScriptEnginePrivate::hasValidCodeBlockRegister(frame)) {
189  JSC::SourceProvider *source = codeBlock->source();
190  scriptId = source->asID();
191  fileName = source->url();
192  }
193 
194  // Get the others information:
195  JSC::JSObject *callee = frame->callee();
196  if (callee && callee->inherits(&JSC::InternalFunction::info))
197  functionName = JSC::asInternalFunction(callee)->name(frame);
198  if (callee && callee->inherits(&JSC::JSFunction::info)
199  && !JSC::asFunction(callee)->isHostFunction()) {
201  JSC::FunctionExecutable *body = JSC::asFunction(callee)->jsExecutable();
202  functionStartLineNumber = body->lineNo();
203  functionEndLineNumber = body->lastLine();
204  for (size_t i = 0; i < body->parameterCount(); ++i)
205  parameterNames.append(body->parameterName(i));
206  // ### get the function name from the AST
207  } else if (callee && callee->inherits(&QScript::QtFunction::info)) {
209  // ### the slot can be overloaded -- need to get the particular overload from the context
210  functionMetaIndex = static_cast<QScript::QtFunction*>(callee)->initialIndex();
211  const QMetaObject *meta = static_cast<QScript::QtFunction*>(callee)->metaObject();
212  if (meta != 0) {
213  QMetaMethod method = meta->method(functionMetaIndex);
214  QList<QByteArray> formals = method.parameterNames();
215  for (int i = 0; i < formals.count(); ++i)
216  parameterNames.append(QLatin1String(formals.at(i)));
217  }
218  }
219  else if (callee && callee->inherits(&QScript::QtPropertyFunction::info)) {
221  functionMetaIndex = static_cast<QScript::QtPropertyFunction*>(callee)->propertyIndex();
222  }
223 }
224 
229 {
230 }
231 
241  : d_ptr(0)
242 {
243  if (context) {
244  d_ptr = new QScriptContextInfoPrivate(context);
245  d_ptr->q_ptr = this;
246  }
247 }
248 
253  : d_ptr(other.d_ptr)
254 {
255 }
256 
263  : d_ptr(0)
264 {
265 }
266 
271 {
272 }
273 
279 {
280  d_ptr = other.d_ptr;
281  return *this;
282 }
283 
292 {
293  Q_D(const QScriptContextInfo);
294  if (!d)
295  return -1;
296  return d->scriptId;
297 }
298 
309 {
310  Q_D(const QScriptContextInfo);
311  if (!d)
312  return QString();
313  return d->fileName;
314 }
315 
326 {
327  Q_D(const QScriptContextInfo);
328  if (!d)
329  return -1;
330  return d->lineNumber;
331 }
332 
337 {
338  Q_D(const QScriptContextInfo);
339  if (!d)
340  return -1;
341  return d->columnNumber;
342 }
343 
356 {
357  Q_D(const QScriptContextInfo);
358  if (!d)
359  return QString();
360  return d->functionName;
361 }
362 
369 {
370  Q_D(const QScriptContextInfo);
371  if (!d)
372  return NativeFunction;
373  return d->functionType;
374 }
375 
386 {
387  Q_D(const QScriptContextInfo);
388  if (!d)
389  return -1;
390  return d->functionStartLineNumber;
391 }
392 
403 {
404  Q_D(const QScriptContextInfo);
405  if (!d)
406  return -1;
407  return d->functionEndLineNumber;
408 }
409 
417 {
418  Q_D(const QScriptContextInfo);
419  if (!d)
420  return QStringList();
421  return d->parameterNames;
422 }
423 
438 {
439  Q_D(const QScriptContextInfo);
440  if (!d)
441  return -1;
442  return d->functionMetaIndex;
443 }
444 
450 {
451  Q_D(const QScriptContextInfo);
452  return (d == 0);
453 }
454 
460 {
461  Q_D(const QScriptContextInfo);
462  const QScriptContextInfoPrivate *od = other.d_func();
463  if (d == od)
464  return true;
465  if (!d || !od)
466  return false;
467  return ((d->scriptId == od->scriptId)
468  && (d->lineNumber == od->lineNumber)
469  && (d->columnNumber == od->columnNumber)
470  && (d->fileName == od->fileName)
471  && (d->functionName == od->functionName)
472  && (d->functionType == od->functionType)
473  && (d->functionStartLineNumber == od->functionStartLineNumber)
474  && (d->functionEndLineNumber == od->functionEndLineNumber)
475  && (d->functionMetaIndex == od->functionMetaIndex)
476  && (d->parameterNames == od->parameterNames));
477 }
478 
484 {
485  return !(*this == other);
486 }
487 
488 #ifndef QT_NO_DATASTREAM
489 
500 {
501  out << info.scriptId();
502  out << (qint32)info.lineNumber();
503  out << (qint32)info.columnNumber();
504 
505  out << (quint32)info.functionType();
506  out << (qint32)info.functionStartLineNumber();
507  out << (qint32)info.functionEndLineNumber();
508  out << (qint32)info.functionMetaIndex();
509 
510  out << info.fileName();
511  out << info.functionName();
512  out << info.functionParameterNames();
513 
514  return out;
515 }
516 
529 {
530  if (!info.d_ptr) {
531  info.d_ptr = new QScriptContextInfoPrivate();
532  }
533 
534  in >> info.d_ptr->scriptId;
535 
536  qint32 line;
537  in >> line;
538  info.d_ptr->lineNumber = line;
539 
540  qint32 column;
541  in >> column;
542  info.d_ptr->columnNumber = column;
543 
544  quint32 ftype;
545  in >> ftype;
547 
548  qint32 startLine;
549  in >> startLine;
550  info.d_ptr->functionStartLineNumber = startLine;
551 
552  qint32 endLine;
553  in >> endLine;
554  info.d_ptr->functionEndLineNumber = endLine;
555 
556  qint32 metaIndex;
557  in >> metaIndex;
558  info.d_ptr->functionMetaIndex = metaIndex;
559 
560  in >> info.d_ptr->fileName;
561  in >> info.d_ptr->functionName;
562  in >> info.d_ptr->parameterNames;
563 
564  return in;
565 }
566 #endif
567 
double d
Definition: qnumeric_p.h:62
The QScriptContext class represents a Qt Script function invocation.
The QMetaObject class contains meta-information about Qt objects.
Definition: qobjectdefs.h:304
static JSC::ExecState * frameForContext(QScriptContext *context)
QScriptEnginePrivate * scriptEngineFromExec(const JSC::ExecState *exec)
static mach_timebase_info_data_t info
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
int qint32
Definition: qglobal.h:937
int functionEndLineNumber() const
Returns the line number where the definition of the called function ends, or -1 if the line number is...
static const JSC::ClassInfo info
static QScriptEnginePrivate * get(QScriptEngine *q)
QT_DEPRECATED int columnNumber() const
int count(const T &t) const
Returns the number of occurrences of value in the list.
Definition: qlist.h:891
QScriptEngine * engine() const
Returns the QScriptEngine that this QScriptContext belongs to.
bool isNull() const
Returns true if this QScriptContextInfo is null, i.e.
The QString class provides a Unicode character string.
Definition: qstring.h:83
int functionMetaIndex() const
Returns the meta index of the called function, or -1 if the meta index is not available.
#define Q_ASSERT(cond)
Definition: qglobal.h:1823
#define Q_D(Class)
Definition: qglobal.h:2482
FunctionType
This enum specifies the type of function being called.
QScriptContextInfo & operator=(const QScriptContextInfo &other)
Assigns the other info to this QScriptContextInfo, and returns a reference to this QScriptContextInfo...
QString fileName() const
Returns the name of the file where the code being executed was defined, if available; otherwise retur...
QExplicitlySharedDataPointer< QScriptContextInfoPrivate > d_ptr
void append(const T &t)
Inserts value at the end of the list.
Definition: qlist.h:507
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
friend Q_SCRIPT_EXPORT QDataStream & operator<<(QDataStream &, const QScriptContextInfo &)
Writes the given info to the specified stream.
QList< QByteArray > parameterNames() const
Returns a list of parameter names.
int lineNumber() const
Returns the line number corresponding to the statement being executed, or -1 if the line number is no...
static QScriptContext * contextForFrame(JSC::ExecState *frame)
QScriptContextInfo()
Constructs a null QScriptContextInfo.
const T & at(int i) const
Returns the item at index position i in the list.
Definition: qlist.h:468
The QStringList class provides a list of strings.
Definition: qstringlist.h:66
The QLatin1String class provides a thin wrapper around an US-ASCII/Latin-1 encoded string literal...
Definition: qstring.h:654
__int64 qint64
Definition: qglobal.h:942
#define Q_SCRIPT_EXPORT
Definition: qglobal.h:1460
int functionStartLineNumber() const
Returns the line number where the definition of the called function starts, or -1 if the line number ...
QScriptContextInfo::FunctionType functionType
bool operator==(const QScriptContextInfo &other) const
Returns true if this QScriptContextInfo is equal to the other info, otherwise returns false...
~QScriptContextInfo()
Destroys the QScriptContextInfo.
The QScriptContextInfo class provides additional information about a QScriptContext.
#define Q_DECLARE_PUBLIC(Class)
Definition: qglobal.h:2477
friend Q_SCRIPT_EXPORT QDataStream & operator>>(QDataStream &, QScriptContextInfo &)
Reads a QScriptContextInfo from the specified stream into the given info.
QStringList functionParameterNames() const
Returns the names of the formal parameters of the called function, or an empty QStringList if the par...
unsigned int quint32
Definition: qglobal.h:938
FunctionType functionType() const
Returns the type of the called function.
QMetaMethod method(int index) const
Returns the meta-data for the method with the given index.
The QDataStream class provides serialization of binary data to a QIODevice.
Definition: qdatastream.h:71
qint64 scriptId() const
Returns the ID of the script where the code being executed was defined, or -1 if the ID is not availa...
ExecState CallFrame
bool operator!=(const QScriptContextInfo &other) const
Returns true if this QScriptContextInfo is not equal to the other info, otherwise returns false...
static const JSC::ClassInfo info
The QMetaMethod class provides meta-data about a member function.
Definition: qmetaobject.h:56
static bool hasValidCodeBlockRegister(JSC::ExecState *frame)
QString functionName() const
Returns the name of the called function, or an empty string if the name is not available.