From 891f7029457c5135c365ec32c06e7750abaceeab Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Mon, 15 Apr 2013 11:50:16 +0200 Subject: Fix compilation with built-in v4vm JS engine Change-Id: Ieda9267e296acf6392a5461f4cfb9233a7a409a0 Reviewed-by: Lars Knoll --- src/qml/qml/v4vm/qv4object_p.h | 417 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 417 insertions(+) create mode 100644 src/qml/qml/v4vm/qv4object_p.h (limited to 'src/qml/qml/v4vm/qv4object_p.h') diff --git a/src/qml/qml/v4vm/qv4object_p.h b/src/qml/qml/v4vm/qv4object_p.h new file mode 100644 index 0000000000..4039eb6da7 --- /dev/null +++ b/src/qml/qml/v4vm/qv4object_p.h @@ -0,0 +1,417 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the V4VM module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#ifndef QMLJS_OBJECTS_H +#define QMLJS_OBJECTS_H + +#include "qv4global_p.h" +#include "qv4runtime_p.h" +#include "qv4engine_p.h" +#include "qv4context_p.h" +#include "qv4sparsearray_p.h" +#include "qv4string_p.h" +#include "qv4codegen_p.h" +#include "qv4isel_p.h" +#include "qv4managed_p.h" +#include "qv4property_p.h" +#include "qv4internalclass_p.h" +#include "qv4objectiterator_p.h" + +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +namespace QQmlJS { +namespace VM { + +struct Value; +struct Function; +struct Lookup; +struct Object; +struct ObjectIterator; +struct BooleanObject; +struct NumberObject; +struct StringObject; +struct ArrayObject; +struct DateObject; +struct FunctionObject; +struct RegExpObject; +struct ErrorObject; +struct ArgumentsObject; +struct ExecutionContext; +struct CallContext; +struct ExecutionEngine; +class MemoryManager; + +struct ObjectPrototype; +struct StringPrototype; +struct NumberPrototype; +struct BooleanPrototype; +struct ArrayPrototype; +struct FunctionPrototype; +struct DatePrototype; +struct RegExpPrototype; +struct ErrorPrototype; +struct EvalErrorPrototype; +struct RangeErrorPrototype; +struct ReferenceErrorPrototype; +struct SyntaxErrorPrototype; +struct TypeErrorPrototype; +struct URIErrorPrototype; + + +struct Q_V4_EXPORT Object: Managed { + + class ExternalResource { + public: + virtual ~ExternalResource() {} + }; + + Object *prototype; + InternalClass *internalClass; + uint memberDataAlloc; + Property *memberData; + + union { + uint arrayFreeList; + uint arrayOffset; + }; + uint arrayDataLen; + uint arrayAlloc; + PropertyAttributes *arrayAttributes; + Property *arrayData; + SparseArray *sparseArray; + ExternalResource *externalResource; + + enum { + InlinePropertySize = 4 + }; + Property inlineProperties[InlinePropertySize]; + + Object(ExecutionEngine *engine); + Object(ExecutionContext *context); + ~Object(); + + Property *__getOwnProperty__(String *name, PropertyAttributes *attrs = 0); + Property *__getOwnProperty__(uint index, PropertyAttributes *attrs = 0); + + Property *__getPropertyDescriptor__(String *name, PropertyAttributes *attrs = 0) const; + Property *__getPropertyDescriptor__(uint index, PropertyAttributes *attrs = 0) const; + + bool __hasProperty__(String *name) const { + return __getPropertyDescriptor__(name); + } + bool __hasProperty__(uint index) const { + return __getPropertyDescriptor__(index); + } + + bool __defineOwnProperty__(ExecutionContext *ctx, Property *current, String *member, const Property &p, PropertyAttributes attrs); + bool __defineOwnProperty__(ExecutionContext *ctx, String *name, const Property &p, PropertyAttributes attrs); + bool __defineOwnProperty__(ExecutionContext *ctx, uint index, const Property &p, PropertyAttributes attrs); + bool __defineOwnProperty__(ExecutionContext *ctx, const QString &name, const Property &p, PropertyAttributes attrs); + + // + // helpers + // + void put(ExecutionContext *ctx, const QString &name, const Value &value); + + static Value getValue(const Value &thisObject, ExecutionContext *ctx, const Property *p, PropertyAttributes attrs); + Value getValue(ExecutionContext *ctx, const Property *p, PropertyAttributes attrs) const { + return getValue(Value::fromObject(const_cast(this)), ctx, p, attrs); + } + + void putValue(ExecutionContext *ctx, Property *pd, PropertyAttributes attrs, const Value &value); + + void inplaceBinOp(ExecutionContext *ctx, BinOp op, String *name, const Value &rhs); + void inplaceBinOp(ExecutionContext *ctx, BinOp op, const Value &index, const Value &rhs); + + /* The spec default: Writable: true, Enumerable: false, Configurable: true */ + void defineDefaultProperty(String *name, Value value); + void defineDefaultProperty(ExecutionContext *context, const QString &name, Value value); + void defineDefaultProperty(ExecutionContext *context, const QString &name, Value (*code)(SimpleCallContext *), int count = 0); + /* Fixed: Writable: false, Enumerable: false, Configurable: false */ + void defineReadonlyProperty(ExecutionEngine *engine, const QString &name, Value value); + void defineReadonlyProperty(String *name, Value value); + + Property *insertMember(String *s, PropertyAttributes attributes); + + // Array handling + + uint allocArrayValue() { + uint idx = arrayFreeList; + if (arrayAlloc <= arrayFreeList) + arrayReserve(arrayAlloc + 1); + arrayFreeList = arrayData[arrayFreeList].value.uint_32; + if (arrayAttributes) + arrayAttributes[idx].setType(PropertyAttributes::Data); + return idx; + } + + uint allocArrayValue(Value v) { + uint idx = allocArrayValue(); + Property *pd = &arrayData[idx]; + pd->value = v; + return idx; + } + void freeArrayValue(int idx) { + Property &pd = arrayData[idx]; + pd.value.tag = Value::_Deleted_Type; + pd.value.int_32 = arrayFreeList; + arrayFreeList = idx; + if (arrayAttributes) + arrayAttributes[idx].clear(); + } + + void getArrayHeadRoom() { + assert(!sparseArray && !arrayOffset); + arrayOffset = qMax(arrayDataLen >> 2, (uint)16); + Property *newArray = new Property[arrayOffset + arrayAlloc]; + memcpy(newArray + arrayOffset, arrayData, arrayDataLen*sizeof(Property)); + delete [] arrayData; + arrayData = newArray + arrayOffset; + if (arrayAttributes) { + PropertyAttributes *newAttrs = new PropertyAttributes[arrayOffset + arrayAlloc]; + memcpy(newAttrs + arrayOffset, arrayAttributes, arrayDataLen*sizeof(PropertyAttributes)); + delete [] arrayAttributes; + arrayAttributes = newAttrs + arrayOffset; + } + } + +public: + void copyArrayData(Object *other); + void initSparse(); + + uint arrayLength() const; + bool setArrayLength(uint newLen); + + void setArrayLengthUnchecked(uint l); + + Property *arrayInsert(uint index, PropertyAttributes attributes = Attr_Data) { + + Property *pd; + if (!sparseArray && (index < 0x1000 || index < arrayDataLen + (arrayDataLen >> 2))) { + if (index >= arrayAlloc) + arrayReserve(index + 1); + if (index >= arrayDataLen) { + ensureArrayAttributes(); + for (uint i = arrayDataLen; i < index; ++i) + arrayAttributes[i].clear(); + arrayDataLen = index + 1; + } + pd = arrayData + index; + } else { + initSparse(); + SparseArrayNode *n = sparseArray->insert(index); + if (n->value == UINT_MAX) + n->value = allocArrayValue(); + pd = arrayData + n->value; + } + if (index >= arrayLength()) + setArrayLengthUnchecked(index + 1); + if (arrayAttributes || attributes != Attr_Data) { + if (!arrayAttributes) + ensureArrayAttributes(); + attributes.resolve(); + arrayAttributes[pd - arrayData] = attributes; + } + return pd; + } + + void arraySet(uint index, const Property *pd) { + *arrayInsert(index) = *pd; + } + + void arraySet(uint index, Value value) { + Property *pd = arrayInsert(index); + pd->value = value; + } + + uint propertyIndexFromArrayIndex(uint index) const + { + if (!sparseArray) { + if (index >= arrayDataLen) + return UINT_MAX; + return index; + } else { + SparseArrayNode *n = sparseArray->findNode(index); + if (!n) + return UINT_MAX; + return n->value; + } + } + + Property *arrayAt(uint index) const { + uint pidx = propertyIndexFromArrayIndex(index); + if (pidx == UINT_MAX) + return 0; + return arrayData + pidx; + } + + Property *nonSparseArrayAt(uint index) const { + if (sparseArray) + return 0; + if (index >= arrayDataLen) + return 0; + return arrayData + index; + } + + void markArrayObjects() const; + + void push_back(Value v) { + uint idx = arrayLength(); + if (!sparseArray) { + if (idx >= arrayAlloc) + arrayReserve(idx + 1); + arrayData[idx].value = v; + arrayDataLen = idx + 1; + } else { + uint idx = allocArrayValue(v); + sparseArray->push_back(idx, arrayLength()); + } + setArrayLengthUnchecked(idx + 1); + } + + SparseArrayNode *sparseArrayBegin() { return sparseArray ? sparseArray->begin() : 0; } + SparseArrayNode *sparseArrayEnd() { return sparseArray ? sparseArray->end() : 0; } + + void arrayConcat(const ArrayObject *other); + void arraySort(ExecutionContext *context, Object *thisObject, const Value &comparefn, uint arrayDataLen); + Value arrayIndexOf(Value v, uint fromIndex, uint arrayDataLen, ExecutionContext *ctx, Object *o); + + void arrayReserve(uint n); + void ensureArrayAttributes(); + + using Managed::get; + using Managed::getIndexed; + using Managed::put; + using Managed::putIndexed; + using Managed::deleteProperty; + using Managed::deleteIndexedProperty; +protected: + static const ManagedVTable static_vtbl; + static void destroy(Managed *that); + static void markObjects(Managed *that); + static Value get(Managed *m, ExecutionContext *ctx, String *name, bool *hasProperty); + static Value getIndexed(Managed *m, ExecutionContext *ctx, uint index, bool *hasProperty); + static void put(Managed *m, ExecutionContext *ctx, String *name, const Value &value); + static void putIndexed(Managed *m, ExecutionContext *ctx, uint index, const Value &value); + static PropertyAttributes query(Managed *m, ExecutionContext *ctx, String *name); + static PropertyAttributes queryIndexed(Managed *m, ExecutionContext *ctx, uint index); + static bool deleteProperty(Managed *m, ExecutionContext *ctx, String *name); + static bool deleteIndexedProperty(Managed *m, ExecutionContext *ctx, uint index); + +private: + Value internalGet(ExecutionContext *ctx, String *name, bool *hasProperty); + Value internalGetIndexed(ExecutionContext *ctx, uint index, bool *hasProperty); + void internalPut(ExecutionContext *ctx, String *name, const Value &value); + void internalPutIndexed(ExecutionContext *ctx, uint index, const Value &value); + bool internalDeleteProperty(ExecutionContext *ctx, String *name); + bool internalDeleteIndexedProperty(ExecutionContext *ctx, uint index); + + friend struct ObjectIterator; + friend struct ObjectPrototype; +}; + +struct ForEachIteratorObject: Object { + ObjectIterator it; + ForEachIteratorObject(ExecutionContext *ctx, Object *o) + : Object(ctx->engine), it(ctx, o, ObjectIterator::EnumberableOnly|ObjectIterator::WithProtoChain) { + vtbl = &static_vtbl; + type = Type_ForeachIteratorObject; + } + + Value nextPropertyName() { return it.nextPropertyNameAsString(); } + +protected: + static const ManagedVTable static_vtbl; + static void markObjects(Managed *that); +}; + +struct BooleanObject: Object { + Value value; + BooleanObject(ExecutionEngine *engine, const Value &value): Object(engine), value(value) { type = Type_BooleanObject; } +}; + +struct NumberObject: Object { + Value value; + NumberObject(ExecutionEngine *engine, const Value &value): Object(engine), value(value) { type = Type_NumberObject; } +}; + +struct ArrayObject: Object { + enum { + LengthPropertyIndex = 0 + }; + + ArrayObject(ExecutionContext *ctx) : Object(ctx->engine) { init(ctx); } + void init(ExecutionContext *context); +}; + +inline uint Object::arrayLength() const +{ + if (isArrayObject()) { + // length is always the first property of an array + Value v = memberData[ArrayObject::LengthPropertyIndex].value; + if (v.isInteger()) + return v.integerValue(); + return Value::toUInt32(v.doubleValue()); + } + return 0; +} + +inline void Object::setArrayLengthUnchecked(uint l) +{ + if (isArrayObject()) { + // length is always the first property of an array + Property &lengthProperty = memberData[ArrayObject::LengthPropertyIndex]; + lengthProperty.value = Value::fromUInt32(l); + } +} + + +} // namespace VM +} // namespace QQmlJS + +QT_END_NAMESPACE + +#endif // QMLJS_OBJECTS_H -- cgit v1.2.3