diff options
-rw-r--r-- | llvm_runtime.cpp | 2 | ||||
-rw-r--r-- | main.cpp | 4 | ||||
-rw-r--r-- | moth/qv4vme_moth.cpp | 8 | ||||
-rw-r--r-- | qmljs_engine.cpp | 4 | ||||
-rw-r--r-- | qmljs_engine.h | 5 | ||||
-rw-r--r-- | qmljs_environment.cpp | 165 | ||||
-rw-r--r-- | qmljs_environment.h | 53 | ||||
-rw-r--r-- | qmljs_objects.cpp | 12 | ||||
-rw-r--r-- | qmljs_objects.h | 27 | ||||
-rw-r--r-- | qmljs_runtime.cpp | 4 | ||||
-rw-r--r-- | qv4ecmaobjects.cpp | 135 | ||||
-rw-r--r-- | qv4isel_masm.cpp | 6 |
12 files changed, 279 insertions, 146 deletions
diff --git a/llvm_runtime.cpp b/llvm_runtime.cpp index b911ad4880..553f2fd1ac 100644 --- a/llvm_runtime.cpp +++ b/llvm_runtime.cpp @@ -55,7 +55,7 @@ void __qmljs_llvm_return(ExecutionContext *ctx, Value *result) Value *__qmljs_llvm_get_argument(ExecutionContext *ctx, int index) { - return &ctx->arguments[index]; + return &ctx->variableEnvironment->arguments[index]; } void __qmljs_llvm_init_undefined(Value *result) @@ -71,7 +71,7 @@ struct Print: FunctionObject virtual void call(ExecutionContext *ctx) { - for (unsigned int i = 0; i < ctx->argumentCount; ++i) { + for (unsigned int i = 0; i < ctx->argumentCount(); ++i) { String *s = ctx->argument(i).toString(ctx); if (i) std::cout << ' '; @@ -89,7 +89,7 @@ struct TestHarnessError: FunctionObject { errorOccurred = true; - for (unsigned int i = 0; i < ctx->argumentCount; ++i) { + for (unsigned int i = 0; i < ctx->argumentCount(); ++i) { String *s = ctx->argument(i).toString(ctx); if (i) std::cerr << ' '; diff --git a/moth/qv4vme_moth.cpp b/moth/qv4vme_moth.cpp index c058002aa2..30a5d3c3a6 100644 --- a/moth/qv4vme_moth.cpp +++ b/moth/qv4vme_moth.cpp @@ -68,11 +68,11 @@ static inline VM::Value *tempValue(QQmlJS::VM::ExecutionContext *context, QVecto if (index < 0) { const int arg = -index - 1; - return context->arguments + arg; - } else if (index < (int) context->varCount) { - return context->locals + index; + return context->variableEnvironment->arguments + arg; + } else if (index < (int) context->variableEnvironment->varCount) { + return context->variableEnvironment->locals + index; } else { - int off = index - context->varCount; + int off = index - context->variableEnvironment->varCount; return stack.data() + off; } } diff --git a/qmljs_engine.cpp b/qmljs_engine.cpp index 9229dbd9a2..8097639e54 100644 --- a/qmljs_engine.cpp +++ b/qmljs_engine.cpp @@ -139,7 +139,7 @@ ExecutionEngine::ExecutionEngine() // VM::Object *glo = newObject(/*rootContext*/); globalObject = Value::fromObject(glo); - rootContext->activation = glo; + rootContext->variableEnvironment->activation = glo; glo->__put__(rootContext, identifier(QStringLiteral("Object")), objectCtor); glo->__put__(rootContext, identifier(QStringLiteral("String")), stringCtor); @@ -324,7 +324,7 @@ Object *ExecutionEngine::newMathObject(ExecutionContext *ctx) return object; } -Object *ExecutionEngine::newActivationObject(ExecutionContext *ctx) +Object *ExecutionEngine::newActivationObject(DeclarativeEnvironment *ctx) { return new ActivationObject(ctx); } diff --git a/qmljs_engine.h b/qmljs_engine.h index ed4b0d4a16..f111979f0d 100644 --- a/qmljs_engine.h +++ b/qmljs_engine.h @@ -42,6 +42,7 @@ #define QMLJS_ENGINE_H #include <qmljs_objects.h> +#include <qmljs_environment.h> #include <setjmp.h> namespace QQmlJS { @@ -81,7 +82,9 @@ struct URIErrorPrototype; struct ExecutionEngine { + ExecutionContext *current; ExecutionContext *rootContext; + Value globalObject; Value objectCtor; @@ -170,7 +173,7 @@ struct ExecutionEngine Object *newErrorObject(const Value &value); Object *newMathObject(ExecutionContext *ctx); - Object *newActivationObject(ExecutionContext *ctx); + Object *newActivationObject(DeclarativeEnvironment *ctx); Object *newForEachIteratorObject(Object *o); }; diff --git a/qmljs_environment.cpp b/qmljs_environment.cpp index 550d619fe1..338006474e 100644 --- a/qmljs_environment.cpp +++ b/qmljs_environment.cpp @@ -45,25 +45,134 @@ namespace QQmlJS { namespace VM { -void ExecutionContext::init(ExecutionEngine *eng) +DeclarativeEnvironment::DeclarativeEnvironment(ExecutionEngine *e) { - engine = eng; - parent = 0; + engine = e; + outer = 0; arguments = 0; argumentCount = 0; locals = 0; activation = 0; - thisObject = Value::nullValue(); - result = Value::undefinedValue(); formals = 0; formalCount = 0; vars = 0; varCount = 0; } +DeclarativeEnvironment::DeclarativeEnvironment(FunctionObject *f, Value *args, uint argc) +{ + outer = f->scope; + engine = outer->engine; + + if (f->needsActivation) + activation = engine->newActivationObject(this); + else + activation = 0; + + formals = f->formalParameterList; + formalCount = f->formalParameterCount; + arguments = args; + argumentCount = argc; + if (f->needsActivation || argc < formalCount){ + arguments = new Value[qMax(argc, formalCount)]; + if (argc) + std::copy(args, args + argc, arguments); + if (argc < formalCount) + std::fill(arguments + argc, arguments + formalCount, Value::undefinedValue()); + } + vars = f->varList; + varCount = f->varCount; + locals = varCount ? new Value[varCount] : 0; + if (varCount) + std::fill(locals, locals + varCount, Value::undefinedValue()); +} + +bool DeclarativeEnvironment::hasBinding(String *name) const +{ + for (unsigned int i = 0; i < varCount; ++i) { + if (__qmljs_string_equal(vars[i], name)) + return true; + } + for (unsigned int i = 0; i < formalCount; ++i) { + if (__qmljs_string_equal(formals[i], name)) + return true; + } + return deletableLocals.contains(name->toQString()); +} + +void DeclarativeEnvironment::createMutableBinding(String *name, bool deletable) +{ + // all non deletable vars should get created at compile time + assert(deletable); + assert(!hasBinding(name)); + + deletableLocals.insert(name->toQString(), Value::undefinedValue()); +} + +void DeclarativeEnvironment::setMutableBinding(String *name, Value value, bool strict) +{ + // ### throw if strict is true, and it would change an immutable binding + for (unsigned int i = 0; i < varCount; ++i) { + if (__qmljs_string_equal(vars[i], name)) { + locals[i] = value; + return; + } + } + for (unsigned int i = 0; i < formalCount; ++i) { + if (__qmljs_string_equal(formals[i], name)) { + arguments[i] = value; + return; + } + } + QHash<QString, Value>::iterator it = deletableLocals.find(name->toQString()); + if (it != deletableLocals.end()) { + *it = value; + return; + } + assert(false); +} + +Value DeclarativeEnvironment::getBindingValue(String *name, bool strict) const +{ + for (unsigned int i = 0; i < varCount; ++i) { + if (__qmljs_string_equal(vars[i], name)) + return locals[i]; + } + for (unsigned int i = 0; i < formalCount; ++i) { + if (__qmljs_string_equal(formals[i], name)) + return arguments[i]; + } + QHash<QString, Value>::const_iterator it = deletableLocals.find(name->toQString()); + if (it != deletableLocals.end()) + return *it; + + assert(false); +} + +bool DeclarativeEnvironment::deleteBinding(String *name) +{ + QHash<QString, Value>::iterator it = deletableLocals.find(name->toQString()); + if (it != deletableLocals.end()) { + deletableLocals.erase(it); + return true; + } + return !hasBinding(name); +} + + +void ExecutionContext::init(ExecutionEngine *eng) +{ + engine = eng; + parent = 0; + variableEnvironment = new DeclarativeEnvironment(eng); + lexicalEnvironment = variableEnvironment; + thisObject = Value::nullValue(); + result = Value::undefinedValue(); +} + PropertyDescriptor *ExecutionContext::lookupPropertyDescriptor(String *name, PropertyDescriptor *tmp) { - for (ExecutionContext *ctx = this; ctx; ctx = ctx->parent) { + for (DeclarativeEnvironment *ctx = lexicalEnvironment; ctx; ctx = ctx->outer) { if (ctx->activation) { if (PropertyDescriptor *pd = ctx->activation->__getPropertyDescriptor__(this, name, tmp)) return pd; @@ -74,7 +183,7 @@ PropertyDescriptor *ExecutionContext::lookupPropertyDescriptor(String *name, Pro void ExecutionContext::inplaceBitOp(Value value, String *name, BinOp op) { - for (ExecutionContext *ctx = this; ctx; ctx = ctx->parent) { + for (DeclarativeEnvironment *ctx = lexicalEnvironment; ctx; ctx = ctx->outer) { if (ctx->activation) { if (ctx->activation->inplaceBinOp(value, name, op, this)) return; @@ -117,40 +226,21 @@ void ExecutionContext::throwReferenceError(Value value) void ExecutionContext::initCallContext(ExecutionContext *parent, const Value that, FunctionObject *f, Value *args, unsigned argc) { engine = parent->engine; - this->parent = f->scope; - assert(this->parent == f->scope); - result = Value::undefinedValue(); + this->parent = parent; - if (f->needsActivation) - activation = engine->newActivationObject(this); - else - activation = 0; + variableEnvironment = new DeclarativeEnvironment(f, args, argc); + lexicalEnvironment = variableEnvironment; thisObject = that; - - formals = f->formalParameterList; - formalCount = f->formalParameterCount; - arguments = args; - argumentCount = argc; - if (f->needsActivation || argc < formalCount){ - arguments = new Value[qMax(argc, formalCount)]; - if (argc) - std::copy(args, args + argc, arguments); - if (argc < formalCount) - std::fill(arguments + argc, arguments + formalCount, Value::undefinedValue()); - } - vars = f->varList; - varCount = f->varCount; - locals = varCount ? new Value[varCount] : 0; - if (varCount) - std::fill(locals, locals + varCount, Value::undefinedValue()); + result = Value::undefinedValue(); } void ExecutionContext::leaveCallContext() { - if (activation) { - delete[] locals; - locals = 0; + // ## Should rather be handled by a the activation object having a ref to the environment + if (variableEnvironment->activation) { + delete[] variableEnvironment->locals; + variableEnvironment->locals = 0; } } @@ -171,11 +261,12 @@ void ExecutionContext::wireUpPrototype(FunctionObject *f) result = thisObject; Value proto = f->__get__(this, engine->id_prototype); - thisObject.objectValue()->prototype = proto.objectValue(); - if (! thisObject.isObject()) + if (proto.isObject()) + thisObject.objectValue()->prototype = proto.objectValue(); + else thisObject.objectValue()->prototype = engine->objectPrototype; - } + } // namespace VM } // namespace QQmlJS diff --git a/qmljs_environment.h b/qmljs_environment.h index 74568cdf25..bbb5cc4839 100644 --- a/qmljs_environment.h +++ b/qmljs_environment.h @@ -50,30 +50,47 @@ struct Value; struct Object; struct ExecutionEngine; struct ExecutionContext; +struct DeclarativeEnvironment; -struct ExecutionContext { +// This merges LexicalEnvironment and EnvironmentRecord from +// Sec. 10.2 into one class +struct DeclarativeEnvironment +{ ExecutionEngine *engine; - ExecutionContext *parent; + DeclarativeEnvironment *outer; + Object *activation; - Value thisObject; Value *arguments; unsigned int argumentCount; Value *locals; - Value result; String **formals; unsigned int formalCount; String **vars; unsigned int varCount; - PropertyDescriptor *lookupPropertyDescriptor(String *name, PropertyDescriptor *tmp); - void inplaceBitOp(Value value, String *name, BinOp op); + // these get used for createMutableBinding(..., true). + // the only place this is being used is eval(...) + QHash<QString, Value> deletableLocals; - inline Value argument(unsigned int index = 0) - { - if (index < argumentCount) - return arguments[index]; - return Value::undefinedValue(); - } + DeclarativeEnvironment(ExecutionEngine *e); + DeclarativeEnvironment(FunctionObject *f, Value *args, uint argc); + + bool hasBinding(String *name) const; + void createMutableBinding(String *name, bool deletable); + void setMutableBinding(String *name, Value value, bool strict); + Value getBindingValue(String *name, bool strict) const; + bool deleteBinding(String *name); +}; + +struct ExecutionContext +{ + ExecutionEngine *engine; + ExecutionContext *parent; + // ### Should be a general environment + DeclarativeEnvironment *lexicalEnvironment; + DeclarativeEnvironment *variableEnvironment; + Value thisObject; + Value result; void init(ExecutionEngine *eng); @@ -89,9 +106,21 @@ struct ExecutionContext { void throwTypeError(); void throwReferenceError(Value value); void throwUnimplemented(const QString &message); + + PropertyDescriptor *lookupPropertyDescriptor(String *name, PropertyDescriptor *tmp); + void inplaceBitOp(Value value, String *name, BinOp op); + + inline uint argumentCount() const { return variableEnvironment->argumentCount; } + inline Value argument(unsigned int index = 0) + { + if (index < variableEnvironment->argumentCount) + return variableEnvironment->arguments[index]; + return Value::undefinedValue(); + } }; + } // namespace VM } // namespace QQmlJS diff --git a/qmljs_objects.cpp b/qmljs_objects.cpp index 7552a83a03..4f831b01bf 100644 --- a/qmljs_objects.cpp +++ b/qmljs_objects.cpp @@ -554,11 +554,11 @@ int EvalFunction::evaluate(QQmlJS::VM::ExecutionContext *ctx, const QString &fil return EXIT_FAILURE; } - if (!ctx->activation) - ctx->activation = new QQmlJS::VM::Object(); + if (!ctx->variableEnvironment->activation) + ctx->variableEnvironment->activation = new QQmlJS::VM::Object(); foreach (const QString *local, globalCode->locals) { - ctx->activation->__put__(ctx, *local, QQmlJS::VM::Value::undefinedValue()); + ctx->variableEnvironment->activation->__put__(ctx, *local, QQmlJS::VM::Value::undefinedValue()); } if (mode == Codegen::GlobalCode) { @@ -668,7 +668,7 @@ PropertyDescriptor *ActivationObject::__getPropertyDescriptor__(ExecutionContext Value ArgumentsObject::__get__(ExecutionContext *ctx, String *name) { if (name->isEqualTo(ctx->engine->id_length)) - return Value::fromDouble(context->argumentCount); + return Value::fromInt32(context->argumentCount()); return Object::__get__(ctx, name); } @@ -676,8 +676,8 @@ PropertyDescriptor *ArgumentsObject::__getPropertyDescriptor__(ExecutionContext { if (context) { const quint32 i = Value::fromString(name).toUInt32(ctx); - if (i < context->argumentCount) { - *to_fill = PropertyDescriptor::fromValue(context->arguments[i]); + if (i < context->argumentCount()) { + *to_fill = PropertyDescriptor::fromValue(context->argument(i)); to_fill->writable = PropertyDescriptor::Unset; to_fill->enumberable = PropertyDescriptor::Unset; return to_fill; diff --git a/qmljs_objects.h b/qmljs_objects.h index ce26089e8f..6d0e0fa35d 100644 --- a/qmljs_objects.h +++ b/qmljs_objects.h @@ -474,7 +474,7 @@ struct ArrayObject: Object { }; struct FunctionObject: Object { - ExecutionContext *scope; + DeclarativeEnvironment *scope; String *name; String **formalParameterList; unsigned int formalParameterCount; @@ -483,7 +483,7 @@ struct FunctionObject: Object { bool needsActivation; FunctionObject(ExecutionContext *scope) - : scope(scope) + : scope(scope->variableEnvironment) , name(0) , formalParameterList(0) , formalParameterCount(0) @@ -554,39 +554,46 @@ protected: }; struct EvalErrorObject: ErrorObject { - EvalErrorObject(ExecutionContext *ctx): ErrorObject(ctx->argument(0)) { setNameProperty(ctx); } + EvalErrorObject(ExecutionContext *ctx) + : ErrorObject(ctx->argument(0)) { setNameProperty(ctx); } virtual QString className() { return QStringLiteral("EvalError"); } }; struct RangeErrorObject: ErrorObject { - RangeErrorObject(ExecutionContext *ctx): ErrorObject(ctx->argument(0)) { setNameProperty(ctx); } + RangeErrorObject(ExecutionContext *ctx) + : ErrorObject(ctx->argument(0)) { setNameProperty(ctx); } virtual QString className() { return QStringLiteral("RangeError"); } }; struct ReferenceErrorObject: ErrorObject { - ReferenceErrorObject(ExecutionContext *ctx): ErrorObject(ctx->argument(0)) { setNameProperty(ctx); } + ReferenceErrorObject(ExecutionContext *ctx) + : ErrorObject(ctx->argument(0)) { setNameProperty(ctx); } virtual QString className() { return QStringLiteral("ReferenceError"); } }; struct SyntaxErrorObject: ErrorObject { - SyntaxErrorObject(ExecutionContext *ctx): ErrorObject(ctx->argument(0)) { setNameProperty(ctx); } + SyntaxErrorObject(ExecutionContext *ctx) + : ErrorObject(ctx->argument(0)) { setNameProperty(ctx); } virtual QString className() { return QStringLiteral("SyntaxError"); } }; struct TypeErrorObject: ErrorObject { - TypeErrorObject(ExecutionContext *ctx): ErrorObject(ctx->argument(0)) { setNameProperty(ctx); } + TypeErrorObject(ExecutionContext *ctx) + : ErrorObject(ctx->argument(0)) { setNameProperty(ctx); } virtual QString className() { return QStringLiteral("TypeError"); } }; struct URIErrorObject: ErrorObject { - URIErrorObject(ExecutionContext *ctx): ErrorObject(ctx->argument(0)) { setNameProperty(ctx); } + URIErrorObject(ExecutionContext *ctx) + : ErrorObject(ctx->argument(0)) { setNameProperty(ctx); } virtual QString className() { return QStringLiteral("URIError"); } }; struct ActivationObject: Object { - ExecutionContext *context; + DeclarativeEnvironment *context; Value arguments; - ActivationObject(ExecutionContext *context): context(context), arguments(Value::undefinedValue()) {} + ActivationObject(DeclarativeEnvironment *context) + : context(context), arguments(Value::undefinedValue()) {} virtual QString className() { return QStringLiteral("Activation"); } virtual ActivationObject *asActivationObject() { return this; } virtual PropertyDescriptor *__getPropertyDescriptor__(ExecutionContext *ctx, String *name, PropertyDescriptor *to_fill); diff --git a/qmljs_runtime.cpp b/qmljs_runtime.cpp index 44226fb593..407348fe6a 100644 --- a/qmljs_runtime.cpp +++ b/qmljs_runtime.cpp @@ -197,7 +197,7 @@ Value __qmljs_delete_member(ExecutionContext *ctx, Value base, String *name) Value __qmljs_delete_property(ExecutionContext *ctx, String *name) { - Object *obj = ctx->activation; + Object *obj = ctx->lexicalEnvironment->activation; if (!obj) obj = ctx->engine->globalObject.objectValue(); return Value::fromBoolean(obj->__delete__(ctx, name, true)); @@ -779,7 +779,7 @@ Value __qmljs_call_property(ExecutionContext *context, Value base, String *name, Value thisObject; if (base.isUndefined()) { - baseObject = context->activation; + baseObject = context->lexicalEnvironment->activation; thisObject = Value::nullValue(); } else { if (!base.isObject()) diff --git a/qv4ecmaobjects.cpp b/qv4ecmaobjects.cpp index 652fc4525a..7d0b25b5db 100644 --- a/qv4ecmaobjects.cpp +++ b/qv4ecmaobjects.cpp @@ -710,7 +710,7 @@ StringCtor::StringCtor(ExecutionContext *scope) void StringCtor::construct(ExecutionContext *ctx) { Value value; - if (ctx->argumentCount) + if (ctx->argumentCount()) value = Value::fromString(ctx->argument(0).toString(ctx)); else value = Value::fromString(ctx, QString()); @@ -786,7 +786,7 @@ void StringPrototype::method_charAt(ExecutionContext *ctx) const QString str = getThisString(ctx); int pos = 0; - if (ctx->argumentCount > 0) + if (ctx->argumentCount() > 0) pos = (int) ctx->argument(0).toInteger(ctx); QString result; @@ -801,7 +801,7 @@ void StringPrototype::method_charCodeAt(ExecutionContext *ctx) const QString str = getThisString(ctx); int pos = 0; - if (ctx->argumentCount > 0) + if (ctx->argumentCount() > 0) pos = (int) ctx->argument(0).toInteger(ctx); double result = qSNaN(); @@ -816,8 +816,8 @@ void StringPrototype::method_concat(ExecutionContext *ctx) { QString value = getThisString(ctx); - for (unsigned i = 0; i < ctx->argumentCount; ++i) { - Value v = __qmljs_to_string(ctx->arguments[i], ctx); + for (unsigned i = 0; i < ctx->argumentCount(); ++i) { + Value v = __qmljs_to_string(ctx->argument(i), ctx); assert(v.isString()); value += v.stringValue()->toQString(); } @@ -830,11 +830,11 @@ void StringPrototype::method_indexOf(ExecutionContext *ctx) QString value = getThisString(ctx); QString searchString; - if (ctx->argumentCount) + if (ctx->argumentCount()) searchString = ctx->argument(0).toString(ctx)->toQString(); int pos = 0; - if (ctx->argumentCount > 1) + if (ctx->argumentCount() > 1) pos = (int) ctx->argument(1).toInteger(ctx); int index = -1; @@ -849,8 +849,8 @@ void StringPrototype::method_lastIndexOf(ExecutionContext *ctx) const QString value = getThisString(ctx); QString searchString; - if (ctx->argumentCount) { - Value v = __qmljs_to_string(ctx->arguments[0], ctx); + if (ctx->argumentCount()) { + Value v = __qmljs_to_string(ctx->argument(0), ctx); searchString = v.stringValue()->toQString(); } @@ -926,11 +926,11 @@ void StringPrototype::method_substr(ExecutionContext *ctx) const QString value = getThisString(ctx); double start = 0; - if (ctx->argumentCount > 0) + if (ctx->argumentCount() > 0) start = ctx->argument(0).toInteger(ctx); double length = +qInf(); - if (ctx->argumentCount > 1) + if (ctx->argumentCount() > 1) length = ctx->argument(1).toInteger(ctx); double count = value.length(); @@ -952,10 +952,10 @@ void StringPrototype::method_substring(ExecutionContext *ctx) double start = 0; double end = length; - if (ctx->argumentCount > 0) + if (ctx->argumentCount() > 0) start = ctx->argument(0).toInteger(ctx); - if (ctx->argumentCount > 1) + if (ctx->argumentCount() > 1) end = ctx->argument(1).toInteger(ctx); if (qIsNaN(start) || start < 0) @@ -1006,7 +1006,7 @@ void StringPrototype::method_toLocaleUpperCase(ExecutionContext *ctx) void StringPrototype::method_fromCharCode(ExecutionContext *ctx) { QString str; - for (unsigned i = 0; i < ctx->argumentCount; ++i) { + for (unsigned i = 0; i < ctx->argumentCount(); ++i) { QChar c(ctx->argument(i).toUInt16(ctx)); str += c; } @@ -1029,7 +1029,7 @@ void NumberCtor::construct(ExecutionContext *ctx) void NumberCtor::call(ExecutionContext *ctx) { - double value = ctx->argumentCount ? ctx->argument(0).toNumber(ctx) : 0; + double value = ctx->argumentCount() ? ctx->argument(0).toNumber(ctx) : 0; ctx->result = Value::fromDouble(value); } @@ -1143,7 +1143,7 @@ void NumberPrototype::method_toFixed(ExecutionContext *ctx) if (NumberObject *thisObject = ctx->thisObject.asNumberObject()) { double fdigits = 0; - if (ctx->argumentCount > 0) + if (ctx->argumentCount() > 0) fdigits = ctx->argument(0).toInteger(ctx); if (qIsNaN(fdigits)) @@ -1168,7 +1168,7 @@ void NumberPrototype::method_toExponential(ExecutionContext *ctx) if (NumberObject *thisObject = ctx->thisObject.asNumberObject()) { double fdigits = 0; - if (ctx->argumentCount > 0) + if (ctx->argumentCount() > 0) fdigits = ctx->argument(0).toInteger(ctx); QString z = QString::number(thisObject->value.asDouble(), 'e', int (fdigits)); @@ -1183,7 +1183,7 @@ void NumberPrototype::method_toPrecision(ExecutionContext *ctx) if (NumberObject *thisObject = ctx->thisObject.asNumberObject()) { double fdigits = 0; - if (ctx->argumentCount > 0) + if (ctx->argumentCount() > 0) fdigits = ctx->argument(0).toInteger(ctx); ctx->result = Value::fromString(ctx, QString::number(thisObject->value.asDouble(), 'g', int (fdigits))); @@ -1208,7 +1208,7 @@ void BooleanCtor::construct(ExecutionContext *ctx) void BooleanCtor::call(ExecutionContext *ctx) { - bool value = ctx->argumentCount ? ctx->argument(0).toBoolean(ctx) : 0; + bool value = ctx->argumentCount() ? ctx->argument(0).toBoolean(ctx) : 0; ctx->result = Value::fromBoolean(value); } @@ -1255,7 +1255,7 @@ void ArrayCtor::construct(ExecutionContext *ctx) void ArrayCtor::call(ExecutionContext *ctx) { Array value; - if (ctx->argumentCount == 1 && ctx->argument(0).isNumber()) { + if (ctx->argumentCount() == 1 && ctx->argument(0).isNumber()) { double size = ctx->argument(0).asDouble(); quint32 isize = Value::toUInt32(size); @@ -1266,7 +1266,7 @@ void ArrayCtor::call(ExecutionContext *ctx) value.resize(isize); } else { - for (unsigned int i = 0; i < ctx->argumentCount; ++i) { + for (unsigned int i = 0; i < ctx->argumentCount(); ++i) { value.assign(i, ctx->argument(i)); } } @@ -1322,7 +1322,7 @@ void ArrayPrototype::method_concat(ExecutionContext *ctx) result.assign(0, Value::fromString(ctx, v)); } - for (uint i = 0; i < ctx->argumentCount; ++i) { + for (uint i = 0; i < ctx->argumentCount(); ++i) { quint32 k = result.size(); Value arg = ctx->argument(i); @@ -1420,7 +1420,7 @@ void ArrayPrototype::method_push(ExecutionContext *ctx) Value self = ctx->thisObject; if (ArrayObject *instance = self.asArrayObject()) { uint pos = instance->value.size(); - for (unsigned int i = 0; i < ctx->argumentCount; ++i) { + for (unsigned int i = 0; i < ctx->argumentCount(); ++i) { Value val = ctx->argument(i); instance->value.assign(pos++, val); } @@ -1428,7 +1428,7 @@ void ArrayPrototype::method_push(ExecutionContext *ctx) } else { Value r1 = self.property(ctx, ctx->engine->id_length); quint32 n = !r1.isUndefined() ? r1.toUInt32(ctx) : 0; - for (unsigned int index = 0; index < ctx->argumentCount; ++index, ++n) { + for (unsigned int index = 0; index < ctx->argumentCount(); ++index, ++n) { Value r3 = ctx->argument(index); String *name = Value::fromDouble(n).toString(ctx); self.objectValue()->__put__(ctx, name, r3); @@ -1505,7 +1505,7 @@ void ArrayPrototype::method_sort(ExecutionContext *ctx) void ArrayPrototype::method_splice(ExecutionContext *ctx) { - if (ctx->argumentCount < 2) + if (ctx->argumentCount() < 2) return; double start = ctx->argument(0).toInteger(ctx); @@ -1514,7 +1514,7 @@ void ArrayPrototype::method_splice(ExecutionContext *ctx) Value self = ctx->thisObject; if (ArrayObject *instance = self.asArrayObject()) { QVector<Value> items; - for (unsigned int i = 2; i < ctx->argumentCount; ++i) + for (unsigned int i = 2; i < ctx->argumentCount(); ++i) items << ctx->argument(i); ArrayObject *otherInstance = a.asArrayObject(); assert(otherInstance); @@ -1739,13 +1739,13 @@ void FunctionCtor::construct(ExecutionContext *ctx) { QString args; QString body; - if (ctx->argumentCount > 0) - body = ctx->arguments[ctx->argumentCount - 1].toString(ctx)->toQString(); + if (ctx->argumentCount() > 0) + body = ctx->argument(ctx->argumentCount() - 1).toString(ctx)->toQString(); - for (uint i = 0; i < ctx->argumentCount - 1; ++i) { + for (uint i = 0; i < ctx->argumentCount() - 1; ++i) { if (i) args += QLatin1String(", "); - args += ctx->arguments[i].toString(ctx)->toQString(); + args += ctx->argument(i).toString(ctx)->toQString(); } QString function = QLatin1String("function(") + args + QLatin1String("){") + body + QLatin1String("}"); @@ -1835,9 +1835,10 @@ void FunctionPrototype::method_apply(ExecutionContext *ctx) void FunctionPrototype::method_call(ExecutionContext *ctx) { Value thisArg = ctx->argument(0); - QVector<Value> args(ctx->argumentCount ? ctx->argumentCount - 1 : 0); - if (ctx->argumentCount) - qCopy(ctx->arguments + 1, ctx->arguments + ctx->argumentCount, args.begin()); + QVector<Value> args(ctx->argumentCount() ? ctx->argumentCount() - 1 : 0); + if (ctx->argumentCount()) + qCopy(ctx->variableEnvironment->arguments + 1, + ctx->variableEnvironment->arguments + ctx->argumentCount(), args.begin()); ctx->result = __qmljs_call_value(ctx, thisArg, ctx->thisObject, args.data(), args.size()); } @@ -1863,10 +1864,10 @@ void DateCtor::construct(ExecutionContext *ctx) { double t = 0; - if (ctx->argumentCount == 0) + if (ctx->argumentCount() == 0) t = currentTime(); - else if (ctx->argumentCount == 1) { + else if (ctx->argumentCount() == 1) { Value arg = ctx->argument(0); if (DateObject *d = arg.asDateObject()) arg = d->value; @@ -1879,14 +1880,14 @@ void DateCtor::construct(ExecutionContext *ctx) t = TimeClip(arg.toNumber(ctx)); } - else { // ctx->argumentCount() > 1 + else { // ctx->argumentCount()() > 1 double year = ctx->argument(0).toNumber(ctx); double month = ctx->argument(1).toNumber(ctx); - double day = ctx->argumentCount >= 3 ? ctx->argument(2).toNumber(ctx) : 1; - double hours = ctx->argumentCount >= 4 ? ctx->argument(3).toNumber(ctx) : 0; - double mins = ctx->argumentCount >= 5 ? ctx->argument(4).toNumber(ctx) : 0; - double secs = ctx->argumentCount >= 6 ? ctx->argument(5).toNumber(ctx) : 0; - double ms = ctx->argumentCount >= 7 ? ctx->argument(6).toNumber(ctx) : 0; + double day = ctx->argumentCount() >= 3 ? ctx->argument(2).toNumber(ctx) : 1; + double hours = ctx->argumentCount() >= 4 ? ctx->argument(3).toNumber(ctx) : 0; + double mins = ctx->argumentCount() >= 5 ? ctx->argument(4).toNumber(ctx) : 0; + double secs = ctx->argumentCount() >= 6 ? ctx->argument(5).toNumber(ctx) : 0; + double ms = ctx->argumentCount() >= 7 ? ctx->argument(6).toNumber(ctx) : 0; if (year >= 0 && year <= 99) year += 1900; t = MakeDate(MakeDay(year, month, day), MakeTime(hours, mins, secs, ms)); @@ -1990,7 +1991,7 @@ void DatePrototype::method_parse(ExecutionContext *ctx) void DatePrototype::method_UTC(ExecutionContext *ctx) { - const int numArgs = ctx->argumentCount; + const int numArgs = ctx->argumentCount(); if (numArgs >= 2) { double year = ctx->argument(0).toNumber(ctx); double month = ctx->argument(1).toNumber(ctx); @@ -2238,7 +2239,7 @@ void DatePrototype::method_setSeconds(ExecutionContext *ctx) if (DateObject *self = ctx->thisObject.asDateObject()) { double t = LocalTime(self->value.asDouble()); double sec = ctx->argument(0).toNumber(ctx); - double ms = (ctx->argumentCount < 2) ? msFromTime(t) : ctx->argument(1).toNumber(ctx); + double ms = (ctx->argumentCount() < 2) ? msFromTime(t) : ctx->argument(1).toNumber(ctx); t = TimeClip(UTC(MakeDate(Day(t), MakeTime(HourFromTime(t), MinFromTime(t), sec, ms)))); self->value.setDouble(t); ctx->result = self->value; @@ -2252,7 +2253,7 @@ void DatePrototype::method_setUTCSeconds(ExecutionContext *ctx) if (DateObject *self = ctx->thisObject.asDateObject()) { double t = self->value.asDouble(); double sec = ctx->argument(0).toNumber(ctx); - double ms = (ctx->argumentCount < 2) ? msFromTime(t) : ctx->argument(1).toNumber(ctx); + double ms = (ctx->argumentCount() < 2) ? msFromTime(t) : ctx->argument(1).toNumber(ctx); t = TimeClip(UTC(MakeDate(Day(t), MakeTime(HourFromTime(t), MinFromTime(t), sec, ms)))); self->value.setDouble(t); ctx->result = self->value; @@ -2266,8 +2267,8 @@ void DatePrototype::method_setMinutes(ExecutionContext *ctx) if (DateObject *self = ctx->thisObject.asDateObject()) { double t = LocalTime(self->value.asDouble()); double min = ctx->argument(0).toNumber(ctx); - double sec = (ctx->argumentCount < 2) ? SecFromTime(t) : ctx->argument(1).toNumber(ctx); - double ms = (ctx->argumentCount < 3) ? msFromTime(t) : ctx->argument(2).toNumber(ctx); + double sec = (ctx->argumentCount() < 2) ? SecFromTime(t) : ctx->argument(1).toNumber(ctx); + double ms = (ctx->argumentCount() < 3) ? msFromTime(t) : ctx->argument(2).toNumber(ctx); t = TimeClip(UTC(MakeDate(Day(t), MakeTime(HourFromTime(t), min, sec, ms)))); self->value.setDouble(t); ctx->result = self->value; @@ -2281,8 +2282,8 @@ void DatePrototype::method_setUTCMinutes(ExecutionContext *ctx) if (DateObject *self = ctx->thisObject.asDateObject()) { double t = self->value.asDouble(); double min = ctx->argument(0).toNumber(ctx); - double sec = (ctx->argumentCount < 2) ? SecFromTime(t) : ctx->argument(1).toNumber(ctx); - double ms = (ctx->argumentCount < 3) ? msFromTime(t) : ctx->argument(2).toNumber(ctx); + double sec = (ctx->argumentCount() < 2) ? SecFromTime(t) : ctx->argument(1).toNumber(ctx); + double ms = (ctx->argumentCount() < 3) ? msFromTime(t) : ctx->argument(2).toNumber(ctx); t = TimeClip(UTC(MakeDate(Day(t), MakeTime(HourFromTime(t), min, sec, ms)))); self->value.setDouble(t); ctx->result = self->value; @@ -2296,9 +2297,9 @@ void DatePrototype::method_setHours(ExecutionContext *ctx) if (DateObject *self = ctx->thisObject.asDateObject()) { double t = LocalTime(self->value.asDouble()); double hour = ctx->argument(0).toNumber(ctx); - double min = (ctx->argumentCount < 2) ? MinFromTime(t) : ctx->argument(1).toNumber(ctx); - double sec = (ctx->argumentCount < 3) ? SecFromTime(t) : ctx->argument(2).toNumber(ctx); - double ms = (ctx->argumentCount < 4) ? msFromTime(t) : ctx->argument(3).toNumber(ctx); + double min = (ctx->argumentCount() < 2) ? MinFromTime(t) : ctx->argument(1).toNumber(ctx); + double sec = (ctx->argumentCount() < 3) ? SecFromTime(t) : ctx->argument(2).toNumber(ctx); + double ms = (ctx->argumentCount() < 4) ? msFromTime(t) : ctx->argument(3).toNumber(ctx); t = TimeClip(UTC(MakeDate(Day(t), MakeTime(hour, min, sec, ms)))); self->value.setDouble(t); ctx->result = self->value; @@ -2312,9 +2313,9 @@ void DatePrototype::method_setUTCHours(ExecutionContext *ctx) if (DateObject *self = ctx->thisObject.asDateObject()) { double t = self->value.asDouble(); double hour = ctx->argument(0).toNumber(ctx); - double min = (ctx->argumentCount < 2) ? MinFromTime(t) : ctx->argument(1).toNumber(ctx); - double sec = (ctx->argumentCount < 3) ? SecFromTime(t) : ctx->argument(2).toNumber(ctx); - double ms = (ctx->argumentCount < 4) ? msFromTime(t) : ctx->argument(3).toNumber(ctx); + double min = (ctx->argumentCount() < 2) ? MinFromTime(t) : ctx->argument(1).toNumber(ctx); + double sec = (ctx->argumentCount() < 3) ? SecFromTime(t) : ctx->argument(2).toNumber(ctx); + double ms = (ctx->argumentCount() < 4) ? msFromTime(t) : ctx->argument(3).toNumber(ctx); t = TimeClip(UTC(MakeDate(Day(t), MakeTime(hour, min, sec, ms)))); self->value.setDouble(t); ctx->result = self->value; @@ -2354,7 +2355,7 @@ void DatePrototype::method_setMonth(ExecutionContext *ctx) if (DateObject *self = ctx->thisObject.asDateObject()) { double t = LocalTime(self->value.asDouble()); double month = ctx->argument(0).toNumber(ctx); - double date = (ctx->argumentCount < 2) ? DateFromTime(t) : ctx->argument(1).toNumber(ctx); + double date = (ctx->argumentCount() < 2) ? DateFromTime(t) : ctx->argument(1).toNumber(ctx); t = TimeClip(UTC(MakeDate(MakeDay(YearFromTime(t), month, date), TimeWithinDay(t)))); self->value.setDouble(t); ctx->result = self->value; @@ -2368,7 +2369,7 @@ void DatePrototype::method_setUTCMonth(ExecutionContext *ctx) if (DateObject *self = ctx->thisObject.asDateObject()) { double t = self->value.asDouble(); double month = ctx->argument(0).toNumber(ctx); - double date = (ctx->argumentCount < 2) ? DateFromTime(t) : ctx->argument(1).toNumber(ctx); + double date = (ctx->argumentCount() < 2) ? DateFromTime(t) : ctx->argument(1).toNumber(ctx); t = TimeClip(UTC(MakeDate(MakeDay(YearFromTime(t), month, date), TimeWithinDay(t)))); self->value.setDouble(t); ctx->result = self->value; @@ -2408,8 +2409,8 @@ void DatePrototype::method_setUTCFullYear(ExecutionContext *ctx) if (DateObject *self = ctx->thisObject.asDateObject()) { double t = self->value.asDouble(); double year = ctx->argument(0).toNumber(ctx); - double month = (ctx->argumentCount < 2) ? MonthFromTime(t) : ctx->argument(1).toNumber(ctx); - double date = (ctx->argumentCount < 3) ? DateFromTime(t) : ctx->argument(2).toNumber(ctx); + double month = (ctx->argumentCount() < 2) ? MonthFromTime(t) : ctx->argument(1).toNumber(ctx); + double date = (ctx->argumentCount() < 3) ? DateFromTime(t) : ctx->argument(2).toNumber(ctx); t = TimeClip(UTC(MakeDate(MakeDay(year, month, date), TimeWithinDay(t)))); self->value.setDouble(t); ctx->result = self->value; @@ -2423,8 +2424,8 @@ void DatePrototype::method_setFullYear(ExecutionContext *ctx) if (DateObject *self = ctx->thisObject.asDateObject()) { double t = LocalTime(self->value.asDouble()); double year = ctx->argument(0).toNumber(ctx); - double month = (ctx->argumentCount < 2) ? MonthFromTime(t) : ctx->argument(1).toNumber(ctx); - double date = (ctx->argumentCount < 3) ? DateFromTime(t) : ctx->argument(2).toNumber(ctx); + double month = (ctx->argumentCount() < 2) ? MonthFromTime(t) : ctx->argument(1).toNumber(ctx); + double date = (ctx->argumentCount() < 3) ? DateFromTime(t) : ctx->argument(2).toNumber(ctx); t = TimeClip(UTC(MakeDate(MakeDay(year, month, date), TimeWithinDay(t)))); self->value.setDouble(t); ctx->result = self->value; @@ -2451,13 +2452,13 @@ RegExpCtor::RegExpCtor(ExecutionContext *scope) void RegExpCtor::construct(ExecutionContext *ctx) { -// if (ctx->argumentCount > 2) { +// if (ctx->argumentCount() > 2) { // ctx->throwTypeError(); // return; // } - Value r = ctx->argumentCount > 0 ? ctx->argument(0) : Value::undefinedValue(); - Value f = ctx->argumentCount > 1 ? ctx->argument(1) : Value::undefinedValue(); + Value r = ctx->argumentCount() > 0 ? ctx->argument(0) : Value::undefinedValue(); + Value f = ctx->argumentCount() > 1 ? ctx->argument(1) : Value::undefinedValue(); if (RegExpObject *re = r.asRegExpObject()) { if (!f.isUndefined()) { ctx->throwTypeError(); @@ -2501,8 +2502,8 @@ void RegExpCtor::construct(ExecutionContext *ctx) void RegExpCtor::call(ExecutionContext *ctx) { - if (ctx->argumentCount > 0 && ctx->argument(0).asRegExpObject()) { - if (ctx->argumentCount == 1 || ctx->argument(1).isUndefined()) { + if (ctx->argumentCount() > 0 && ctx->argument(0).asRegExpObject()) { + if (ctx->argumentCount() == 1 || ctx->argument(1).isUndefined()) { ctx->result = ctx->argument(0); return; } @@ -2822,7 +2823,7 @@ void MathObject::method_log(ExecutionContext *ctx) void MathObject::method_max(ExecutionContext *ctx) { double mx = -qInf(); - for (unsigned i = 0; i < ctx->argumentCount; ++i) { + for (unsigned i = 0; i < ctx->argumentCount(); ++i) { double x = ctx->argument(i).toNumber(ctx); if (x > mx || qIsNaN(x)) mx = x; @@ -2833,7 +2834,7 @@ void MathObject::method_max(ExecutionContext *ctx) void MathObject::method_min(ExecutionContext *ctx) { double mx = qInf(); - for (unsigned i = 0; i < ctx->argumentCount; ++i) { + for (unsigned i = 0; i < ctx->argumentCount(); ++i) { double x = ctx->argument(i).toNumber(ctx); if ((x == 0 && mx == x && copySign(1.0, x) == -1.0) || (x < mx) || qIsNaN(x)) { diff --git a/qv4isel_masm.cpp b/qv4isel_masm.cpp index 90b3cb968d..8a8e663e93 100644 --- a/qv4isel_masm.cpp +++ b/qv4isel_masm.cpp @@ -180,10 +180,12 @@ InstructionSelection::Pointer InstructionSelection::loadTempAddress(RegisterID r int32_t offset = 0; if (t->index < 0) { const int arg = -t->index - 1; - loadPtr(Address(ContextRegister, offsetof(ExecutionContext, arguments)), reg); + loadPtr(Address(ContextRegister, offsetof(ExecutionContext, variableEnvironment)), reg); + loadPtr(Address(reg, offsetof(DeclarativeEnvironment, arguments)), reg); offset = arg * sizeof(Value); } else if (t->index < _function->locals.size()) { - loadPtr(Address(ContextRegister, offsetof(ExecutionContext, locals)), reg); + loadPtr(Address(ContextRegister, offsetof(ExecutionContext, variableEnvironment)), reg); + loadPtr(Address(reg, offsetof(DeclarativeEnvironment, locals)), reg); offset = t->index * sizeof(Value); } else { const int arg = _function->maxNumberOfArguments + t->index - _function->locals.size(); |