aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@digia.com>2013-09-11 19:05:24 +0200
committerSimon Hausmann <simon.hausmann@digia.com>2013-09-11 19:08:28 +0200
commit89402e0ef69da3c954a540510e8b4e8501bc1ce3 (patch)
treecf97d95e1ac837e5d439f2be9125e0a104b5bbce /src/qml
parent0cce947449fa502fd4bf2aec95fa490c8417cdeb (diff)
parent262d7261033df7650938c38401112a4767d926ff (diff)
Merge branch 'dev' of qtdeclarative into wip/v4
Conflicts: src/qml/jsruntime/qv4script.cpp Change-Id: I20136cab29d86862b5bd9208003200bc24bcdacf
Diffstat (limited to 'src/qml')
-rw-r--r--src/qml/compiler/qv4compileddata.cpp2
-rw-r--r--src/qml/compiler/qv4instr_moth_p.h14
-rw-r--r--src/qml/compiler/qv4isel_masm.cpp129
-rw-r--r--src/qml/compiler/qv4isel_masm_p.h101
-rw-r--r--src/qml/compiler/qv4isel_moth.cpp46
-rw-r--r--src/qml/compiler/qv4isel_moth_p.h9
-rw-r--r--src/qml/compiler/qv4isel_util_p.h2
-rw-r--r--src/qml/compiler/qv4jsir_p.h6
-rw-r--r--src/qml/compiler/qv4regalloc.cpp3
-rw-r--r--src/qml/compiler/qv4ssa.cpp160
-rw-r--r--src/qml/jsapi/qjsvalue.cpp27
-rw-r--r--src/qml/jsruntime/jsruntime.pri1
-rw-r--r--src/qml/jsruntime/qv4argumentsobject.cpp19
-rw-r--r--src/qml/jsruntime/qv4argumentsobject_p.h4
-rw-r--r--src/qml/jsruntime/qv4arrayobject.cpp123
-rw-r--r--src/qml/jsruntime/qv4arrayobject_p.h4
-rw-r--r--src/qml/jsruntime/qv4booleanobject.cpp8
-rw-r--r--src/qml/jsruntime/qv4booleanobject_p.h4
-rw-r--r--src/qml/jsruntime/qv4context.cpp48
-rw-r--r--src/qml/jsruntime/qv4context_p.h9
-rw-r--r--src/qml/jsruntime/qv4dateobject.cpp55
-rw-r--r--src/qml/jsruntime/qv4dateobject_p.h4
-rw-r--r--src/qml/jsruntime/qv4debugging.cpp18
-rw-r--r--src/qml/jsruntime/qv4debugging_p.h7
-rw-r--r--src/qml/jsruntime/qv4engine.cpp21
-rw-r--r--src/qml/jsruntime/qv4engine_p.h15
-rw-r--r--src/qml/jsruntime/qv4errorobject.cpp42
-rw-r--r--src/qml/jsruntime/qv4errorobject_p.h16
-rw-r--r--src/qml/jsruntime/qv4function.cpp15
-rw-r--r--src/qml/jsruntime/qv4function_p.h13
-rw-r--r--src/qml/jsruntime/qv4functionobject.cpp135
-rw-r--r--src/qml/jsruntime/qv4functionobject_p.h36
-rw-r--r--src/qml/jsruntime/qv4globalobject.cpp12
-rw-r--r--src/qml/jsruntime/qv4globalobject_p.h2
-rw-r--r--src/qml/jsruntime/qv4identifier.cpp4
-rw-r--r--src/qml/jsruntime/qv4include.cpp9
-rw-r--r--src/qml/jsruntime/qv4jsonobject.cpp30
-rw-r--r--src/qml/jsruntime/qv4lookup.cpp51
-rw-r--r--src/qml/jsruntime/qv4managed.cpp4
-rw-r--r--src/qml/jsruntime/qv4managed_p.h37
-rw-r--r--src/qml/jsruntime/qv4mm.cpp13
-rw-r--r--src/qml/jsruntime/qv4mm_p.h2
-rw-r--r--src/qml/jsruntime/qv4numberobject.cpp14
-rw-r--r--src/qml/jsruntime/qv4numberobject_p.h4
-rw-r--r--src/qml/jsruntime/qv4object.cpp93
-rw-r--r--src/qml/jsruntime/qv4object_p.h8
-rw-r--r--src/qml/jsruntime/qv4objectproto.cpp21
-rw-r--r--src/qml/jsruntime/qv4objectproto_p.h4
-rw-r--r--src/qml/jsruntime/qv4qobjectwrapper.cpp38
-rw-r--r--src/qml/jsruntime/qv4qobjectwrapper_p.h6
-rw-r--r--src/qml/jsruntime/qv4regexpobject.cpp44
-rw-r--r--src/qml/jsruntime/qv4regexpobject_p.h4
-rw-r--r--src/qml/jsruntime/qv4runtime.cpp645
-rw-r--r--src/qml/jsruntime/qv4runtime_p.h509
-rw-r--r--src/qml/jsruntime/qv4scopedvalue_p.h287
-rw-r--r--src/qml/jsruntime/qv4script.cpp9
-rw-r--r--src/qml/jsruntime/qv4script_p.h2
-rw-r--r--src/qml/jsruntime/qv4sequenceobject.cpp11
-rw-r--r--src/qml/jsruntime/qv4sparsearray.cpp18
-rw-r--r--src/qml/jsruntime/qv4stacktrace.cpp2
-rw-r--r--src/qml/jsruntime/qv4stringobject.cpp64
-rw-r--r--src/qml/jsruntime/qv4stringobject_p.h4
-rw-r--r--src/qml/jsruntime/qv4unwindhelper_arm_p.h12
-rw-r--r--src/qml/jsruntime/qv4unwindhelper_dw2_p.h2
-rw-r--r--src/qml/jsruntime/qv4value.cpp85
-rw-r--r--src/qml/jsruntime/qv4value_p.h50
-rw-r--r--src/qml/jsruntime/qv4vme_moth.cpp132
-rw-r--r--src/qml/qml/qqmlcomponent.cpp41
-rw-r--r--src/qml/qml/qqmljavascriptexpression.cpp13
-rw-r--r--src/qml/qml/qqmlproperty.cpp10
-rw-r--r--src/qml/qml/qqmlpropertycache.cpp4
-rw-r--r--src/qml/qml/qqmlvmemetaobject.cpp9
-rw-r--r--src/qml/qml/qqmlxmlhttprequest.cpp11
-rw-r--r--src/qml/qml/v8/qqmlbuiltinfunctions.cpp4
-rw-r--r--src/qml/qml/v8/qv8engine.cpp11
-rw-r--r--src/qml/qml/v8/qv8engine_p.h4
-rw-r--r--src/qml/types/qqmldelegatemodel.cpp8
-rw-r--r--src/qml/types/qquickworkerscript.cpp27
78 files changed, 2048 insertions, 1422 deletions
diff --git a/src/qml/compiler/qv4compileddata.cpp b/src/qml/compiler/qv4compileddata.cpp
index 404039d4e4..cdcc407e2a 100644
--- a/src/qml/compiler/qv4compileddata.cpp
+++ b/src/qml/compiler/qv4compileddata.cpp
@@ -57,7 +57,7 @@ namespace CompiledData {
namespace {
bool functionSortHelper(QV4::Function *lhs, QV4::Function *rhs)
{
- return reinterpret_cast<quintptr>(lhs->code) < reinterpret_cast<quintptr>(rhs->code);
+ return reinterpret_cast<quintptr>(lhs->codePtr) < reinterpret_cast<quintptr>(rhs->codePtr);
}
}
diff --git a/src/qml/compiler/qv4instr_moth_p.h b/src/qml/compiler/qv4instr_moth_p.h
index 8164e439f0..68bc109eb4 100644
--- a/src/qml/compiler/qv4instr_moth_p.h
+++ b/src/qml/compiler/qv4instr_moth_p.h
@@ -289,7 +289,7 @@ union Instr
struct instr_callValue {
MOTH_INSTR_HEADER
quint32 argc;
- quint32 args;
+ quint32 callData;
Param dest;
Param result;
};
@@ -297,7 +297,7 @@ union Instr
MOTH_INSTR_HEADER
int name;
quint32 argc;
- quint32 args;
+ quint32 callData;
Param base;
Param result;
};
@@ -306,14 +306,14 @@ union Instr
Param base;
Param index;
quint32 argc;
- quint32 args;
+ quint32 callData;
Param result;
};
struct instr_callActivationProperty {
MOTH_INSTR_HEADER
int name;
quint32 argc;
- quint32 args;
+ quint32 callData;
Param result;
};
struct instr_callBuiltinThrow {
@@ -460,7 +460,7 @@ union Instr
struct instr_createValue {
MOTH_INSTR_HEADER
quint32 argc;
- quint32 args;
+ quint32 callData;
Param func;
Param result;
};
@@ -468,7 +468,7 @@ union Instr
MOTH_INSTR_HEADER
int name;
quint32 argc;
- quint32 args;
+ quint32 callData;
Param base;
Param result;
};
@@ -476,7 +476,7 @@ union Instr
MOTH_INSTR_HEADER
int name;
quint32 argc;
- quint32 args;
+ quint32 callData;
Param result;
};
struct instr_jump {
diff --git a/src/qml/compiler/qv4isel_masm.cpp b/src/qml/compiler/qv4isel_masm.cpp
index cefc053ac4..19c7039e69 100644
--- a/src/qml/compiler/qv4isel_masm.cpp
+++ b/src/qml/compiler/qv4isel_masm.cpp
@@ -68,7 +68,7 @@ using namespace QV4;
CompilationUnit::~CompilationUnit()
{
foreach (Function *f, runtimeFunctions)
- engine->allFunctions.remove(reinterpret_cast<quintptr>(f->code));
+ engine->allFunctions.remove(reinterpret_cast<quintptr>(f->codePtr));
UnwindHelper::deregisterFunctions(runtimeFunctions);
}
@@ -87,7 +87,7 @@ void CompilationUnit::linkBackendToEngine(ExecutionEngine *engine)
UnwindHelper::registerFunctions(runtimeFunctions);
foreach (Function *f, runtimeFunctions)
- engine->allFunctions.insert(reinterpret_cast<quintptr>(f->code), f);
+ engine->allFunctions.insert(reinterpret_cast<quintptr>(f->codePtr), f);
}
QV4::ExecutableAllocator::ChunkOfPages *CompilationUnit::chunkForFunction(int functionIndex)
@@ -341,7 +341,7 @@ void Assembler::storeValue(QV4::Value value, V4IR::Temp* destination)
storeValue(value, addr);
}
-void Assembler::enterStandardStackFrame(bool withLocals)
+void Assembler::enterStandardStackFrame()
{
platformEnterStandardStackFrame();
@@ -350,23 +350,22 @@ void Assembler::enterStandardStackFrame(bool withLocals)
push(StackFrameRegister);
move(StackPointerRegister, StackFrameRegister);
- int frameSize = _stackLayout.calculateStackFrameSize(withLocals);
+ int frameSize = _stackLayout.calculateStackFrameSize();
subPtr(TrustedImm32(frameSize), StackPointerRegister);
for (int i = 0; i < calleeSavedRegisterCount; ++i)
storePtr(calleeSavedRegisters[i], Address(StackFrameRegister, -(i + 1) * sizeof(void*)));
- move(StackFrameRegister, LocalsRegister);
}
-void Assembler::leaveStandardStackFrame(bool withLocals)
+void Assembler::leaveStandardStackFrame()
{
// restore the callee saved registers
for (int i = calleeSavedRegisterCount - 1; i >= 0; --i)
loadPtr(Address(StackFrameRegister, -(i + 1) * sizeof(void*)), calleeSavedRegisters[i]);
- int frameSize = _stackLayout.calculateStackFrameSize(withLocals);
+ int frameSize = _stackLayout.calculateStackFrameSize();
// Work around bug in ARMv7Assembler.h where add32(imm, sp, sp) doesn't
// work well for large immediates.
#if CPU(ARM_THUMB2)
@@ -625,7 +624,7 @@ void InstructionSelection::run(V4IR::Function *function)
Assembler* oldAssembler = _as;
_as = new Assembler(this, _function, executableAllocator, 6); // 6 == max argc for calls to built-ins with an argument array
- _as->enterStandardStackFrame(/*withLocals*/true);
+ _as->enterStandardStackFrame();
int contextPointer = 0;
#if !defined(RETURN_VALUE_IN_REGISTER)
@@ -641,13 +640,19 @@ void InstructionSelection::run(V4IR::Function *function)
_as->loadPtr(addressForArgument(contextPointer), Assembler::ContextRegister);
#endif
+ const int locals = _as->stackLayout().calculateJSStackFrameSize();
+ _as->loadPtr(Address(Assembler::ContextRegister, offsetof(ExecutionContext, engine)), Assembler::ScratchRegister);
+ _as->loadPtr(Address(Assembler::ScratchRegister, offsetof(ExecutionEngine, jsStackTop)), Assembler::LocalsRegister);
+ _as->addPtr(Assembler::TrustedImm32(sizeof(QV4::Value)*locals), Assembler::LocalsRegister);
+ _as->storePtr(Assembler::LocalsRegister, Address(Assembler::ScratchRegister, offsetof(ExecutionEngine, jsStackTop)));
+
for (int i = 0, ei = _function->basicBlocks.size(); i != ei; ++i) {
V4IR::BasicBlock *nextBlock = (i < ei - 1) ? _function->basicBlocks[i + 1] : 0;
_block = _function->basicBlocks[i];
_as->registerBlock(_block, nextBlock);
if (_reentryBlocks.contains(_block)) {
- _as->enterStandardStackFrame(/*locals*/false);
+ _as->enterStandardStackFrame();
#ifdef ARGUMENTS_IN_REGISTERS
_as->move(Assembler::registerForArgument(0), Assembler::ContextRegister);
_as->move(Assembler::registerForArgument(1), Assembler::LocalsRegister);
@@ -694,21 +699,19 @@ QV4::CompiledData::CompilationUnit *InstructionSelection::backendCompileStep()
void InstructionSelection::callBuiltinInvalid(V4IR::Name *func, V4IR::ExprList *args, V4IR::Temp *result)
{
- int argc = prepareVariableArguments(args);
+ int argc = prepareCallData(args, 0);
if (useFastLookups && func->global) {
uint index = registerGlobalGetterLookup(*func->id);
generateFunctionCall(Assembler::Void, __qmljs_call_global_lookup,
Assembler::ContextRegister, Assembler::PointerToValue(result),
Assembler::TrustedImm32(index),
- baseAddressForCallArguments(),
- Assembler::TrustedImm32(argc));
+ baseAddressForCallData());
} else {
generateFunctionCall(Assembler::Void, __qmljs_call_activation_property,
Assembler::ContextRegister, Assembler::PointerToValue(result),
Assembler::PointerToString(*func->id),
- baseAddressForCallArguments(),
- Assembler::TrustedImm32(argc));
+ baseAddressForCallData());
}
}
@@ -829,16 +832,21 @@ static void *tryWrapper(ExecutionContext *context, void *localsPtr, MiddleOfFunc
{
*exceptionVar = Value::undefinedValue();
void *addressToContinueAt = 0;
+ Value *jsStackTop = context->engine->jsStackTop;
try {
addressToContinueAt = tryBody(context, localsPtr);
} catch (Exception& ex) {
+ context->engine->jsStackTop = jsStackTop;
ex.accept(context);
*exceptionVar = ex.value();
try {
- ExecutionContext *catchContext = __qmljs_builtin_push_catch_scope(exceptionVarName, ex.value(), context);
+ QV4::ValueScope scope(context);
+ QV4::ScopedValue exception(scope, ex.value());
+ ExecutionContext *catchContext = __qmljs_builtin_push_catch_scope(exceptionVarName, exception, context);
addressToContinueAt = catchBody(catchContext, localsPtr);
context = __qmljs_builtin_pop_scope(catchContext);
} catch (Exception& ex) {
+ context->engine->jsStackTop = jsStackTop;
*exceptionVar = ex.value();
ex.accept(context);
addressToContinueAt = catchBody(context, localsPtr);
@@ -867,7 +875,7 @@ void InstructionSelection::callBuiltinFinishTry()
// This assumes that we're in code that was called by tryWrapper, so we return to try wrapper
// with the address that we'd like to continue at, which is right after the ret below.
Assembler::DataLabelPtr continuation = _as->moveWithPatch(Assembler::TrustedImmPtr(0), Assembler::ReturnValueRegister);
- _as->leaveStandardStackFrame(/*locals*/false);
+ _as->leaveStandardStackFrame();
_as->ret();
_as->addPatch(continuation, _as->label());
}
@@ -976,11 +984,10 @@ void InstructionSelection::callValue(V4IR::Temp *value, V4IR::ExprList *args, V4
{
Q_ASSERT(value);
- int argc = prepareVariableArguments(args);
- V4IR::Temp* thisObject = 0;
+ int argc = prepareCallData(args, 0);
generateFunctionCall(Assembler::Void, __qmljs_call_value, Assembler::ContextRegister,
- Assembler::PointerToValue(result), Assembler::PointerToValue(thisObject),
- Assembler::Reference(value), baseAddressForCallArguments(), Assembler::TrustedImm32(argc));
+ Assembler::PointerToValue(result), Assembler::Reference(value),
+ baseAddressForCallData());
}
void InstructionSelection::loadThisObject(V4IR::Temp *temp)
@@ -1333,19 +1340,19 @@ void InstructionSelection::callProperty(V4IR::Expr *base, const QString &name, V
{
assert(base != 0);
- int argc = prepareVariableArguments(args);
+ int argc = prepareCallData(args, base);
if (useFastLookups) {
uint index = registerGetterLookup(name);
generateFunctionCall(Assembler::Void, __qmljs_call_property_lookup,
Assembler::ContextRegister, Assembler::PointerToValue(result),
- Assembler::PointerToValue(base), Assembler::TrustedImm32(index),
- baseAddressForCallArguments(),
- Assembler::TrustedImm32(argc));
- } else {
+ Assembler::TrustedImm32(index),
+ baseAddressForCallData());
+ } else
+ {
generateFunctionCall(Assembler::Void, __qmljs_call_property, Assembler::ContextRegister,
- Assembler::PointerToValue(result), Assembler::PointerToValue(base), Assembler::PointerToString(name),
- baseAddressForCallArguments(), Assembler::TrustedImm32(argc));
+ Assembler::PointerToValue(result), Assembler::PointerToString(name),
+ baseAddressForCallData());
}
}
@@ -1354,11 +1361,10 @@ void InstructionSelection::callSubscript(V4IR::Expr *base, V4IR::Expr *index, V4
{
assert(base != 0);
- int argc = prepareVariableArguments(args);
+ int argc = prepareCallData(args, base);
generateFunctionCall(Assembler::Void, __qmljs_call_element, Assembler::ContextRegister,
- Assembler::PointerToValue(result), Assembler::PointerToValue(base),
- Assembler::PointerToValue(index), baseAddressForCallArguments(),
- Assembler::TrustedImm32(argc));
+ Assembler::PointerToValue(result), Assembler::PointerToValue(index),
+ baseAddressForCallData());
}
void InstructionSelection::convertType(V4IR::Temp *source, V4IR::Temp *target)
@@ -1559,35 +1565,41 @@ void InstructionSelection::convertTypeToSInt32(V4IR::Temp *source, V4IR::Temp *t
void InstructionSelection::constructActivationProperty(V4IR::Name *func, V4IR::ExprList *args, V4IR::Temp *result)
{
assert(func != 0);
+ int argc = prepareCallData(args, 0);
if (useFastLookups && func->global) {
- int argc = prepareVariableArguments(args);
uint index = registerGlobalGetterLookup(*func->id);
generateFunctionCall(Assembler::Void, __qmljs_construct_global_lookup,
Assembler::ContextRegister, Assembler::PointerToValue(result),
Assembler::TrustedImm32(index),
- baseAddressForCallArguments(),
- Assembler::TrustedImm32(argc));
+ baseAddressForCallData());
return;
}
- callRuntimeMethod(result, __qmljs_construct_activation_property, func, args);
+ generateFunctionCall(Assembler::Void, __qmljs_construct_activation_property,
+ Assembler::ContextRegister, Assembler::PointerToValue(result),
+ Assembler::PointerToString(*func->id),
+ baseAddressForCallData());
}
+
void InstructionSelection::constructProperty(V4IR::Temp *base, const QString &name, V4IR::ExprList *args, V4IR::Temp *result)
{
- int argc = prepareVariableArguments(args);
+ int argc = prepareCallData(args, 0);
generateFunctionCall(Assembler::Void, __qmljs_construct_property, Assembler::ContextRegister,
- Assembler::PointerToValue(result), Assembler::Reference(base), Assembler::PointerToString(name), baseAddressForCallArguments(), Assembler::TrustedImm32(argc));
+ Assembler::PointerToValue(result), Assembler::Reference(base), Assembler::PointerToString(name),
+ baseAddressForCallData());
}
void InstructionSelection::constructValue(V4IR::Temp *value, V4IR::ExprList *args, V4IR::Temp *result)
{
assert(value != 0);
- int argc = prepareVariableArguments(args);
- generateFunctionCall(Assembler::Void, __qmljs_construct_value, Assembler::ContextRegister,
- Assembler::PointerToValue(result), Assembler::Reference(value), baseAddressForCallArguments(), Assembler::TrustedImm32(argc));
+ int argc = prepareCallData(args, 0);
+ generateFunctionCall(Assembler::Void, __qmljs_construct_value,
+ Assembler::ContextRegister, Assembler::PointerToValue(result),
+ Assembler::Reference(value),
+ baseAddressForCallData());
}
void InstructionSelection::visitJump(V4IR::Jump *s)
@@ -1740,7 +1752,12 @@ void InstructionSelection::visitRet(V4IR::Ret *s)
Q_UNUSED(s);
}
- _as->leaveStandardStackFrame(/*withLocals*/true);
+ const int locals = _as->stackLayout().calculateJSStackFrameSize();
+ _as->subPtr(Assembler::TrustedImm32(sizeof(QV4::Value)*locals), Assembler::LocalsRegister);
+ _as->loadPtr(Address(Assembler::ContextRegister, offsetof(ExecutionContext, engine)), Assembler::ScratchRegister);
+ _as->storePtr(Assembler::LocalsRegister, Address(Assembler::ScratchRegister, offsetof(ExecutionEngine, jsStackTop)));
+
+ _as->leaveStandardStackFrame();
#if !defined(ARGUMENTS_IN_REGISTERS) && !defined(RETURN_VALUE_IN_REGISTER)
// Emulate ret(n) instruction
// Pop off return address into scratch register ...
@@ -1769,17 +1786,33 @@ int InstructionSelection::prepareVariableArguments(V4IR::ExprList* args)
return argc;
}
-void InstructionSelection::callRuntimeMethodImp(V4IR::Temp *result, const char* name, ActivationMethod method, V4IR::Expr *base, V4IR::ExprList *args)
+int InstructionSelection::prepareCallData(V4IR::ExprList* args, V4IR::Expr *thisObject)
{
- V4IR::Name *baseName = base->asName();
- assert(baseName != 0);
+ int argc = 0;
+ for (V4IR::ExprList *it = args; it; it = it->next) {
+ ++argc;
+ }
+
+ Pointer p = _as->stackLayout().callDataAddress(offsetof(CallData, tag));
+ _as->store32(Assembler::TrustedImm32(0), p);
+ p = _as->stackLayout().callDataAddress(offsetof(CallData, argc));
+ _as->store32(Assembler::TrustedImm32(argc), p);
+ p = _as->stackLayout().callDataAddress(offsetof(CallData, thisObject));
+ if (!thisObject)
+ _as->storeValue(QV4::Value::undefinedValue(), p);
+ else
+ _as->copyValue(p, thisObject);
- int argc = prepareVariableArguments(args);
- _as->generateFunctionCallImp(Assembler::Void, name, method, Assembler::ContextRegister, Assembler::PointerToValue(result),
- Assembler::PointerToString(*baseName->id), baseAddressForCallArguments(),
- Assembler::TrustedImm32(argc));
+ int i = 0;
+ for (V4IR::ExprList *it = args; it; it = it->next, ++i) {
+ V4IR::Expr *arg = it->expr;
+ Q_ASSERT(arg != 0);
+ _as->copyValue(_as->stackLayout().argumentAddressForCall(i), arg);
+ }
+ return argc;
}
+
QT_BEGIN_NAMESPACE
namespace QV4 {
bool operator==(const Value &v1, const Value &v2)
diff --git a/src/qml/compiler/qv4isel_masm_p.h b/src/qml/compiler/qv4isel_masm_p.h
index 588e26a566..ec6780a6f3 100644
--- a/src/qml/compiler/qv4isel_masm_p.h
+++ b/src/qml/compiler/qv4isel_masm_p.h
@@ -269,7 +269,7 @@ public:
public:
StackLayout(V4IR::Function *function, int maxArgCountForBuiltins)
: calleeSavedRegCount(Assembler::calleeSavedRegisterCount + 1)
- , maxOutgoingArgumentCount(qMax(function->maxNumberOfArguments, maxArgCountForBuiltins))
+ , maxOutgoingArgumentCount(function->maxNumberOfArguments)
, localCount(function->tempCount)
, savedConstCount(maxArgCountForBuiltins)
{
@@ -289,15 +289,13 @@ public:
#endif
}
- int calculateStackFrameSize(bool withLocals) const
+ int calculateStackFrameSize() const
{
const int stackSpaceAllocatedOtherwise = StackSpaceAllocatedUponFunctionEntry
+ RegisterSize; // saved StackFrameRegister
- const int locals = withLocals ? (maxOutgoingArgumentCount + localCount + savedConstCount) : 0;
-
- // space for the locals and the callee saved registers
- int frameSize = locals * sizeof(QV4::Value) + RegisterSize * calleeSavedRegisterCount;
+ // space for the callee saved registers
+ int frameSize = RegisterSize * (calleeSavedRegisterCount + savedConstCount);
frameSize = WTF::roundUpToMultipleOf(StackAlignment, frameSize + stackSpaceAllocatedOtherwise);
frameSize -= stackSpaceAllocatedOtherwise;
@@ -305,12 +303,19 @@ public:
return frameSize;
}
+ int calculateJSStackFrameSize() const
+ {
+ const int locals = (localCount + sizeof(QV4::CallData)/sizeof(QV4::Value) - 1 + maxOutgoingArgumentCount) + 1;
+ int frameSize = locals * sizeof(QV4::Value);
+ return frameSize;
+ }
+
Address stackSlotPointer(int idx) const
{
Q_ASSERT(idx >= 0);
Q_ASSERT(idx < localCount);
- Pointer addr = argumentAddressForCall(0);
+ Pointer addr = callDataAddress(0);
addr.offset -= sizeof(QV4::Value) * (idx + 1);
return addr;
}
@@ -323,8 +328,11 @@ public:
Q_ASSERT(argument < maxOutgoingArgumentCount);
const int index = maxOutgoingArgumentCount - argument;
- return Pointer(Assembler::LocalsRegister,
- sizeof(QV4::Value) * (-index) - calleeSavedRegisterSpace());
+ return Pointer(Assembler::LocalsRegister, sizeof(QV4::Value) * (-index));
+ }
+
+ Pointer callDataAddress(int offset = 0) const {
+ return Pointer(Assembler::LocalsRegister, -(sizeof(QV4::CallData) + sizeof(QV4::Value) * (maxOutgoingArgumentCount - 1)) + offset);
}
Address savedRegPointer(int offset) const
@@ -431,6 +439,38 @@ public:
return Pointer(_stackLayout.stackSlotPointer(t->index));
}
+ template <int argumentNumber>
+ void saveOutRegister(PointerToValue arg)
+ {
+ if (!arg.value)
+ return;
+ if (V4IR::Temp *t = arg.value->asTemp()) {
+ if (t->kind == V4IR::Temp::PhysicalRegister) {
+ Pointer addr(_stackLayout.savedRegPointer(argumentNumber));
+ switch (t->type) {
+ case V4IR::BoolType:
+ storeBool((RegisterID) t->index, addr);
+ break;
+ case V4IR::SInt32Type:
+ storeInt32((RegisterID) t->index, addr);
+ break;
+ case V4IR::UInt32Type:
+ storeUInt32((RegisterID) t->index, addr);
+ break;
+ case V4IR::DoubleType:
+ storeDouble((FPRegisterID) t->index, addr);
+ break;
+ default:
+ Q_UNIMPLEMENTED();
+ }
+ }
+ }
+ }
+
+ template <int, typename ArgType>
+ void saveOutRegister(ArgType)
+ {}
+
void loadArgumentInRegister(RegisterID source, RegisterID dest, int argumentNumber)
{
Q_UNUSED(argumentNumber);
@@ -684,8 +724,8 @@ public:
void storeValue(QV4::Value value, V4IR::Temp* temp);
- void enterStandardStackFrame(bool withLocals);
- void leaveStandardStackFrame(bool withLocals);
+ void enterStandardStackFrame();
+ void leaveStandardStackFrame();
template <int argumentNumber, typename T>
void loadArgumentOnStackOrRegister(const T &value)
@@ -747,6 +787,15 @@ public:
sub32(TrustedImm32(stackSpaceNeeded), StackPointerRegister);
}
+ // First save any arguments that reside in registers, because they could be overwritten
+ // if that register is also used to pass arguments.
+ saveOutRegister<5>(arg6);
+ saveOutRegister<4>(arg5);
+ saveOutRegister<3>(arg4);
+ saveOutRegister<2>(arg3);
+ saveOutRegister<1>(arg2);
+ saveOutRegister<0>(arg1);
+
loadArgumentOnStackOrRegister<5>(arg6);
loadArgumentOnStackOrRegister<4>(arg5);
loadArgumentOnStackOrRegister<3>(arg4);
@@ -967,25 +1016,8 @@ public:
if (t->kind != V4IR::Temp::PhysicalRegister)
return loadTempAddress(tmpReg, t);
- Pointer addr(_stackLayout.savedRegPointer(offset));
- switch (t->type) {
- case V4IR::BoolType:
- storeBool((RegisterID) t->index, addr);
- break;
- case V4IR::SInt32Type:
- storeInt32((RegisterID) t->index, addr);
- break;
- case V4IR::UInt32Type:
- storeUInt32((RegisterID) t->index, addr);
- break;
- case V4IR::DoubleType:
- storeDouble((FPRegisterID) t->index, addr);
- break;
- default:
- Q_UNIMPLEMENTED();
- }
- return addr;
+ return Pointer(_stackLayout.savedRegPointer(offset));
}
void storeBool(RegisterID reg, Pointer addr)
@@ -1226,6 +1258,11 @@ protected:
return _as->stackLayout().argumentAddressForCall(0);
}
+ Pointer baseAddressForCallData()
+ {
+ return _as->stackLayout().callDataAddress();
+ }
+
virtual void constructActivationProperty(V4IR::Name *func, V4IR::ExprList *args, V4IR::Temp *result);
virtual void constructProperty(V4IR::Temp *base, const QString &name, V4IR::ExprList *args, V4IR::Temp *result);
virtual void constructValue(V4IR::Temp *value, V4IR::ExprList *args, V4IR::Temp *result);
@@ -1300,11 +1337,7 @@ private:
_as->generateFunctionCallImp(t, isel_stringIfy(function), function, __VA_ARGS__)
int prepareVariableArguments(V4IR::ExprList* args);
-
- typedef void (*ActivationMethod)(QV4::ExecutionContext *, QV4::Value *result, QV4::String *name, QV4::Value *args, int argc);
- void callRuntimeMethodImp(V4IR::Temp *result, const char* name, ActivationMethod method, V4IR::Expr *base, V4IR::ExprList *args);
-#define callRuntimeMethod(result, function, ...) \
- callRuntimeMethodImp(result, isel_stringIfy(function), function, __VA_ARGS__)
+ int prepareCallData(V4IR::ExprList* args, V4IR::Expr *thisObject);
template <typename Arg1, typename Arg2>
void generateLookupCall(uint index, uint getterSetterOffset, Arg1 arg1, Arg2 arg2)
diff --git a/src/qml/compiler/qv4isel_moth.cpp b/src/qml/compiler/qv4isel_moth.cpp
index d4dc5460b7..67433070f6 100644
--- a/src/qml/compiler/qv4isel_moth.cpp
+++ b/src/qml/compiler/qv4isel_moth.cpp
@@ -310,7 +310,8 @@ QV4::CompiledData::CompilationUnit *InstructionSelection::backendCompileStep()
void InstructionSelection::callValue(V4IR::Temp *value, V4IR::ExprList *args, V4IR::Temp *result)
{
Instruction::CallValue call;
- prepareCallArgs(args, call.argc, call.args);
+ prepareCallArgs(args, call.argc);
+ call.callData = callDataStart();
call.dest = getParam(value);
call.result = getResultParam(result);
addInstruction(call);
@@ -323,7 +324,8 @@ void InstructionSelection::callProperty(V4IR::Expr *base, const QString &name, V
Instruction::CallProperty call;
call.base = getParam(base);
call.name = registerString(name);
- prepareCallArgs(args, call.argc, call.args);
+ prepareCallArgs(args, call.argc);
+ call.callData = callDataStart();
call.result = getResultParam(result);
addInstruction(call);
}
@@ -335,7 +337,8 @@ void InstructionSelection::callSubscript(V4IR::Expr *base, V4IR::Expr *index, V4
Instruction::CallElement call;
call.base = getParam(base);
call.index = getParam(index);
- prepareCallArgs(args, call.argc, call.args);
+ prepareCallArgs(args, call.argc);
+ call.callData = callDataStart();
call.result = getResultParam(result);
addInstruction(call);
}
@@ -358,7 +361,8 @@ void InstructionSelection::constructActivationProperty(V4IR::Name *func,
{
Instruction::CreateActivationProperty create;
create.name = registerString(*func->id);
- prepareCallArgs(args, create.argc, create.args);
+ prepareCallArgs(args, create.argc);
+ create.callData = callDataStart();
create.result = getResultParam(result);
addInstruction(create);
}
@@ -368,7 +372,8 @@ void InstructionSelection::constructProperty(V4IR::Temp *base, const QString &na
Instruction::CreateProperty create;
create.base = getParam(base);
create.name = registerString(name);
- prepareCallArgs(args, create.argc, create.args);
+ prepareCallArgs(args, create.argc);
+ create.callData = callDataStart();
create.result = getResultParam(result);
addInstruction(create);
}
@@ -377,7 +382,8 @@ void InstructionSelection::constructValue(V4IR::Temp *value, V4IR::ExprList *arg
{
Instruction::CreateValue create;
create.func = getParam(value);
- prepareCallArgs(args, create.argc, create.args);
+ prepareCallArgs(args, create.argc);
+ create.callData = callDataStart();
create.result = getResultParam(result);
addInstruction(create);
}
@@ -666,23 +672,15 @@ void InstructionSelection::inplaceMemberOp(V4IR::AluOp oper, V4IR::Temp *source,
addInstruction(imo);
}
-void InstructionSelection::prepareCallArgs(V4IR::ExprList *e, quint32 &argc, quint32 &args)
+void InstructionSelection::prepareCallArgs(V4IR::ExprList *e, quint32 &argc, quint32 *args)
{
- bool singleArgIsTemp = false;
- if (e && e->next == 0 && e->expr->asTemp()) {
- singleArgIsTemp = e->expr->asTemp()->kind == V4IR::Temp::VirtualRegister;
- }
-
- if (singleArgIsTemp) {
- // We pass single arguments as references to the stack, but only if it's not a local or an argument.
- argc = 1;
- args = getParam(e->expr).index;
- } else if (e) {
+ int argLocation = outgoingArgumentTempStart();
+ argc = 0;
+ if (args)
+ *args = argLocation;
+ if (e) {
// We need to move all the temps into the function arg array
- int argLocation = outgoingArgumentTempStart();
assert(argLocation >= 0);
- argc = 0;
- args = argLocation;
while (e) {
Instruction::MoveTemp move;
move.source = getParam(e->expr);
@@ -692,9 +690,6 @@ void InstructionSelection::prepareCallArgs(V4IR::ExprList *e, quint32 &argc, qui
++argc;
e = e->next;
}
- } else {
- argc = 0;
- args = 0;
}
}
@@ -762,7 +757,8 @@ void InstructionSelection::callBuiltinInvalid(V4IR::Name *func, V4IR::ExprList *
{
Instruction::CallActivationProperty call;
call.name = registerString(*func->id);
- prepareCallArgs(args, call.argc, call.args);
+ prepareCallArgs(args, call.argc);
+ call.callData = callDataStart();
call.result = getResultParam(result);
addInstruction(call);
}
@@ -979,7 +975,7 @@ void InstructionSelection::callBuiltinDefineProperty(V4IR::Temp *object, const Q
void InstructionSelection::callBuiltinDefineArray(V4IR::Temp *result, V4IR::ExprList *args)
{
Instruction::CallBuiltinDefineArray call;
- prepareCallArgs(args, call.argc, call.args);
+ prepareCallArgs(args, call.argc, &call.args);
call.result = getResultParam(result);
addInstruction(call);
}
diff --git a/src/qml/compiler/qv4isel_moth_p.h b/src/qml/compiler/qv4isel_moth_p.h
index c33c58b627..cf7d1f43e9 100644
--- a/src/qml/compiler/qv4isel_moth_p.h
+++ b/src/qml/compiler/qv4isel_moth_p.h
@@ -161,11 +161,12 @@ private:
}
void simpleMove(V4IR::Move *);
- void prepareCallArgs(V4IR::ExprList *, quint32 &, quint32 &);
+ void prepareCallArgs(V4IR::ExprList *, quint32 &, quint32 * = 0);
- int outgoingArgumentTempStart() const { return _function->tempCount; }
- int scratchTempIndex() const { return outgoingArgumentTempStart() + _function->maxNumberOfArguments; }
- int frameSize() const { return scratchTempIndex() + 1; }
+ int scratchTempIndex() const { return _function->tempCount; }
+ int callDataStart() const { return scratchTempIndex() + 1; }
+ int outgoingArgumentTempStart() const { return callDataStart() + offsetof(QV4::CallData, args)/sizeof(QV4::Value); }
+ int frameSize() const { return outgoingArgumentTempStart() + _function->maxNumberOfArguments; }
template <int Instr>
inline ptrdiff_t addInstruction(const InstrData<Instr> &data);
diff --git a/src/qml/compiler/qv4isel_util_p.h b/src/qml/compiler/qv4isel_util_p.h
index 2e3b64c360..610988ce0c 100644
--- a/src/qml/compiler/qv4isel_util_p.h
+++ b/src/qml/compiler/qv4isel_util_p.h
@@ -91,6 +91,8 @@ inline QV4::Value convertToValue(V4IR::Const *c)
default:
Q_UNREACHABLE();
}
+ // unreachable, but the function must return something
+ return QV4::Value::undefinedValue();
}
} // namespace QQmlJS
diff --git a/src/qml/compiler/qv4jsir_p.h b/src/qml/compiler/qv4jsir_p.h
index 1e046b83e3..12f69ac92e 100644
--- a/src/qml/compiler/qv4jsir_p.h
+++ b/src/qml/compiler/qv4jsir_p.h
@@ -183,6 +183,12 @@ enum Type {
StringType = 1 << 7,
ObjectType = 1 << 8
};
+
+inline bool strictlyEqualTypes(Type t1, Type t2)
+{
+ return t1 == t2 || ((t1 & NumberType) && (t2 & NumberType));
+}
+
QString typeName(Type t);
struct ExprVisitor {
diff --git a/src/qml/compiler/qv4regalloc.cpp b/src/qml/compiler/qv4regalloc.cpp
index f82a5fcf1c..1c8bb66fc1 100644
--- a/src/qml/compiler/qv4regalloc.cpp
+++ b/src/qml/compiler/qv4regalloc.cpp
@@ -307,7 +307,6 @@ protected: // IRDecoder
virtual void loadThisObject(V4IR::Temp *temp)
{
addDef(temp);
- addCall(); // FIXME: propagate this
}
virtual void loadConst(V4IR::Const *sourceConst, V4IR::Temp *targetTemp)
@@ -813,8 +812,8 @@ private:
foreach (const Move &m, _moves)
if (m.needsSwap)
++swapCount;
-#endif
Q_ASSERT(output.size() == _moves.size() + swapCount);
+#endif
}
#ifdef DEBUG_REGALLOC
diff --git a/src/qml/compiler/qv4ssa.cpp b/src/qml/compiler/qv4ssa.cpp
index 0b663288ab..528450b73e 100644
--- a/src/qml/compiler/qv4ssa.cpp
+++ b/src/qml/compiler/qv4ssa.cpp
@@ -1419,11 +1419,28 @@ protected:
_ty.fullyTyped &= ty.fullyTyped;
}
- // TODO: check & double check the next condition!
- if (_ty.type & ObjectType || _ty.type & UndefinedType || _ty.type & NullType)
- _ty.type = ObjectType;
- else if (_ty.type & NumberType)
- _ty.type = DoubleType;
+ switch (_ty.type) {
+ case UndefinedType:
+ case NullType:
+ case BoolType:
+ case SInt32Type:
+ case UInt32Type:
+ case DoubleType:
+ case StringType:
+ case ObjectType:
+ // The type is not a combination of two or more types, so we're done.
+ break;
+
+ default:
+ // There are multiple types involved, so:
+ if ((_ty.type & NumberType) && !(_ty.type & ~NumberType))
+ // The type is any combination of double/int32/uint32, but nothing else. So we can
+ // type it as double.
+ _ty.type = DoubleType;
+ else
+ // There just is no single type that can hold this combination, so:
+ _ty.type = ObjectType;
+ }
setType(s->targetTemp, _ty.type);
}
@@ -2083,6 +2100,67 @@ void purgeBB(BasicBlock *bb, Function *func, DefUsesCalculator &defUses, QVector
delete bb;
}
}
+
+bool tryOptimizingComparison(Expr *&expr)
+{
+ Binop *b = expr->asBinop();
+ if (!b)
+ return false;
+ Const *leftConst = b->left->asConst();
+ if (!leftConst || leftConst->type == StringType || leftConst->type == ObjectType)
+ return false;
+ Const *rightConst = b->right->asConst();
+ if (!rightConst || rightConst->type == StringType || rightConst->type == ObjectType)
+ return false;
+
+ QV4::Value l = convertToValue(leftConst);
+ QV4::Value r = convertToValue(rightConst);
+
+ switch (b->op) {
+ case OpGt:
+ leftConst->value = __qmljs_cmp_gt(&l, &r);
+ leftConst->type = BoolType;
+ expr = leftConst;
+ return true;
+ case OpLt:
+ leftConst->value = __qmljs_cmp_lt(&l, &r);
+ leftConst->type = BoolType;
+ expr = leftConst;
+ return true;
+ case OpGe:
+ leftConst->value = __qmljs_cmp_ge(&l, &r);
+ leftConst->type = BoolType;
+ expr = leftConst;
+ return true;
+ case OpLe:
+ leftConst->value = __qmljs_cmp_le(&l, &r);
+ leftConst->type = BoolType;
+ expr = leftConst;
+ return true;
+ case OpStrictEqual:
+ if (!strictlyEqualTypes(leftConst->type, rightConst->type))
+ return false;
+ // intentional fall-through
+ case OpEqual:
+ leftConst->value = __qmljs_cmp_eq(&l, &r);
+ leftConst->type = BoolType;
+ expr = leftConst;
+ return true;
+ case OpStrictNotEqual:
+ if (!strictlyEqualTypes(leftConst->type, rightConst->type))
+ return false;
+ // intentional fall-through
+ case OpNotEqual:
+ leftConst->value = __qmljs_cmp_ne(&l, &r);
+ leftConst->type = BoolType;
+ expr = leftConst;
+ return true;
+ default:
+ break;
+ }
+
+ return false;
+}
} // anonymous namespace
void optimizeSSA(Function *function, DefUsesCalculator &defUses)
@@ -2229,7 +2307,61 @@ void optimizeSSA(Function *function, DefUsesCalculator &defUses)
continue;
}
- // TODO: Constant binary expression evaluation
+ if (Binop *b = m->source->asBinop()) {
+ // TODO: More constant binary expression evaluation
+ // TODO: If the result of the move is only used in one single cjump, then
+ // inline the binop into the cjump.
+ Const *leftConst = b->left->asConst();
+ if (!leftConst || leftConst->type == StringType || leftConst->type == ObjectType)
+ continue;
+ Const *rightConst = b->right->asConst();
+ if (!rightConst || rightConst->type == StringType || rightConst->type == ObjectType)
+ continue;
+
+ QV4::Value lc = convertToValue(leftConst);
+ QV4::Value rc = convertToValue(rightConst);
+ double l = __qmljs_to_number(&lc);
+ double r = __qmljs_to_number(&rc);
+
+ switch (b->op) {
+ case OpMul:
+ leftConst->value = l * r;
+ leftConst->type = DoubleType;
+ m->source = leftConst;
+ W += m;
+ break;
+ case OpAdd:
+ leftConst->value = l + r;
+ leftConst->type = DoubleType;
+ m->source = leftConst;
+ W += m;
+ break;
+ case OpSub:
+ leftConst->value = l - r;
+ leftConst->type = DoubleType;
+ m->source = leftConst;
+ W += m;
+ break;
+ case OpDiv:
+ leftConst->value = l / r;
+ leftConst->type = DoubleType;
+ m->source = leftConst;
+ W += m;
+ break;
+ case OpMod:
+ leftConst->value = std::fmod(l, r);
+ leftConst->type = DoubleType;
+ m->source = leftConst;
+ W += m;
+ break;
+ default:
+ if (tryOptimizingComparison(m->source))
+ W += m;
+ break;
+ }
+
+ continue;
+ }
}
} else if (CJump *cjump = s->asCJump()) {
if (Const *c = cjump->cond->asConst()) {
@@ -2246,9 +2378,12 @@ void optimizeSSA(Function *function, DefUsesCalculator &defUses)
*ref[s] = jump;
continue;
+ } else if (cjump->cond->asBinop()) {
+ if (tryOptimizingComparison(cjump->cond))
+ W += cjump;
+ continue;
}
// TODO: Constant unary expression evaluation
- // TODO: Constant binary expression evaluation
}
}
@@ -2580,9 +2715,10 @@ void Optimizer::run()
// showMeTheCode(function);
+ static bool doSSA = /*qgetenv("QV4_NO_SSA").isEmpty();*/ false;
static bool doOpt = qgetenv("QV4_NO_OPT").isEmpty();
- if (!function->hasTry && !function->hasWith && doOpt) {
+ if (!function->hasTry && !function->hasWith && doSSA) {
// qout << "Starting edge splitting..." << endl;
splitCriticalEdges(function);
// showMeTheCode(function);
@@ -2605,9 +2741,11 @@ void Optimizer::run()
DeadCodeElimination(defUses, function).run();
// showMeTheCode(function);
-// qout << "Running SSA optimization..." << endl;
- optimizeSSA(function, defUses);
-// showMeTheCode(function);
+ if (doOpt) {
+// qout << "Running SSA optimization..." << endl;
+ optimizeSSA(function, defUses);
+// showMeTheCode(function);
+ }
// qout << "Running type inference..." << endl;
TypeInference(defUses).run(function);
diff --git a/src/qml/jsapi/qjsvalue.cpp b/src/qml/jsapi/qjsvalue.cpp
index b737ee0073..f18814cedf 100644
--- a/src/qml/jsapi/qjsvalue.cpp
+++ b/src/qml/jsapi/qjsvalue.cpp
@@ -55,6 +55,7 @@
#include "private/qv8engine_p.h"
#include <private/qv4mm_p.h>
#include <private/qv4exception_p.h>
+#include <private/qv4scopedvalue_p.h>
QV4::Value QJSValuePrivate::getValue(QV4::ExecutionEngine *e)
{
@@ -505,20 +506,20 @@ QJSValue QJSValue::call(const QJSValueList &args)
ExecutionEngine *engine = d->engine;
assert(engine);
- CALLDATA(args.length());
- d.thisObject = Value::fromObject(engine->globalObject);
+ ScopedCallData callData(engine, args.length());
+ callData->thisObject = Value::fromObject(engine->globalObject);
for (int i = 0; i < args.size(); ++i) {
if (!args.at(i).d->checkEngine(engine)) {
qWarning("QJSValue::call() failed: cannot call function with argument created in a different engine");
return QJSValue();
}
- d.args[i] = args.at(i).d->getValue(engine);
+ callData->args[i] = args.at(i).d->getValue(engine);
}
Value result;
QV4::ExecutionContext *ctx = engine->current;
try {
- result = f->call(d);
+ result = f->call(callData);
} catch (Exception &e) {
e.accept(ctx);
result = e.value();
@@ -561,20 +562,20 @@ QJSValue QJSValue::callWithInstance(const QJSValue &instance, const QJSValueList
return QJSValue();
}
- CALLDATA(args.size());
- d.thisObject = instance.d->getValue(engine);
+ ScopedCallData callData(engine, args.size());
+ callData->thisObject = instance.d->getValue(engine);
for (int i = 0; i < args.size(); ++i) {
if (!args.at(i).d->checkEngine(engine)) {
qWarning("QJSValue::call() failed: cannot call function with argument created in a different engine");
return QJSValue();
}
- d.args[i] = args.at(i).d->getValue(engine);
+ callData->args[i] = args.at(i).d->getValue(engine);
}
Value result;
QV4::ExecutionContext *ctx = engine->current;
try {
- result = f->call(d);
+ result = f->call(callData);
} catch (Exception &e) {
e.accept(ctx);
result = e.value();
@@ -610,19 +611,19 @@ QJSValue QJSValue::callAsConstructor(const QJSValueList &args)
ExecutionEngine *engine = d->engine;
assert(engine);
- CALLDATA(args.size());
+ ScopedCallData callData(engine, args.size());
for (int i = 0; i < args.size(); ++i) {
if (!args.at(i).d->checkEngine(engine)) {
qWarning("QJSValue::callAsConstructor() failed: cannot construct function with argument created in a different engine");
return QJSValue();
}
- d.args[i] = args.at(i).d->getValue(engine);
+ callData->args[i] = args.at(i).d->getValue(engine);
}
Value result;
QV4::ExecutionContext *ctx = engine->current;
try {
- result = f->construct(d);
+ result = f->construct(callData);
} catch (Exception &e) {
e.accept(ctx);
result = e.value();
@@ -742,7 +743,7 @@ QJSValue& QJSValue::operator=(const QJSValue& other)
*/
bool QJSValue::equals(const QJSValue& other) const
{
- return __qmljs_cmp_eq(d->value, other.d->value);
+ return __qmljs_cmp_eq(QV4::ValueRef(d), QV4::ValueRef(other.d));
}
/*!
@@ -769,7 +770,7 @@ bool QJSValue::equals(const QJSValue& other) const
*/
bool QJSValue::strictlyEquals(const QJSValue& other) const
{
- return __qmljs_strict_equal(d->value, other.d->value);
+ return __qmljs_strict_equal(QV4::ValueRef(d), QV4::ValueRef(other.d));
}
/*!
diff --git a/src/qml/jsruntime/jsruntime.pri b/src/qml/jsruntime/jsruntime.pri
index 9a1325b58a..c504f750e9 100644
--- a/src/qml/jsruntime/jsruntime.pri
+++ b/src/qml/jsruntime/jsruntime.pri
@@ -90,6 +90,7 @@ HEADERS += \
$$PWD/qv4unwindhelper_arm_p.h \
$$PWD/qv4serialize_p.h \
$$PWD/qv4script_p.h \
+ $$PWD/qv4scopedvalue_p.h \
$$PWD/qv4util_p.h \
$$PWD/qv4executableallocator_p.h \
$$PWD/qv4sequenceobject_p.h \
diff --git a/src/qml/jsruntime/qv4argumentsobject.cpp b/src/qml/jsruntime/qv4argumentsobject.cpp
index 7ac74c1197..5a53c0fc3e 100644
--- a/src/qml/jsruntime/qv4argumentsobject.cpp
+++ b/src/qml/jsruntime/qv4argumentsobject.cpp
@@ -40,6 +40,7 @@
****************************************************************************/
#include <qv4argumentsobject_p.h>
#include <qv4alloca_p.h>
+#include <qv4scopedvalue_p.h>
using namespace QV4;
@@ -129,10 +130,10 @@ bool ArgumentsObject::defineOwnProperty(ExecutionContext *ctx, uint index, const
if (isMapped && attrs.isData()) {
if (!attrs.isGeneric()) {
- CALLDATA(1);
- d.thisObject = Value::fromObject(this);
- d.args[0] = desc.value;
- map.setter()->call(d);
+ ScopedCallData callData(ctx->engine, 1);
+ callData->thisObject = Value::fromObject(this);
+ callData->args[0] = desc.value;
+ map.setter()->call(callData);
}
if (attrs.isWritable()) {
*pd = map;
@@ -147,10 +148,10 @@ bool ArgumentsObject::defineOwnProperty(ExecutionContext *ctx, uint index, const
DEFINE_MANAGED_VTABLE(ArgumentsGetterFunction);
-Value ArgumentsGetterFunction::call(Managed *getter, const CallData &d)
+Value ArgumentsGetterFunction::call(Managed *getter, CallData *callData)
{
ArgumentsGetterFunction *g = static_cast<ArgumentsGetterFunction *>(getter);
- Object *that = d.thisObject.asObject();
+ Object *that = callData->thisObject.asObject();
if (!that)
getter->engine()->current->throwTypeError();
ArgumentsObject *o = that->asArgumentsObject();
@@ -163,10 +164,10 @@ Value ArgumentsGetterFunction::call(Managed *getter, const CallData &d)
DEFINE_MANAGED_VTABLE(ArgumentsSetterFunction);
-Value ArgumentsSetterFunction::call(Managed *setter, const CallData &d)
+Value ArgumentsSetterFunction::call(Managed *setter, CallData *callData)
{
ArgumentsSetterFunction *s = static_cast<ArgumentsSetterFunction *>(setter);
- Object *that = d.thisObject.asObject();
+ Object *that = callData->thisObject.asObject();
if (!that)
setter->engine()->current->throwTypeError();
ArgumentsObject *o = that->asArgumentsObject();
@@ -174,7 +175,7 @@ Value ArgumentsSetterFunction::call(Managed *setter, const CallData &d)
setter->engine()->current->throwTypeError();
assert(s->index < o->context->argumentCount);
- o->context->arguments[s->index] = d.argc ? d.args[0] : Value::undefinedValue();
+ o->context->arguments[s->index] = callData->argc ? callData->args[0] : Value::undefinedValue();
return Value::undefinedValue();
}
diff --git a/src/qml/jsruntime/qv4argumentsobject_p.h b/src/qml/jsruntime/qv4argumentsobject_p.h
index f48db1f2e6..66ee22c953 100644
--- a/src/qml/jsruntime/qv4argumentsobject_p.h
+++ b/src/qml/jsruntime/qv4argumentsobject_p.h
@@ -55,7 +55,7 @@ struct ArgumentsGetterFunction: FunctionObject
ArgumentsGetterFunction(ExecutionContext *scope, uint index)
: FunctionObject(scope), index(index) { vtbl = &static_vtbl; }
- static Value call(Managed *that, const CallData &d);
+ static Value call(Managed *that, CallData *d);
protected:
static const ManagedVTable static_vtbl;
@@ -68,7 +68,7 @@ struct ArgumentsSetterFunction: FunctionObject
ArgumentsSetterFunction(ExecutionContext *scope, uint index)
: FunctionObject(scope), index(index) { vtbl = &static_vtbl; }
- static Value call(Managed *that, const CallData &d);
+ static Value call(Managed *that, CallData *callData);
protected:
static const ManagedVTable static_vtbl;
diff --git a/src/qml/jsruntime/qv4arrayobject.cpp b/src/qml/jsruntime/qv4arrayobject.cpp
index 6fc661565d..e3b08f5941 100644
--- a/src/qml/jsruntime/qv4arrayobject.cpp
+++ b/src/qml/jsruntime/qv4arrayobject.cpp
@@ -42,6 +42,7 @@
#include "qv4arrayobject_p.h"
#include "qv4sparsearray_p.h"
#include "qv4objectproto_p.h"
+#include "qv4scopedvalue_p.h"
using namespace QV4;
@@ -53,25 +54,25 @@ ArrayCtor::ArrayCtor(ExecutionContext *scope)
vtbl = &static_vtbl;
}
-Value ArrayCtor::construct(Managed *m, const CallData &d)
+Value ArrayCtor::construct(Managed *m, CallData *callData)
{
ExecutionEngine *v4 = m->engine();
ArrayObject *a = v4->newArrayObject();
uint len;
- if (d.argc == 1 && d.args[0].isNumber()) {
+ if (callData->argc == 1 && callData->args[0].isNumber()) {
bool ok;
- len = d.args[0].asArrayLength(&ok);
+ len = callData->args[0].asArrayLength(&ok);
if (!ok)
- v4->current->throwRangeError(d.args[0]);
+ v4->current->throwRangeError(callData->args[0]);
if (len < 0x1000)
a->arrayReserve(len);
} else {
- len = d.argc;
+ len = callData->argc;
a->arrayReserve(len);
for (unsigned int i = 0; i < len; ++i)
- a->arrayData[i].value = d.args[i];
+ a->arrayData[i].value = callData->args[i];
a->arrayDataLen = len;
}
a->setArrayLengthUnchecked(len);
@@ -79,9 +80,9 @@ Value ArrayCtor::construct(Managed *m, const CallData &d)
return Value::fromObject(a);
}
-Value ArrayCtor::call(Managed *that, const CallData &d)
+Value ArrayCtor::call(Managed *that, CallData *callData)
{
- return construct(that, d);
+ return construct(that, callData);
}
ArrayPrototype::ArrayPrototype(InternalClass *ic)
@@ -137,8 +138,8 @@ Value ArrayPrototype::method_toString(SimpleCallContext *ctx)
QV4::Object *o = ctx->thisObject.toObject(ctx);
FunctionObject *f = o->get(ctx->engine->newString("join")).asFunctionObject();
if (f) {
- CALLDATA(0);
- d.thisObject = ctx->thisObject;
+ ScopedCallData d(ctx->engine, 0);
+ d->thisObject = ctx->thisObject;
return f->call(d);
}
return ObjectPrototype::method_toString(ctx);
@@ -545,12 +546,14 @@ Value ArrayPrototype::method_unshift(SimpleCallContext *ctx)
Value ArrayPrototype::method_indexOf(SimpleCallContext *ctx)
{
+ ValueScope scope(ctx);
+
Object *instance = ctx->thisObject.toObject(ctx);
uint len = getLength(ctx, instance);
if (!len)
return Value::fromInt32(-1);
- Value searchValue;
+ ScopedValue searchValue(scope);
uint fromIndex = 0;
if (ctx->argumentCount >= 1)
@@ -568,9 +571,10 @@ Value ArrayPrototype::method_indexOf(SimpleCallContext *ctx)
}
if (instance->isStringObject()) {
+ ScopedValue v(scope);
for (uint k = fromIndex; k < len; ++k) {
bool exists;
- Value v = instance->getIndexed(k, &exists);
+ v = instance->getIndexed(k, &exists);
if (exists && __qmljs_strict_equal(v, searchValue))
return Value::fromDouble(k);
}
@@ -582,12 +586,14 @@ Value ArrayPrototype::method_indexOf(SimpleCallContext *ctx)
Value ArrayPrototype::method_lastIndexOf(SimpleCallContext *ctx)
{
+ ValueScope scope(ctx);
+
Object *instance = ctx->thisObject.toObject(ctx);
uint len = getLength(ctx, instance);
if (!len)
return Value::fromInt32(-1);
- Value searchValue;
+ ScopedValue searchValue(scope);
uint fromIndex = len;
if (ctx->argumentCount >= 1)
@@ -607,10 +613,11 @@ Value ArrayPrototype::method_lastIndexOf(SimpleCallContext *ctx)
fromIndex = (uint) f + 1;
}
+ ScopedValue v(scope);
for (uint k = fromIndex; k > 0;) {
--k;
bool exists;
- Value v = instance->getIndexed(k, &exists);
+ v = instance->getIndexed(k, &exists);
if (exists && __qmljs_strict_equal(v, searchValue))
return Value::fromDouble(k);
}
@@ -636,12 +643,12 @@ Value ArrayPrototype::method_every(SimpleCallContext *ctx)
if (!exists)
continue;
- CALLDATA(3);
- d.args[0] = v;
- d.args[1] = Value::fromDouble(k);
- d.args[2] = Value::fromObject(instance);
- d.thisObject = thisArg;
- Value r = callback->call(d);
+ ScopedCallData callData(ctx->engine, 3);
+ callData->args[0] = v;
+ callData->args[1] = Value::fromDouble(k);
+ callData->args[2] = Value::fromObject(instance);
+ callData->thisObject = thisArg;
+ Value r = callback->call(callData);
ok = r.toBoolean();
}
return Value::fromBoolean(ok);
@@ -665,12 +672,12 @@ Value ArrayPrototype::method_some(SimpleCallContext *ctx)
if (!exists)
continue;
- CALLDATA(3);
- d.args[0] = v;
- d.args[1] = Value::fromDouble(k);
- d.args[2] = Value::fromObject(instance);
- d.thisObject = thisArg;
- Value r = callback->call(d);
+ ScopedCallData callData(ctx->engine, 3);
+ callData->thisObject = thisArg;
+ callData->args[0] = v;
+ callData->args[1] = Value::fromDouble(k);
+ callData->args[2] = Value::fromObject(instance);
+ Value r = callback->call(callData);
if (r.toBoolean())
return Value::fromBoolean(true);
}
@@ -695,12 +702,12 @@ Value ArrayPrototype::method_forEach(SimpleCallContext *ctx)
if (!exists)
continue;
- CALLDATA(3);
- d.args[0] = v;
- d.args[1] = Value::fromDouble(k);
- d.args[2] = Value::fromObject(instance);
- d.thisObject = thisArg;
- callback->call(d);
+ ScopedCallData callData(ctx->engine, 3);
+ callData->thisObject = thisArg;
+ callData->args[0] = v;
+ callData->args[1] = Value::fromDouble(k);
+ callData->args[2] = Value::fromObject(instance);
+ callback->call(callData);
}
return Value::undefinedValue();
}
@@ -727,12 +734,12 @@ Value ArrayPrototype::method_map(SimpleCallContext *ctx)
if (!exists)
continue;
- CALLDATA(3);
- d.args[0] = v;
- d.args[1] = Value::fromDouble(k);
- d.args[2] = Value::fromObject(instance);
- d.thisObject = thisArg;
- Value mapped = callback->call(d);
+ ScopedCallData callData(ctx->engine, 3);
+ callData->thisObject = thisArg;
+ callData->args[0] = v;
+ callData->args[1] = Value::fromDouble(k);
+ callData->args[2] = Value::fromObject(instance);
+ Value mapped = callback->call(callData);
a->arraySet(k, mapped);
}
return Value::fromObject(a);
@@ -760,12 +767,12 @@ Value ArrayPrototype::method_filter(SimpleCallContext *ctx)
if (!exists)
continue;
- CALLDATA(3);
- d.args[0] = v;
- d.args[1] = Value::fromDouble(k);
- d.args[2] = Value::fromObject(instance);
- d.thisObject = thisArg;
- Value selected = callback->call(d);
+ ScopedCallData callData(ctx->engine, 3);
+ callData->thisObject = thisArg;
+ callData->args[0] = v;
+ callData->args[1] = Value::fromDouble(k);
+ callData->args[2] = Value::fromObject(instance);
+ Value selected = callback->call(callData);
if (selected.toBoolean()) {
a->arraySet(to, v);
++to;
@@ -804,13 +811,13 @@ Value ArrayPrototype::method_reduce(SimpleCallContext *ctx)
bool kPresent;
Value v = instance->getIndexed(k, &kPresent);
if (kPresent) {
- CALLDATA(4);
- d.args[0] = acc;
- d.args[1] = v;
- d.args[2] = Value::fromDouble(k);
- d.args[3] = Value::fromObject(instance);
- d.thisObject = Value::undefinedValue();
- acc = callback->call(d);
+ ScopedCallData callData(ctx->engine, 4);
+ callData->thisObject = Value::undefinedValue();
+ callData->args[0] = acc;
+ callData->args[1] = v;
+ callData->args[2] = Value::fromDouble(k);
+ callData->args[3] = Value::fromObject(instance);
+ acc = callback->call(callData);
}
++k;
}
@@ -853,13 +860,13 @@ Value ArrayPrototype::method_reduceRight(SimpleCallContext *ctx)
bool kPresent;
Value v = instance->getIndexed(k - 1, &kPresent);
if (kPresent) {
- CALLDATA(4);
- d.args[0] = acc;
- d.args[1] = v;
- d.args[2] = Value::fromDouble(k - 1);
- d.args[3] = Value::fromObject(instance);
- d.thisObject = Value::undefinedValue();
- acc = callback->call(d);
+ ScopedCallData callData(ctx->engine, 4);
+ callData->thisObject = Value::undefinedValue();
+ callData->args[0] = acc;
+ callData->args[1] = v;
+ callData->args[2] = Value::fromDouble(k - 1);
+ callData->args[3] = Value::fromObject(instance);
+ acc = callback->call(callData);
}
--k;
}
diff --git a/src/qml/jsruntime/qv4arrayobject_p.h b/src/qml/jsruntime/qv4arrayobject_p.h
index 0d76542535..354ddd0380 100644
--- a/src/qml/jsruntime/qv4arrayobject_p.h
+++ b/src/qml/jsruntime/qv4arrayobject_p.h
@@ -53,8 +53,8 @@ struct ArrayCtor: FunctionObject
{
ArrayCtor(ExecutionContext *scope);
- static Value construct(Managed *m, const CallData &d);
- static Value call(Managed *that, const CallData &d);
+ static Value construct(Managed *m, CallData *callData);
+ static Value call(Managed *that, CallData *callData);
protected:
static const ManagedVTable static_vtbl;
diff --git a/src/qml/jsruntime/qv4booleanobject.cpp b/src/qml/jsruntime/qv4booleanobject.cpp
index 25c105210a..6b77db3ca7 100644
--- a/src/qml/jsruntime/qv4booleanobject.cpp
+++ b/src/qml/jsruntime/qv4booleanobject.cpp
@@ -51,15 +51,15 @@ BooleanCtor::BooleanCtor(ExecutionContext *scope)
vtbl = &static_vtbl;
}
-Value BooleanCtor::construct(Managed *m, const CallData &d)
+Value BooleanCtor::construct(Managed *m, CallData *callData)
{
- bool n = d.argc ? d.args[0].toBoolean() : false;
+ bool n = callData->argc ? callData->args[0].toBoolean() : false;
return Value::fromObject(m->engine()->newBooleanObject(Value::fromBoolean(n)));
}
-Value BooleanCtor::call(Managed *, const CallData &d)
+Value BooleanCtor::call(Managed *, CallData *callData)
{
- bool value = d.argc ? d.args[0].toBoolean() : 0;
+ bool value = callData->argc ? callData->args[0].toBoolean() : 0;
return Value::fromBoolean(value);
}
diff --git a/src/qml/jsruntime/qv4booleanobject_p.h b/src/qml/jsruntime/qv4booleanobject_p.h
index b55f82b76f..35ecf25b6f 100644
--- a/src/qml/jsruntime/qv4booleanobject_p.h
+++ b/src/qml/jsruntime/qv4booleanobject_p.h
@@ -53,8 +53,8 @@ struct BooleanCtor: FunctionObject
{
BooleanCtor(ExecutionContext *scope);
- static Value construct(Managed *, const CallData &d);
- static Value call(Managed *that, const CallData &d);
+ static Value construct(Managed *, CallData *callData);
+ static Value call(Managed *that, CallData *callData);
protected:
static const ManagedVTable static_vtbl;
diff --git a/src/qml/jsruntime/qv4context.cpp b/src/qml/jsruntime/qv4context.cpp
index 29fdc333f8..1e42a186a0 100644
--- a/src/qml/jsruntime/qv4context.cpp
+++ b/src/qml/jsruntime/qv4context.cpp
@@ -51,7 +51,7 @@
using namespace QV4;
-CallContext *ExecutionContext::newCallContext(void *stackSpace, FunctionObject *function, const CallData &d)
+CallContext *ExecutionContext::newCallContext(void *stackSpace, FunctionObject *function, CallData *callData)
{
CallContext *c = (CallContext *)stackSpace;
#ifndef QT_NO_DEBUG
@@ -63,10 +63,11 @@ CallContext *ExecutionContext::newCallContext(void *stackSpace, FunctionObject *
c->initBaseContext(Type_CallContext, engine, this);
c->function = function;
- c->arguments = d.args;
- c->realArgumentCount = d.argc;
- c->argumentCount = d.argc;
- c->thisObject = d.thisObject;
+ // ###
+ c->arguments = const_cast<Value *>(callData->args);
+ c->realArgumentCount = callData->argc;
+ c->argumentCount = callData->argc;
+ c->thisObject = callData->thisObject;
c->strictMode = function->strictMode;
c->marked = false;
@@ -89,30 +90,28 @@ CallContext *ExecutionContext::newCallContext(void *stackSpace, FunctionObject *
if (function->varCount)
std::fill(c->locals, c->locals + function->varCount, Value::undefinedValue());
- if (d.argc < function->formalParameterCount) {
+ if (callData->argc < function->formalParameterCount) {
#ifndef QT_NO_DEBUG
Q_ASSERT(function->formalParameterCount <= QV4::Global::ReservedArgumentCount);
#endif
- std::fill(c->arguments + d.argc, c->arguments + function->formalParameterCount, Value::undefinedValue());
+ std::fill(c->arguments + callData->argc, c->arguments + function->formalParameterCount, Value::undefinedValue());
c->argumentCount = function->formalParameterCount;
}
return c;
}
-CallContext *ExecutionContext::newCallContext(FunctionObject *function, const CallData &d)
+CallContext *ExecutionContext::newCallContext(FunctionObject *function, CallData *callData)
{
- CallContext *c = static_cast<CallContext *>(engine->memoryManager->allocContext(requiredMemoryForExecutionContect(function, d.argc)));
+ CallContext *c = static_cast<CallContext *>(engine->memoryManager->allocContext(requiredMemoryForExecutionContect(function, callData->argc)));
engine->current = c;
c->initBaseContext(Type_CallContext, engine, this);
c->function = function;
- c->arguments = d.args;
- c->realArgumentCount = d.argc;
- c->argumentCount = d.argc;
- c->thisObject = d.thisObject;
+ c->realArgumentCount = callData->argc;
+ c->thisObject = callData->thisObject;
c->strictMode = function->strictMode;
c->marked = false;
@@ -135,12 +134,12 @@ CallContext *ExecutionContext::newCallContext(FunctionObject *function, const Ca
if (function->varCount)
std::fill(c->locals, c->locals + function->varCount, Value::undefinedValue());
- c->argumentCount = qMax((uint)d.argc, function->formalParameterCount);
+ c->argumentCount = qMax((uint)callData->argc, function->formalParameterCount);
c->arguments = c->locals + function->varCount;
- if (d.argc)
- ::memcpy(c->arguments, d.args, c->realArgumentCount * sizeof(Value));
- if (d.argc < function->formalParameterCount)
- std::fill(c->arguments + d.argc, c->arguments + function->formalParameterCount, Value::undefinedValue());
+ if (callData->argc)
+ ::memcpy(c->arguments, callData->args, callData->argc * sizeof(Value));
+ if (callData->argc < function->formalParameterCount)
+ std::fill(c->arguments + callData->argc, c->arguments + function->formalParameterCount, Value::undefinedValue());
return c;
}
@@ -595,18 +594,11 @@ Value ExecutionContext::getPropertyAndBase(String *name, Object **base)
}
-
-void ExecutionContext::inplaceBitOp(String *name, const Value &value, BinOp op)
-{
- Value lhs = getProperty(name);
- Value result;
- op(&result, lhs, value);
- setProperty(name, result);
-}
-
void ExecutionContext::throwError(const Value &value)
{
- __qmljs_throw(this, value);
+ ValueScope scope(this);
+ ScopedValue v(scope, value);
+ __qmljs_throw(this, v);
}
void ExecutionContext::throwError(const QString &message)
diff --git a/src/qml/jsruntime/qv4context_p.h b/src/qml/jsruntime/qv4context_p.h
index 331c5aa990..fe10e33c5e 100644
--- a/src/qml/jsruntime/qv4context_p.h
+++ b/src/qml/jsruntime/qv4context_p.h
@@ -42,7 +42,8 @@
#define QMLJS_ENVIRONMENT_H
#include "qv4global_p.h"
-#include "qv4runtime_p.h"
+#include "qv4value_def_p.h"
+#include "qv4managed_p.h"
QT_BEGIN_NAMESPACE
@@ -52,6 +53,7 @@ struct Object;
struct ExecutionEngine;
struct DeclarativeEnvironment;
struct Lookup;
+struct Function;
namespace CompiledData {
struct CompilationUnit;
@@ -114,8 +116,8 @@ struct Q_QML_EXPORT ExecutionContext
interpreterInstructionPointer = 0;
}
- CallContext *newCallContext(void *stackSpace, FunctionObject *f, const CallData &d);
- CallContext *newCallContext(FunctionObject *f, const CallData &d);
+ CallContext *newCallContext(void *stackSpace, FunctionObject *f, CallData *callData);
+ CallContext *newCallContext(FunctionObject *f, CallData *callData);
WithContext *newWithContext(Object *with);
CatchContext *newCatchContext(String* exceptionVarName, const QV4::Value &exceptionValue);
CallContext *newQmlContext(FunctionObject *f, Object *qml);
@@ -143,7 +145,6 @@ struct Q_QML_EXPORT ExecutionContext
Value getProperty(String *name);
Value getPropertyNoThrow(String *name);
Value getPropertyAndBase(String *name, Object **base);
- void inplaceBitOp(String *name, const QV4::Value &value, BinOp op);
bool deleteProperty(String *name);
inline Value argument(unsigned int index = 0);
diff --git a/src/qml/jsruntime/qv4dateobject.cpp b/src/qml/jsruntime/qv4dateobject.cpp
index 9f25b8dc40..1ef4aec246 100644
--- a/src/qml/jsruntime/qv4dateobject.cpp
+++ b/src/qml/jsruntime/qv4dateobject.cpp
@@ -42,7 +42,7 @@
#include "qv4dateobject_p.h"
#include "qv4objectproto_p.h"
-#include "qv4mm_p.h"
+#include "qv4scopedvalue_p.h"
#include <QtCore/qnumeric.h>
#include <QtCore/qmath.h>
#include <QtCore/QDateTime>
@@ -55,11 +55,6 @@
#include <time.h>
#include <private/qqmljsengine_p.h>
-#include <private/qqmljslexer_p.h>
-#include <private/qqmljsparser_p.h>
-#include <private/qqmljsast_p.h>
-#include <qv4jsir_p.h>
-#include <qv4codegen_p.h>
#include <wtf/MathExtras.h>
@@ -659,34 +654,35 @@ DateCtor::DateCtor(ExecutionContext *scope)
vtbl = &static_vtbl;
}
-Value DateCtor::construct(Managed *m, const CallData &d)
+Value DateCtor::construct(Managed *m, CallData *callData)
{
double t = 0;
- if (d.argc == 0)
+ if (callData->argc == 0)
t = currentTime();
- else if (d.argc == 1) {
- Value arg = d.args[0];
- if (DateObject *d = arg.asDateObject())
+ else if (callData->argc == 1) {
+ ValueScope scope(m->engine());
+ ScopedValue arg(scope, callData->args[0]);
+ if (DateObject *d = arg->asDateObject())
arg = d->value;
else
arg = __qmljs_to_primitive(arg, PREFERREDTYPE_HINT);
- if (arg.isString())
- t = ParseString(arg.stringValue()->toQString());
+ if (arg->isString())
+ t = ParseString(arg->stringValue()->toQString());
else
- t = TimeClip(arg.toNumber());
+ t = TimeClip(arg->toNumber());
}
else { // d.argc > 1
- double year = d.args[0].toNumber();
- double month = d.args[1].toNumber();
- double day = d.argc >= 3 ? d.args[2].toNumber() : 1;
- double hours = d.argc >= 4 ? d.args[3].toNumber() : 0;
- double mins = d.argc >= 5 ? d.args[4].toNumber() : 0;
- double secs = d.argc >= 6 ? d.args[5].toNumber() : 0;
- double ms = d.argc >= 7 ? d.args[6].toNumber() : 0;
+ double year = callData->args[0].toNumber();
+ double month = callData->args[1].toNumber();
+ double day = callData->argc >= 3 ? callData->args[2].toNumber() : 1;
+ double hours = callData->argc >= 4 ? callData->args[3].toNumber() : 0;
+ double mins = callData->argc >= 5 ? callData->args[4].toNumber() : 0;
+ double secs = callData->argc >= 6 ? callData->args[5].toNumber() : 0;
+ double ms = callData->argc >= 7 ? callData->args[6].toNumber() : 0;
if (year >= 0 && year <= 99)
year += 1900;
t = MakeDate(MakeDay(year, month, day), MakeTime(hours, mins, secs, ms));
@@ -697,7 +693,7 @@ Value DateCtor::construct(Managed *m, const CallData &d)
return Value::fromObject(o);
}
-Value DateCtor::call(Managed *m, const CallData &)
+Value DateCtor::call(Managed *m, CallData *)
{
double t = currentTime();
return Value::fromString(m->engine()->current, ToString(t));
@@ -1295,20 +1291,21 @@ Value DatePrototype::method_toISOString(SimpleCallContext *ctx)
Value DatePrototype::method_toJSON(SimpleCallContext *ctx)
{
- Value O = __qmljs_to_object(ctx, ctx->thisObject);
- Value tv = __qmljs_to_primitive(O, NUMBER_HINT);
+ ValueScope scope(ctx);
+ ScopedValue O(scope, __qmljs_to_object(ctx, ValueRef(&ctx->thisObject)));
+ ScopedValue tv(scope, __qmljs_to_primitive(O, NUMBER_HINT));
- if (tv.isNumber() && !std::isfinite(tv.toNumber()))
+ if (tv->isNumber() && !std::isfinite(tv->toNumber()))
return Value::nullValue();
- FunctionObject *toIso = O.objectValue()->get(ctx->engine->newString(QStringLiteral("toISOString"))).asFunctionObject();
+ FunctionObject *toIso = O->objectValue()->get(ctx->engine->newString(QStringLiteral("toISOString"))).asFunctionObject();
if (!toIso)
ctx->throwTypeError();
- CALLDATA(0);
- d.thisObject = ctx->thisObject;
- return toIso->call(d);
+ ScopedCallData callData(ctx->engine, 0);
+ callData->thisObject = ctx->thisObject;
+ return toIso->call(callData);
}
void DatePrototype::timezoneUpdated()
diff --git a/src/qml/jsruntime/qv4dateobject_p.h b/src/qml/jsruntime/qv4dateobject_p.h
index 238d10849a..573326adc4 100644
--- a/src/qml/jsruntime/qv4dateobject_p.h
+++ b/src/qml/jsruntime/qv4dateobject_p.h
@@ -66,8 +66,8 @@ struct DateCtor: FunctionObject
{
DateCtor(ExecutionContext *scope);
- static Value construct(Managed *, const CallData &d);
- static Value call(Managed *that, const CallData &);
+ static Value construct(Managed *, CallData *callData);
+ static Value call(Managed *that, CallData *);
protected:
static const ManagedVTable static_vtbl;
diff --git a/src/qml/jsruntime/qv4debugging.cpp b/src/qml/jsruntime/qv4debugging.cpp
index 5534305068..10f22a11b8 100644
--- a/src/qml/jsruntime/qv4debugging.cpp
+++ b/src/qml/jsruntime/qv4debugging.cpp
@@ -298,19 +298,27 @@ void DebuggerAgent::removeDebugger(Debugger *debugger)
debugger->detachFromAgent();
}
-void DebuggerAgent::pause(Debugger *debugger)
+void DebuggerAgent::pause(Debugger *debugger) const
{
debugger->pause();
}
-void DebuggerAgent::addBreakPoint(Debugger *debugger, const QString &fileName, int lineNumber)
+void DebuggerAgent::pauseAll() const
{
- debugger->addBreakPoint(fileName, lineNumber);
+ foreach (Debugger *debugger, m_debuggers)
+ pause(debugger);
}
-void DebuggerAgent::removeBreakPoint(Debugger *debugger, const QString &fileName, int lineNumber)
+void DebuggerAgent::addBreakPoint(const QString &fileName, int lineNumber) const
{
- debugger->removeBreakPoint(fileName, lineNumber);
+ foreach (Debugger *debugger, m_debuggers)
+ debugger->addBreakPoint(fileName, lineNumber);
+}
+
+void DebuggerAgent::removeBreakPoint(const QString &fileName, int lineNumber) const
+{
+ foreach (Debugger *debugger, m_debuggers)
+ debugger->removeBreakPoint(fileName, lineNumber);
}
DebuggerAgent::~DebuggerAgent()
diff --git a/src/qml/jsruntime/qv4debugging_p.h b/src/qml/jsruntime/qv4debugging_p.h
index d71b25f378..908854865d 100644
--- a/src/qml/jsruntime/qv4debugging_p.h
+++ b/src/qml/jsruntime/qv4debugging_p.h
@@ -140,9 +140,10 @@ public:
void addDebugger(Debugger *debugger);
void removeDebugger(Debugger *debugger);
- void pause(Debugger *debugger);
- void addBreakPoint(Debugger *debugger, const QString &fileName, int lineNumber);
- void removeBreakPoint(Debugger *debugger, const QString &fileName, int lineNumber);
+ void pause(Debugger *debugger) const;
+ void pauseAll() const;
+ void addBreakPoint(const QString &fileName, int lineNumber) const;
+ void removeBreakPoint(const QString &fileName, int lineNumber) const;
Q_INVOKABLE virtual void debuggerPaused(QV4::Debugging::Debugger *debugger) = 0;
diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp
index ae444ab938..638609de37 100644
--- a/src/qml/jsruntime/qv4engine.cpp
+++ b/src/qml/jsruntime/qv4engine.cpp
@@ -84,6 +84,7 @@ ExecutionEngine::ExecutionEngine(QQmlJS::EvalISelFactory *factory)
, executableAllocator(new QV4::ExecutableAllocator)
, regExpAllocator(new QV4::ExecutableAllocator)
, bumperPointerAllocator(new WTF::BumpPointerAllocator)
+ , jsStack(new WTF::PageAllocation)
, debugger(0)
, globalObject(0)
, globalCode(0)
@@ -95,8 +96,13 @@ ExecutionEngine::ExecutionEngine(QQmlJS::EvalISelFactory *factory)
MemoryManager::GCBlocker gcBlocker(memoryManager);
if (!factory) {
+
#ifdef V4_ENABLE_JIT
- factory = new QQmlJS::MASM::ISelFactory;
+ static const bool forceMoth = !qgetenv("QV4_FORCE_INTERPRETER").isEmpty();
+ if (forceMoth)
+ factory = new QQmlJS::Moth::ISelFactory;
+ else
+ factory = new QQmlJS::MASM::ISelFactory;
#else // !V4_ENABLE_JIT
factory = new QQmlJS::Moth::ISelFactory;
#endif // V4_ENABLE_JIT
@@ -105,6 +111,11 @@ ExecutionEngine::ExecutionEngine(QQmlJS::EvalISelFactory *factory)
memoryManager->setExecutionEngine(this);
+ // reserve 8MB for the JS stack
+ *jsStack = WTF::PageAllocation::allocate(8*1024*1024, WTF::OSAllocator::JSVMStackPages, true);
+ jsStackBase = (Value *)jsStack->base();
+ jsStackTop = jsStackBase;
+
identifierTable = new IdentifierTable(this);
emptyClass = new (classPool.allocate(sizeof(InternalClass))) InternalClass(this);
@@ -291,6 +302,8 @@ ExecutionEngine::~ExecutionEngine()
delete regExpCache;
delete regExpAllocator;
delete executableAllocator;
+ jsStack->deallocate();
+ delete jsStack;
}
void ExecutionEngine::enableDebugger()
@@ -708,13 +721,13 @@ namespace {
{
bool operator()(Function *function, quintptr pc)
{
- return reinterpret_cast<quintptr>(function->code) < pc
- && (reinterpret_cast<quintptr>(function->code) + function->codeSize) < pc;
+ return reinterpret_cast<quintptr>(function->codePtr) < pc
+ && (reinterpret_cast<quintptr>(function->codePtr) + function->codeSize) < pc;
}
bool operator()(quintptr pc, Function *function)
{
- return pc < reinterpret_cast<quintptr>(function->code);
+ return pc < reinterpret_cast<quintptr>(function->codePtr);
}
};
}
diff --git a/src/qml/jsruntime/qv4engine_p.h b/src/qml/jsruntime/qv4engine_p.h
index b7b27a48f9..1dbffa28aa 100644
--- a/src/qml/jsruntime/qv4engine_p.h
+++ b/src/qml/jsruntime/qv4engine_p.h
@@ -50,6 +50,7 @@
namespace WTF {
class BumpPointerAllocator;
+class PageAllocation;
}
QT_BEGIN_NAMESPACE
@@ -123,6 +124,20 @@ struct Q_QML_EXPORT ExecutionEngine
WTF::BumpPointerAllocator *bumperPointerAllocator; // Used by Yarr Regex engine.
+ WTF::PageAllocation *jsStack;
+ Value *jsStackBase;
+ Value *jsStackTop;
+
+ Value *stackPush(uint nValues) {
+ Value *ptr = jsStackTop;
+ jsStackTop = ptr + nValues;
+ return ptr;
+ }
+
+ void stackPop(uint nValues) {
+ jsStackTop -= nValues;
+ }
+
IdentifierTable *identifierTable;
QV4::Debugging::Debugger *debugger;
diff --git a/src/qml/jsruntime/qv4errorobject.cpp b/src/qml/jsruntime/qv4errorobject.cpp
index 04357c393a..6174c9a7f5 100644
--- a/src/qml/jsruntime/qv4errorobject.cpp
+++ b/src/qml/jsruntime/qv4errorobject.cpp
@@ -240,14 +240,14 @@ ErrorCtor::ErrorCtor(ExecutionContext *scope, String *name)
vtbl = &static_vtbl;
}
-Value ErrorCtor::construct(Managed *m, const CallData &d)
+Value ErrorCtor::construct(Managed *m, CallData *callData)
{
- return Value::fromObject(m->engine()->newErrorObject(d.argc ? d.args[0] : Value::undefinedValue()));
+ return Value::fromObject(m->engine()->newErrorObject(callData->argc ? callData->args[0] : Value::undefinedValue()));
}
-Value ErrorCtor::call(Managed *that, const CallData &d)
+Value ErrorCtor::call(Managed *that, CallData *callData)
{
- return that->construct(d);
+ return that->construct(callData);
}
EvalErrorCtor::EvalErrorCtor(ExecutionContext *scope)
@@ -256,9 +256,9 @@ EvalErrorCtor::EvalErrorCtor(ExecutionContext *scope)
vtbl = &static_vtbl;
}
-Value EvalErrorCtor::construct(Managed *m, const CallData &d)
+Value EvalErrorCtor::construct(Managed *m, CallData *callData)
{
- return Value::fromObject(new (m->engine()->memoryManager) EvalErrorObject(m->engine(), d.argc ? d.args[0] : Value::undefinedValue()));
+ return Value::fromObject(new (m->engine()->memoryManager) EvalErrorObject(m->engine(), callData->argc ? callData->args[0] : Value::undefinedValue()));
}
RangeErrorCtor::RangeErrorCtor(ExecutionContext *scope)
@@ -267,9 +267,9 @@ RangeErrorCtor::RangeErrorCtor(ExecutionContext *scope)
vtbl = &static_vtbl;
}
-Value RangeErrorCtor::construct(Managed *m, const CallData &d)
+Value RangeErrorCtor::construct(Managed *m, CallData *callData)
{
- return Value::fromObject(new (m->engine()->memoryManager) RangeErrorObject(m->engine(), d.argc ? d.args[0] : Value::undefinedValue()));
+ return Value::fromObject(new (m->engine()->memoryManager) RangeErrorObject(m->engine(), callData->argc ? callData->args[0] : Value::undefinedValue()));
}
ReferenceErrorCtor::ReferenceErrorCtor(ExecutionContext *scope)
@@ -278,9 +278,9 @@ ReferenceErrorCtor::ReferenceErrorCtor(ExecutionContext *scope)
vtbl = &static_vtbl;
}
-Value ReferenceErrorCtor::construct(Managed *m, const CallData &d)
+Value ReferenceErrorCtor::construct(Managed *m, CallData *callData)
{
- return Value::fromObject(new (m->engine()->memoryManager) ReferenceErrorObject(m->engine(), d.argc ? d.args[0] : Value::undefinedValue()));
+ return Value::fromObject(new (m->engine()->memoryManager) ReferenceErrorObject(m->engine(), callData->argc ? callData->args[0] : Value::undefinedValue()));
}
SyntaxErrorCtor::SyntaxErrorCtor(ExecutionContext *scope)
@@ -289,9 +289,9 @@ SyntaxErrorCtor::SyntaxErrorCtor(ExecutionContext *scope)
vtbl = &static_vtbl;
}
-Value SyntaxErrorCtor::construct(Managed *m, const CallData &d)
+Value SyntaxErrorCtor::construct(Managed *m, CallData *callData)
{
- return Value::fromObject(new (m->engine()->memoryManager) SyntaxErrorObject(m->engine(), d.argc ? d.args[0] : Value::undefinedValue()));
+ return Value::fromObject(new (m->engine()->memoryManager) SyntaxErrorObject(m->engine(), callData->argc ? callData->args[0] : Value::undefinedValue()));
}
TypeErrorCtor::TypeErrorCtor(ExecutionContext *scope)
@@ -300,9 +300,9 @@ TypeErrorCtor::TypeErrorCtor(ExecutionContext *scope)
vtbl = &static_vtbl;
}
-Value TypeErrorCtor::construct(Managed *m, const CallData &d)
+Value TypeErrorCtor::construct(Managed *m, CallData *callData)
{
- return Value::fromObject(new (m->engine()->memoryManager) TypeErrorObject(m->engine(), d.argc ? d.args[0] : Value::undefinedValue()));
+ return Value::fromObject(new (m->engine()->memoryManager) TypeErrorObject(m->engine(), callData->argc ? callData->args[0] : Value::undefinedValue()));
}
URIErrorCtor::URIErrorCtor(ExecutionContext *scope)
@@ -311,9 +311,9 @@ URIErrorCtor::URIErrorCtor(ExecutionContext *scope)
vtbl = &static_vtbl;
}
-Value URIErrorCtor::construct(Managed *m, const CallData &d)
+Value URIErrorCtor::construct(Managed *m, CallData *callData)
{
- return Value::fromObject(new (m->engine()->memoryManager) URIErrorObject(m->engine(), d.argc ? d.args[0] : Value::undefinedValue()));
+ return Value::fromObject(new (m->engine()->memoryManager) URIErrorObject(m->engine(), callData->argc ? callData->args[0] : Value::undefinedValue()));
}
void ErrorPrototype::init(ExecutionEngine *engine, const Value &ctor, Object *obj)
@@ -327,20 +327,22 @@ void ErrorPrototype::init(ExecutionEngine *engine, const Value &ctor, Object *ob
Value ErrorPrototype::method_toString(SimpleCallContext *ctx)
{
+ ValueScope scope(ctx);
+
Object *o = ctx->thisObject.asObject();
if (!o)
ctx->throwTypeError();
- Value name = o->get(ctx->engine->newString(QString::fromLatin1("name")));
+ ScopedValue name(scope, o->get(ctx->engine->newString(QString::fromLatin1("name"))));
QString qname;
- if (name.isUndefined())
+ if (name->isUndefined())
qname = QString::fromLatin1("Error");
else
qname = __qmljs_to_string(name, ctx).stringValue()->toQString();
- Value message = o->get(ctx->engine->newString(QString::fromLatin1("message")));
+ ScopedValue message(scope, o->get(ctx->engine->newString(QString::fromLatin1("message"))));
QString qmessage;
- if (!message.isUndefined())
+ if (!message->isUndefined())
qmessage = __qmljs_to_string(message, ctx).stringValue()->toQString();
QString str;
diff --git a/src/qml/jsruntime/qv4errorobject_p.h b/src/qml/jsruntime/qv4errorobject_p.h
index f8aeae603c..1d82bb7ba2 100644
--- a/src/qml/jsruntime/qv4errorobject_p.h
+++ b/src/qml/jsruntime/qv4errorobject_p.h
@@ -114,8 +114,8 @@ struct ErrorCtor: FunctionObject
ErrorCtor(ExecutionContext *scope);
ErrorCtor(ExecutionContext *scope, String *name);
- static Value construct(Managed *, const CallData &d);
- static Value call(Managed *that, const CallData &d);
+ static Value construct(Managed *, CallData *callData);
+ static Value call(Managed *that, CallData *callData);
protected:
static const ManagedVTable static_vtbl;
@@ -125,7 +125,7 @@ struct EvalErrorCtor: ErrorCtor
{
EvalErrorCtor(ExecutionContext *scope);
- static Value construct(Managed *m, const CallData &d);
+ static Value construct(Managed *m, CallData *callData);
protected:
static const ManagedVTable static_vtbl;
@@ -135,7 +135,7 @@ struct RangeErrorCtor: ErrorCtor
{
RangeErrorCtor(ExecutionContext *scope);
- static Value construct(Managed *m, const CallData &d);
+ static Value construct(Managed *m, CallData *callData);
protected:
static const ManagedVTable static_vtbl;
@@ -145,7 +145,7 @@ struct ReferenceErrorCtor: ErrorCtor
{
ReferenceErrorCtor(ExecutionContext *scope);
- static Value construct(Managed *m, const CallData &d);
+ static Value construct(Managed *m, CallData *callData);
protected:
static const ManagedVTable static_vtbl;
@@ -155,7 +155,7 @@ struct SyntaxErrorCtor: ErrorCtor
{
SyntaxErrorCtor(ExecutionContext *scope);
- static Value construct(Managed *m, const CallData &d);
+ static Value construct(Managed *m, CallData *callData);
protected:
static const ManagedVTable static_vtbl;
@@ -165,7 +165,7 @@ struct TypeErrorCtor: ErrorCtor
{
TypeErrorCtor(ExecutionContext *scope);
- static Value construct(Managed *m, const CallData &d);
+ static Value construct(Managed *m, CallData *callData);
protected:
static const ManagedVTable static_vtbl;
@@ -175,7 +175,7 @@ struct URIErrorCtor: ErrorCtor
{
URIErrorCtor(ExecutionContext *scope);
- static Value construct(Managed *m, const CallData &d);
+ static Value construct(Managed *m, CallData *callData);
protected:
static const ManagedVTable static_vtbl;
diff --git a/src/qml/jsruntime/qv4function.cpp b/src/qml/jsruntime/qv4function.cpp
index e989d31c1b..9907f3e2ba 100644
--- a/src/qml/jsruntime/qv4function.cpp
+++ b/src/qml/jsruntime/qv4function.cpp
@@ -54,21 +54,14 @@ using namespace QV4;
Function::Function(ExecutionEngine *engine, CompiledData::CompilationUnit *unit, const CompiledData::Function *function,
Value (*codePtr)(ExecutionContext *, const uchar *), quint32 _codeSize)
: name(0)
- , compiledFunction(0)
- , compilationUnit(0)
- , code(0)
+ , compiledFunction(function)
+ , compilationUnit(unit)
+ , codePtr(codePtr)
, codeData(0)
- , codeSize(0)
+ , codeSize(_codeSize)
{
- Q_ASSERT(!compilationUnit);
- compilationUnit = unit;
- compiledFunction = function;
-
name = compilationUnit->runtimeStrings[compiledFunction->nameIndex];
- code = codePtr;
- codeSize = _codeSize;
-
formals.resize(compiledFunction->nFormals);
const quint32 *formalsIndices = compiledFunction->formalsTable();
for (int i = 0; i < compiledFunction->nFormals; ++i)
diff --git a/src/qml/jsruntime/qv4function_p.h b/src/qml/jsruntime/qv4function_p.h
index 735dc558e1..1fc40d7209 100644
--- a/src/qml/jsruntime/qv4function_p.h
+++ b/src/qml/jsruntime/qv4function_p.h
@@ -49,6 +49,7 @@
#include "qv4value_def_p.h"
#include <private/qv4compileddata_p.h>
+#include <private/qv4engine_p.h>
QT_BEGIN_NAMESPACE
@@ -84,7 +85,17 @@ struct Function {
const CompiledData::Function *compiledFunction;
CompiledData::CompilationUnit *compilationUnit;
- Value (*code)(ExecutionContext *, const uchar *);
+ inline Value code(ExecutionContext *ctx, const uchar *data) {
+ Value *stack = ctx->engine->jsStackTop;
+ try {
+ return codePtr(ctx, data);
+ } catch (...) {
+ ctx->engine->jsStackTop = stack;
+ throw;
+ }
+ }
+
+ Value (*codePtr)(ExecutionContext *, const uchar *);
const uchar *codeData;
quint32 codeSize;
diff --git a/src/qml/jsruntime/qv4functionobject.cpp b/src/qml/jsruntime/qv4functionobject.cpp
index 925aadcdf1..252481b7f1 100644
--- a/src/qml/jsruntime/qv4functionobject.cpp
+++ b/src/qml/jsruntime/qv4functionobject.cpp
@@ -48,6 +48,7 @@
#include "qv4mm_p.h"
#include "qv4exception_p.h"
#include "qv4arrayobject_p.h"
+#include "qv4scopedvalue_p.h"
#include <private/qqmljsengine_p.h>
#include <private/qqmljslexer_p.h>
@@ -122,8 +123,8 @@ FunctionObject::~FunctionObject()
Value FunctionObject::newInstance()
{
- CALLDATA(0);
- return construct(d);
+ ScopedCallData callData(engine(), 0);
+ return construct(callData);
}
bool FunctionObject::hasInstance(Managed *that, const Value &value)
@@ -151,7 +152,7 @@ bool FunctionObject::hasInstance(Managed *that, const Value &value)
return false;
}
-Value FunctionObject::construct(Managed *that, const CallData &)
+Value FunctionObject::construct(Managed *that, CallData *)
{
FunctionObject *f = static_cast<FunctionObject *>(that);
ExecutionEngine *v4 = f->engine();
@@ -164,7 +165,7 @@ Value FunctionObject::construct(Managed *that, const CallData &)
return Value::fromObject(obj);
}
-Value FunctionObject::call(Managed *, const CallData &)
+Value FunctionObject::call(Managed *, CallData *)
{
return Value::undefinedValue();
}
@@ -203,7 +204,7 @@ FunctionCtor::FunctionCtor(ExecutionContext *scope)
}
// 15.3.2
-Value FunctionCtor::construct(Managed *that, const CallData &d)
+Value FunctionCtor::construct(Managed *that, CallData *callData)
{
FunctionCtor *f = static_cast<FunctionCtor *>(that);
MemoryManager::GCBlocker gcBlocker(f->engine()->memoryManager);
@@ -211,13 +212,13 @@ Value FunctionCtor::construct(Managed *that, const CallData &d)
ExecutionContext *ctx = f->engine()->current;
QString arguments;
QString body;
- if (d.argc > 0) {
- for (uint i = 0; i < d.argc - 1; ++i) {
+ if (callData->argc > 0) {
+ for (uint i = 0; i < callData->argc - 1; ++i) {
if (i)
arguments += QLatin1String(", ");
- arguments += d.args[i].toString(ctx)->toQString();
+ arguments += callData->args[i].toString(ctx)->toQString();
}
- body = d.args[d.argc - 1].toString(ctx)->toQString();
+ body = callData->args[callData->argc - 1].toString(ctx)->toQString();
}
QString function = QLatin1String("function(") + arguments + QLatin1String("){") + body + QLatin1String("}");
@@ -252,9 +253,9 @@ Value FunctionCtor::construct(Managed *that, const CallData &d)
}
// 15.3.1: This is equivalent to new Function(...)
-Value FunctionCtor::call(Managed *that, const CallData &d)
+Value FunctionCtor::call(Managed *that, CallData *callData)
{
- return construct(that, d);
+ return construct(that, callData);
}
FunctionPrototype::FunctionPrototype(InternalClass *ic)
@@ -307,23 +308,23 @@ Value FunctionPrototype::method_apply(SimpleCallContext *ctx)
len = ArrayPrototype::getLength(ctx, arr);
}
- CALLDATA(len);
+ ScopedCallData callData(ctx->engine, len);
if (len) {
if (arr->protoHasArray() || arr->hasAccessorProperty) {
for (quint32 i = 0; i < len; ++i)
- d.args[i] = arr->getIndexed(i);
+ callData->args[i] = arr->getIndexed(i);
} else {
int alen = qMin(len, arr->arrayDataLen);
for (quint32 i = 0; i < alen; ++i)
- d.args[i] = arr->arrayData[i].value;
+ callData->args[i] = arr->arrayData[i].value;
for (quint32 i = alen; i < len; ++i)
- d.args[i] = Value::undefinedValue();
+ callData->args[i] = Value::undefinedValue();
}
}
- d.thisObject = thisArg;
- return o->call(d);
+ callData->thisObject = thisArg;
+ return o->call(callData);
}
Value FunctionPrototype::method_call(SimpleCallContext *ctx)
@@ -334,12 +335,12 @@ Value FunctionPrototype::method_call(SimpleCallContext *ctx)
if (!o)
ctx->throwTypeError();
- CALLDATA(ctx->argumentCount ? ctx->argumentCount - 1 : 0);
+ ScopedCallData callData(ctx->engine, ctx->argumentCount ? ctx->argumentCount - 1 : 0);
if (ctx->argumentCount)
qCopy(ctx->arguments + 1,
- ctx->arguments + ctx->argumentCount, d.args);
- d.thisObject = thisArg;
- return o->call(d);
+ ctx->arguments + ctx->argumentCount, callData->args);
+ callData->thisObject = thisArg;
+ return o->call(callData);
}
Value FunctionPrototype::method_bind(SimpleCallContext *ctx)
@@ -373,8 +374,8 @@ ScriptFunction::ScriptFunction(ExecutionContext *scope, Function *function)
vtbl = &static_vtbl;
this->function = function;
this->function->compilationUnit->ref();
- assert(function);
- assert(function->code);
+ Q_ASSERT(function);
+ Q_ASSERT(function->codePtr);
// global function
if (!scope)
@@ -400,9 +401,10 @@ ScriptFunction::ScriptFunction(ExecutionContext *scope, Function *function)
}
}
-Value ScriptFunction::construct(Managed *that, const CallData &d)
+Value ScriptFunction::construct(Managed *that, CallData *callData)
{
ScriptFunction *f = static_cast<ScriptFunction *>(that);
+ SAVE_JS_STACK(f->scope);
ExecutionEngine *v4 = f->engine();
InternalClass *ic = v4->objectClass;
@@ -412,9 +414,8 @@ Value ScriptFunction::construct(Managed *that, const CallData &d)
Object *obj = v4->newObject(ic);
ExecutionContext *context = v4->current;
- CallData dd = d;
- dd.thisObject = Value::fromObject(obj);
- ExecutionContext *ctx = context->newCallContext(f, dd);
+ callData->thisObject = Value::fromObject(obj);
+ ExecutionContext *ctx = context->newCallContext(f, callData);
Value result;
try {
@@ -425,23 +426,25 @@ Value ScriptFunction::construct(Managed *that, const CallData &d)
}
ctx->engine->popContext();
+ CHECK_JS_STACK(f->scope);
if (result.isObject())
return result;
return Value::fromObject(obj);
}
-Value ScriptFunction::call(Managed *that, const CallData &d)
+Value ScriptFunction::call(Managed *that, CallData *callData)
{
ScriptFunction *f = static_cast<ScriptFunction *>(that);
+ SAVE_JS_STACK(f->scope);
void *stackSpace;
ExecutionContext *context = f->engine()->current;
- ExecutionContext *ctx = context->newCallContext(f, d);
+ CallContext *ctx = context->newCallContext(f, callData);
- if (!f->strictMode && !d.thisObject.isObject()) {
- if (d.thisObject.isNullOrUndefined()) {
+ if (!f->strictMode && !callData->thisObject.isObject()) {
+ if (callData->thisObject.isNullOrUndefined()) {
ctx->thisObject = Value::fromObject(f->engine()->globalObject);
} else {
- ctx->thisObject = Value::fromObject(d.thisObject.toObject(context));
+ ctx->thisObject = Value::fromObject(callData->thisObject.toObject(context));
}
}
@@ -453,6 +456,7 @@ Value ScriptFunction::call(Managed *that, const CallData &d)
throw;
}
ctx->engine->popContext();
+ CHECK_JS_STACK(f->scope);
return result;
}
@@ -464,8 +468,8 @@ SimpleScriptFunction::SimpleScriptFunction(ExecutionContext *scope, Function *fu
vtbl = &static_vtbl;
this->function = function;
this->function->compilationUnit->ref();
- assert(function);
- assert(function->code);
+ Q_ASSERT(function);
+ Q_ASSERT(function->codePtr);
// global function
if (!scope)
@@ -491,9 +495,10 @@ SimpleScriptFunction::SimpleScriptFunction(ExecutionContext *scope, Function *fu
}
}
-Value SimpleScriptFunction::construct(Managed *that, const CallData &d)
+Value SimpleScriptFunction::construct(Managed *that, CallData *callData)
{
SimpleScriptFunction *f = static_cast<SimpleScriptFunction *>(that);
+ SAVE_JS_STACK(f->scope);
ExecutionEngine *v4 = f->engine();
InternalClass *ic = v4->objectClass;
@@ -504,9 +509,8 @@ Value SimpleScriptFunction::construct(Managed *that, const CallData &d)
ExecutionContext *context = v4->current;
void *stackSpace = alloca(requiredMemoryForExecutionContectSimple(f));
- CallData dd = d;
- dd.thisObject = Value::fromObject(obj);
- ExecutionContext *ctx = context->newCallContext(stackSpace, f, dd);
+ callData->thisObject = Value::fromObject(obj);
+ ExecutionContext *ctx = context->newCallContext(stackSpace, f, callData);
Value result;
try {
@@ -517,23 +521,25 @@ Value SimpleScriptFunction::construct(Managed *that, const CallData &d)
}
ctx->engine->popContext();
+ CHECK_JS_STACK(f->scope);
if (result.isObject())
return result;
return Value::fromObject(obj);
}
-Value SimpleScriptFunction::call(Managed *that, const CallData &d)
+Value SimpleScriptFunction::call(Managed *that, CallData *callData)
{
SimpleScriptFunction *f = static_cast<SimpleScriptFunction *>(that);
+ SAVE_JS_STACK(f->scope);
void *stackSpace = alloca(requiredMemoryForExecutionContectSimple(f));
ExecutionContext *context = f->engine()->current;
- ExecutionContext *ctx = context->newCallContext(stackSpace, f, d);
+ ExecutionContext *ctx = context->newCallContext(stackSpace, f, callData);
- if (!f->strictMode && !d.thisObject.isObject()) {
- if (d.thisObject.isNullOrUndefined()) {
+ if (!f->strictMode && !callData->thisObject.isObject()) {
+ if (callData->thisObject.isNullOrUndefined()) {
ctx->thisObject = Value::fromObject(f->engine()->globalObject);
} else {
- ctx->thisObject = Value::fromObject(d.thisObject.toObject(context));
+ ctx->thisObject = Value::fromObject(callData->thisObject.toObject(context));
}
}
@@ -545,6 +551,7 @@ Value SimpleScriptFunction::call(Managed *that, const CallData &d)
throw;
}
ctx->engine->popContext();
+ CHECK_JS_STACK(f->scope);
return result;
}
@@ -561,13 +568,13 @@ BuiltinFunctionOld::BuiltinFunctionOld(ExecutionContext *scope, String *name, Va
isBuiltinFunction = true;
}
-Value BuiltinFunctionOld::construct(Managed *f, const CallData &d)
+Value BuiltinFunctionOld::construct(Managed *f, CallData *)
{
f->engine()->current->throwTypeError();
return Value::undefinedValue();
}
-Value BuiltinFunctionOld::call(Managed *that, const CallData &d)
+Value BuiltinFunctionOld::call(Managed *that, CallData *callData)
{
BuiltinFunctionOld *f = static_cast<BuiltinFunctionOld *>(that);
ExecutionEngine *v4 = f->engine();
@@ -576,9 +583,10 @@ Value BuiltinFunctionOld::call(Managed *that, const CallData &d)
SimpleCallContext ctx;
ctx.initSimpleCallContext(f->scope->engine);
ctx.strictMode = f->scope->strictMode; // ### needed? scope or parent context?
- ctx.thisObject = d.thisObject;
- ctx.arguments = d.args;
- ctx.argumentCount = d.argc;
+ ctx.thisObject = callData->thisObject;
+ // ### const_cast
+ ctx.arguments = const_cast<Value *>(callData->args);
+ ctx.argumentCount = callData->argc;
v4->pushContext(&ctx);
Value result;
@@ -593,7 +601,7 @@ Value BuiltinFunctionOld::call(Managed *that, const CallData &d)
return result;
}
-Value IndexedBuiltinFunction::call(Managed *that, const CallData &d)
+Value IndexedBuiltinFunction::call(Managed *that, CallData *callData)
{
IndexedBuiltinFunction *f = static_cast<IndexedBuiltinFunction *>(that);
ExecutionEngine *v4 = f->engine();
@@ -602,9 +610,10 @@ Value IndexedBuiltinFunction::call(Managed *that, const CallData &d)
SimpleCallContext ctx;
ctx.initSimpleCallContext(f->scope->engine);
ctx.strictMode = f->scope->strictMode; // ### needed? scope or parent context?
- ctx.thisObject = d.thisObject;
- ctx.arguments = d.args;
- ctx.argumentCount = d.argc;
+ ctx.thisObject = callData->thisObject;
+ // ### const_cast
+ ctx.arguments = const_cast<Value *>(callData->args);
+ ctx.argumentCount = callData->argc;
v4->pushContext(&ctx);
Value result;
@@ -647,24 +656,24 @@ void BoundFunction::destroy(Managed *that)
static_cast<BoundFunction *>(that)->~BoundFunction();
}
-Value BoundFunction::call(Managed *that, const CallData &dd)
+Value BoundFunction::call(Managed *that, CallData *dd)
{
BoundFunction *f = static_cast<BoundFunction *>(that);
- CALLDATA(f->boundArgs.size() + dd.argc);
- d.thisObject = f->boundThis;
- memcpy(d.args, f->boundArgs.constData(), f->boundArgs.size()*sizeof(Value));
- memcpy(d.args + f->boundArgs.size(), dd.args, dd.argc*sizeof(Value));
- return f->target->call(d);
+ ScopedCallData callData(f->scope->engine, f->boundArgs.size() + dd->argc);
+ callData->thisObject = f->boundThis;
+ memcpy(callData->args, f->boundArgs.constData(), f->boundArgs.size()*sizeof(Value));
+ memcpy(callData->args + f->boundArgs.size(), dd->args, dd->argc*sizeof(Value));
+ return f->target->call(callData);
}
-Value BoundFunction::construct(Managed *that, const CallData &dd)
+Value BoundFunction::construct(Managed *that, CallData *dd)
{
BoundFunction *f = static_cast<BoundFunction *>(that);
- CALLDATA(f->boundArgs.size() + dd.argc);
- memcpy(d.args, f->boundArgs.constData(), f->boundArgs.size()*sizeof(Value));
- memcpy(d.args + f->boundArgs.size(), dd.args, dd.argc*sizeof(Value));
- return f->target->construct(d);
+ ScopedCallData callData(f->scope->engine, f->boundArgs.size() + dd->argc);
+ memcpy(callData->args, f->boundArgs.constData(), f->boundArgs.size()*sizeof(Value));
+ memcpy(callData->args + f->boundArgs.size(), dd->args, dd->argc*sizeof(Value));
+ return f->target->construct(callData);
}
bool BoundFunction::hasInstance(Managed *that, const Value &value)
diff --git a/src/qml/jsruntime/qv4functionobject_p.h b/src/qml/jsruntime/qv4functionobject_p.h
index 4d4174d053..d694d28462 100644
--- a/src/qml/jsruntime/qv4functionobject_p.h
+++ b/src/qml/jsruntime/qv4functionobject_p.h
@@ -117,13 +117,13 @@ struct Q_QML_EXPORT FunctionObject: Object {
Value newInstance();
- static Value construct(Managed *that, const CallData &);
- static Value call(Managed *that, const CallData &d);
- inline Value construct(const CallData &d) {
- return vtbl->construct(this, d);
+ static Value construct(Managed *that, CallData *);
+ static Value call(Managed *that, CallData *d);
+ inline Value construct(CallData *callData) {
+ return vtbl->construct(this, callData);
}
- inline Value call(const CallData &d) {
- return vtbl->call(this, d);
+ inline Value call(CallData *callData) {
+ return vtbl->call(this, callData);
}
static FunctionObject *creatScriptFunction(ExecutionContext *scope, Function *function);
@@ -142,8 +142,8 @@ struct FunctionCtor: FunctionObject
{
FunctionCtor(ExecutionContext *scope);
- static Value construct(Managed *that, const CallData &);
- static Value call(Managed *that, const CallData &d);
+ static Value construct(Managed *that, CallData *callData);
+ static Value call(Managed *that, CallData *callData);
protected:
static const ManagedVTable static_vtbl;
@@ -165,8 +165,8 @@ struct BuiltinFunctionOld: FunctionObject {
BuiltinFunctionOld(ExecutionContext *scope, String *name, Value (*code)(SimpleCallContext *));
- static Value construct(Managed *, const CallData &d);
- static Value call(Managed *that, const CallData &d);
+ static Value construct(Managed *, CallData *);
+ static Value call(Managed *that, CallData *callData);
protected:
static const ManagedVTable static_vtbl;
@@ -188,21 +188,21 @@ struct IndexedBuiltinFunction: FunctionObject
isBuiltinFunction = true;
}
- static Value construct(Managed *m, const CallData &)
+ static Value construct(Managed *m, CallData *)
{
m->engine()->current->throwTypeError();
return Value::undefinedValue();
}
- static Value call(Managed *that, const CallData &d);
+ static Value call(Managed *that, CallData *callData);
};
struct ScriptFunction: FunctionObject {
ScriptFunction(ExecutionContext *scope, Function *function);
- static Value construct(Managed *, const CallData &d);
- static Value call(Managed *that, const CallData &d);
+ static Value construct(Managed *, CallData *callData);
+ static Value call(Managed *that, CallData *callData);
protected:
static const ManagedVTable static_vtbl;
@@ -211,8 +211,8 @@ protected:
struct SimpleScriptFunction: FunctionObject {
SimpleScriptFunction(ExecutionContext *scope, Function *function);
- static Value construct(Managed *, const CallData &d);
- static Value call(Managed *that, const CallData &d);
+ static Value construct(Managed *, CallData *callData);
+ static Value call(Managed *that, CallData *callData);
protected:
static const ManagedVTable static_vtbl;
@@ -227,8 +227,8 @@ struct BoundFunction: FunctionObject {
~BoundFunction() {}
- static Value construct(Managed *, const CallData &d);
- static Value call(Managed *that, const CallData &d);
+ static Value construct(Managed *, CallData *d);
+ static Value call(Managed *that, CallData *dd);
static const ManagedVTable static_vtbl;
static void destroy(Managed *);
diff --git a/src/qml/jsruntime/qv4globalobject.cpp b/src/qml/jsruntime/qv4globalobject.cpp
index 3b06a6d884..9764a7930f 100644
--- a/src/qml/jsruntime/qv4globalobject.cpp
+++ b/src/qml/jsruntime/qv4globalobject.cpp
@@ -47,6 +47,7 @@
#include "qv4debugging_p.h"
#include "qv4script_p.h"
#include "qv4exception_p.h"
+#include "qv4scopedvalue_p.h"
#include <private/qqmljsengine_p.h>
#include <private/qqmljslexer_p.h>
@@ -390,9 +391,9 @@ Value EvalFunction::evalCall(Value /*thisObject*/, Value *args, int argc, bool d
if (strictMode) {
FunctionObject *e = FunctionObject::creatScriptFunction(ctx, function);
- CALLDATA(0);
- d.thisObject = ctx->thisObject;
- return e->call(d);
+ ScopedCallData callData(ctx->engine, 0);
+ callData->thisObject = ctx->thisObject;
+ return e->call(callData);
}
ExecutionContext::EvalCode evalCode;
@@ -438,10 +439,11 @@ Value EvalFunction::evalCall(Value /*thisObject*/, Value *args, int argc, bool d
}
-Value EvalFunction::call(Managed *that, const CallData &d)
+Value EvalFunction::call(Managed *that, CallData *callData)
{
// indirect call
- return static_cast<EvalFunction *>(that)->evalCall(d.thisObject, d.args, d.argc, false);
+ // ### const_cast
+ return static_cast<EvalFunction *>(that)->evalCall(callData->thisObject, const_cast<Value *>(callData->args), callData->argc, false);
}
diff --git a/src/qml/jsruntime/qv4globalobject_p.h b/src/qml/jsruntime/qv4globalobject_p.h
index 4ac531c27b..b777bf8915 100644
--- a/src/qml/jsruntime/qv4globalobject_p.h
+++ b/src/qml/jsruntime/qv4globalobject_p.h
@@ -55,7 +55,7 @@ struct Q_QML_EXPORT EvalFunction : FunctionObject
Value evalCall(Value thisObject, Value *args, int argc, bool directCall);
using Managed::construct;
- static Value call(Managed *that, const CallData &d);
+ static Value call(Managed *that, CallData *callData);
protected:
static const ManagedVTable static_vtbl;
diff --git a/src/qml/jsruntime/qv4identifier.cpp b/src/qml/jsruntime/qv4identifier.cpp
index 5d8077bfdc..08f48c36a4 100644
--- a/src/qml/jsruntime/qv4identifier.cpp
+++ b/src/qml/jsruntime/qv4identifier.cpp
@@ -114,7 +114,7 @@ const IdentifierHashEntry *IdentifierHashBase::lookup(const Identifier *identifi
{
if (!d)
return 0;
- assert(d->entries);
+ Q_ASSERT(d->entries);
uint idx = identifier->hashValue % d->alloc;
while (1) {
@@ -131,7 +131,7 @@ const IdentifierHashEntry *IdentifierHashBase::lookup(const QString &str) const
{
if (!d)
return 0;
- assert(d->entries);
+ Q_ASSERT(d->entries);
uint hash = String::createHashValue(str.constData(), str.length());
uint idx = hash % d->alloc;
diff --git a/src/qml/jsruntime/qv4include.cpp b/src/qml/jsruntime/qv4include.cpp
index 9068d573f6..647cc7d2cb 100644
--- a/src/qml/jsruntime/qv4include.cpp
+++ b/src/qml/jsruntime/qv4include.cpp
@@ -40,6 +40,7 @@
****************************************************************************/
#include "qv4include_p.h"
+#include "qv4scopedvalue_p.h"
#include <QtQml/qjsengine.h>
#include <QtNetwork/qnetworkrequest.h>
@@ -104,10 +105,10 @@ void QV4Include::callback(const QV4::Value &callback, const QV4::Value &status)
QV4::ExecutionContext *ctx = f->engine()->current;
try {
- CALLDATA(1);
- d.thisObject = QV4::Value::fromObject(f->engine()->globalObject);
- d.args[0] = status;
- f->call(d);
+ QV4::ScopedCallData callData(ctx->engine, 1);
+ callData->thisObject = QV4::Value::fromObject(f->engine()->globalObject);
+ callData->args[0] = status;
+ f->call(callData);
} catch (QV4::Exception &e) {
e.accept(ctx);
}
diff --git a/src/qml/jsruntime/qv4jsonobject.cpp b/src/qml/jsruntime/qv4jsonobject.cpp
index 9c98d78743..ef1f500580 100644
--- a/src/qml/jsruntime/qv4jsonobject.cpp
+++ b/src/qml/jsruntime/qv4jsonobject.cpp
@@ -44,6 +44,7 @@
#include <qv4stringobject_p.h>
#include <qv4booleanobject_p.h>
#include <qv4objectiterator_p.h>
+#include <qv4scopedvalue_p.h>
#include <qjsondocument.h>
#include <qstack.h>
#include <qstringlist.h>
@@ -702,10 +703,10 @@ QString Stringify::Str(const QString &key, Value value)
if (Object *o = value.asObject()) {
FunctionObject *toJSON = o->get(ctx->engine->newString(QStringLiteral("toJSON"))).asFunctionObject();
if (toJSON) {
- CALLDATA(1);
- d.thisObject = value;
- d.args[0] = Value::fromString(ctx, key);
- value = toJSON->call(d);
+ ScopedCallData callData(ctx->engine, 1);
+ callData->thisObject = value;
+ callData->args[0] = Value::fromString(ctx, key);
+ value = toJSON->call(callData);
}
}
@@ -713,11 +714,11 @@ QString Stringify::Str(const QString &key, Value value)
Object *holder = ctx->engine->newObject();
Value holderValue = Value::fromObject(holder);
holder->put(ctx, QString(), value);
- CALLDATA(2);
- d.args[0] = Value::fromString(ctx, key);
- d.args[1] = value;
- d.thisObject = holderValue;
- value = replacerFunction->call(d);
+ ScopedCallData callData(ctx->engine, 2);
+ callData->args[0] = Value::fromString(ctx, key);
+ callData->args[1] = value;
+ callData->thisObject = holderValue;
+ value = replacerFunction->call(callData);
}
if (Object *o = value.asObject()) {
@@ -885,6 +886,8 @@ Value JsonObject::method_parse(SimpleCallContext *ctx)
Value JsonObject::method_stringify(SimpleCallContext *ctx)
{
+ ValueScope scope(ctx);
+
Stringify stringify(ctx);
Object *o = ctx->argument(1).asObject();
@@ -892,12 +895,13 @@ Value JsonObject::method_stringify(SimpleCallContext *ctx)
stringify.replacerFunction = o->asFunctionObject();
if (o->isArrayObject()) {
uint arrayLen = o->arrayLength();
+ ScopedValue v(scope);
for (uint i = 0; i < arrayLen; ++i) {
- Value v = o->getIndexed(i);
- if (v.asNumberObject() || v.asStringObject() || v.isNumber())
+ v = o->getIndexed(i);
+ if (v->asNumberObject() || v->asStringObject() || v->isNumber())
v = __qmljs_to_string(v, ctx);
- if (v.isString()) {
- String *s = v.stringValue();
+ if (v->isString()) {
+ String *s = v->stringValue();
if (!stringify.propertyList.contains(s))
stringify.propertyList.append(s);
}
diff --git a/src/qml/jsruntime/qv4lookup.cpp b/src/qml/jsruntime/qv4lookup.cpp
index e66055653e..2cffa55642 100644
--- a/src/qml/jsruntime/qv4lookup.cpp
+++ b/src/qml/jsruntime/qv4lookup.cpp
@@ -40,6 +40,7 @@
****************************************************************************/
#include "qv4lookup_p.h"
#include "qv4functionobject_p.h"
+#include "qv4scopedvalue_p.h"
QT_BEGIN_NAMESPACE
@@ -202,9 +203,9 @@ void Lookup::getterAccessor0(Lookup *l, Value *result, const Value &object)
if (!getter) {
res = Value::undefinedValue();
} else {
- CALLDATA(0);
- d.thisObject = object;
- res = getter->call(d);
+ ScopedCallData callData(o->engine(), 0);
+ callData->thisObject = object;
+ res = getter->call(callData);
}
if (result)
*result = res;
@@ -225,9 +226,9 @@ void Lookup::getterAccessor1(Lookup *l, Value *result, const Value &object)
if (!getter) {
res = Value::undefinedValue();
} else {
- CALLDATA(0);
- d.thisObject = object;
- res = getter->call(d);
+ ScopedCallData callData(o->engine(), 0);
+ callData->thisObject = object;
+ res = getter->call(callData);
}
if (result)
*result = res;
@@ -251,9 +252,9 @@ void Lookup::getterAccessor2(Lookup *l, Value *result, const Value &object)
if (!getter) {
res = Value::undefinedValue();
} else {
- CALLDATA(0);
- d.thisObject = object;
- res = getter->call(d);
+ ScopedCallData callData(o->engine(), 0);
+ callData->thisObject = object;
+ res = getter->call(callData);
}
if (result)
*result = res;
@@ -306,9 +307,9 @@ void Lookup::primitiveGetterAccessor0(Lookup *l, Value *result, const Value &obj
if (!getter) {
res = Value::undefinedValue();
} else {
- CALLDATA(0);
- d.thisObject = object;
- res = getter->call(d);
+ ScopedCallData callData(o->engine(), 0);
+ callData->thisObject = object;
+ res = getter->call(callData);
}
if (result)
*result = res;
@@ -330,9 +331,9 @@ void Lookup::primitiveGetterAccessor1(Lookup *l, Value *result, const Value &obj
if (!getter) {
res = Value::undefinedValue();
} else {
- CALLDATA(0);
- d.thisObject = object;
- res = getter->call(d);
+ ScopedCallData callData(o->engine(), 0);
+ callData->thisObject = object;
+ res = getter->call(callData);
}
if (result)
*result = res;
@@ -434,9 +435,9 @@ void Lookup::globalGetterAccessor0(Lookup *l, ExecutionContext *ctx, Value *resu
if (!getter) {
*result = Value::undefinedValue();
} else {
- CALLDATA(0);
- d.thisObject = Value::undefinedValue();
- *result = getter->call(d);
+ ScopedCallData callData(ctx->engine, 0);
+ callData->thisObject = Value::undefinedValue();
+ *result = getter->call(callData);
}
return;
}
@@ -453,9 +454,9 @@ void Lookup::globalGetterAccessor1(Lookup *l, ExecutionContext *ctx, Value *resu
if (!getter) {
*result = Value::undefinedValue();
} else {
- CALLDATA(0);
- d.thisObject = Value::undefinedValue();
- *result = getter->call(d);
+ ScopedCallData callData(ctx->engine, 0);
+ callData->thisObject = Value::undefinedValue();
+ *result = getter->call(callData);
}
return;
}
@@ -475,9 +476,9 @@ void Lookup::globalGetterAccessor2(Lookup *l, ExecutionContext *ctx, Value *resu
if (!getter) {
*result = Value::undefinedValue();
} else {
- CALLDATA(0);
- d.thisObject = Value::undefinedValue();
- *result = getter->call(d);
+ ScopedCallData callData(ctx->engine, 0);
+ callData->thisObject = Value::undefinedValue();
+ *result = getter->call(callData);
}
return;
}
@@ -491,7 +492,7 @@ void Lookup::setterGeneric(Lookup *l, const Value &object, const Value &value)
{
Object *o = object.asObject();
if (!o) {
- o = __qmljs_convert_to_object(l->name->engine()->current, object);
+ o = __qmljs_convert_to_object(l->name->engine()->current, ValueRef::fromRawValue(&object));
o->put(l->name, value);
return;
}
diff --git a/src/qml/jsruntime/qv4managed.cpp b/src/qml/jsruntime/qv4managed.cpp
index 955d12a3d0..62491ba7e5 100644
--- a/src/qml/jsruntime/qv4managed.cpp
+++ b/src/qml/jsruntime/qv4managed.cpp
@@ -176,12 +176,12 @@ bool Managed::hasInstance(Managed *m, const Value &)
m->engine()->current->throwTypeError();
}
-Value Managed::construct(Managed *m, const CallData &)
+Value Managed::construct(Managed *m, CallData *)
{
m->engine()->current->throwTypeError();
}
-Value Managed::call(Managed *m, const CallData &)
+Value Managed::call(Managed *m, CallData *)
{
m->engine()->current->throwTypeError();
}
diff --git a/src/qml/jsruntime/qv4managed_p.h b/src/qml/jsruntime/qv4managed_p.h
index b77b1cd638..50325478f5 100644
--- a/src/qml/jsruntime/qv4managed_p.h
+++ b/src/qml/jsruntime/qv4managed_p.h
@@ -76,28 +76,23 @@ struct GCDeletable
struct CallData
{
- Value thisObject;
- Value *args;
+ // below is to be compatible with Value. Initialize tag to 0
+#if Q_BYTE_ORDER != Q_LITTLE_ENDIAN
+ uint tag;
+#endif
int argc;
-};
-
-#ifdef QT_NO_DEBUG
-#define CALLDATA(argc_) \
- QV4::CallData d; \
- d.argc = argc_; \
- d.args = (QV4::Value *)alloca(qMax((int)(argc_), (int)QV4::Global::ReservedArgumentCount)*sizeof(QV4::Value))
-#else
-#define CALLDATA(argc_) \
- QV4::CallData d; \
- d.argc = argc_; \
- d.args = (QV4::Value *)alloca(qMax((int)(argc_), (int)QV4::Global::ReservedArgumentCount)*sizeof(QV4::Value)); \
- for (int iii = 0; iii < qMax((int)(argc_), (int)QV4::Global::ReservedArgumentCount); ++iii) d.args[iii] = QV4::Value::undefinedValue()
+#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
+ uint tag;
#endif
+ Value thisObject;
+ Value args[1];
+};
+
struct ManagedVTable
{
- Value (*call)(Managed *, const CallData &data);
- Value (*construct)(Managed *, const CallData &data);
+ Value (*call)(Managed *, CallData *data);
+ Value (*construct)(Managed *, CallData *data);
void (*markObjects)(Managed *);
void (*destroy)(Managed *);
void (*collectDeletables)(Managed *, GCDeletable **deletable);
@@ -257,8 +252,8 @@ public:
inline bool hasInstance(const Value &v) {
return vtbl->hasInstance(this, v);
}
- Value construct(const CallData &d);
- Value call(const CallData &d);
+ Value construct(CallData *d);
+ Value call(CallData *d);
Value get(String *name, bool *hasProperty = 0);
Value getIndexed(uint index, bool *hasProperty = 0);
void put(String *name, const Value &value)
@@ -286,8 +281,8 @@ public:
static void destroy(Managed *that) { that->_data = 0; }
static bool hasInstance(Managed *that, const Value &value);
- static Value construct(Managed *m, const CallData &d);
- static Value call(Managed *m, const CallData &);
+ static Value construct(Managed *m, CallData *d);
+ static Value call(Managed *m, CallData *);
static void getLookup(Managed *m, Lookup *, Value *);
static void setLookup(Managed *m, Lookup *l, const Value &v);
static bool isEqualTo(Managed *m, Managed *other);
diff --git a/src/qml/jsruntime/qv4mm.cpp b/src/qml/jsruntime/qv4mm.cpp
index 095d27e1c0..874c349c42 100644
--- a/src/qml/jsruntime/qv4mm.cpp
+++ b/src/qml/jsruntime/qv4mm.cpp
@@ -293,6 +293,7 @@ void MemoryManager::mark()
#endif // COMPILER
collectFromStack();
+ collectFromJSStack();
// Preserve QObject ownership rules within JavaScript: A parent with c++ ownership
// keeps all of its children alive in JavaScript.
@@ -602,4 +603,16 @@ void MemoryManager::collectFromStack() const
}
}
+void MemoryManager::collectFromJSStack() const
+{
+ Value *v = engine()->jsStackBase;
+ Value *top = engine()->jsStackTop;
+ while (v < top) {
+ Managed *m = v->asManaged();
+ if (m && m->inUse)
+ // Skip pointers to already freed objects, they are bogus as well
+ m->mark();
+ ++v;
+ }
+}
QT_END_NAMESPACE
diff --git a/src/qml/jsruntime/qv4mm_p.h b/src/qml/jsruntime/qv4mm_p.h
index f72d23dc9a..abbc0a7b4e 100644
--- a/src/qml/jsruntime/qv4mm_p.h
+++ b/src/qml/jsruntime/qv4mm_p.h
@@ -44,6 +44,7 @@
#include "qv4global_p.h"
#include "qv4context_p.h"
+#include "qv4value_p.h"
#include <QScopedPointer>
@@ -129,6 +130,7 @@ protected:
private:
void collectFromStack() const;
+ void collectFromJSStack() const;
void mark();
std::size_t sweep(bool lastSweep = false);
std::size_t sweep(char *chunkStart, std::size_t chunkSize, size_t size, GCDeletable **deletable);
diff --git a/src/qml/jsruntime/qv4numberobject.cpp b/src/qml/jsruntime/qv4numberobject.cpp
index 88c61489db..ffcbca2ce5 100644
--- a/src/qml/jsruntime/qv4numberobject.cpp
+++ b/src/qml/jsruntime/qv4numberobject.cpp
@@ -56,15 +56,15 @@ NumberCtor::NumberCtor(ExecutionContext *scope)
vtbl = &static_vtbl;
}
-Value NumberCtor::construct(Managed *m, const CallData &d)
+Value NumberCtor::construct(Managed *m, CallData *callData)
{
- double dbl = d.argc ? d.args[0].toNumber() : 0.;
+ double dbl = callData->argc ? callData->args[0].toNumber() : 0.;
return Value::fromObject(m->engine()->newNumberObject(Value::fromDouble(dbl)));
}
-Value NumberCtor::call(Managed *, const CallData &d)
+Value NumberCtor::call(Managed *, CallData *callData)
{
- double dbl = d.argc ? d.args[0].toNumber() : 0.;
+ double dbl = callData->argc ? callData->args[0].toNumber() : 0.;
return Value::fromDouble(dbl);
}
@@ -225,7 +225,9 @@ Value NumberPrototype::method_toExponential(SimpleCallContext *ctx)
Value NumberPrototype::method_toPrecision(SimpleCallContext *ctx)
{
- Value v = thisNumberValue(ctx);
+ ValueScope scope(ctx);
+
+ ScopedValue v(scope, thisNumberValue(ctx));
Value prec = ctx->argument(0);
if (prec.isUndefined())
@@ -239,7 +241,7 @@ Value NumberPrototype::method_toPrecision(SimpleCallContext *ctx)
char str[100];
double_conversion::StringBuilder builder(str, sizeof(str));
- double_conversion::DoubleToStringConverter::EcmaScriptConverter().ToPrecision(v.asDouble(), precision, &builder);
+ double_conversion::DoubleToStringConverter::EcmaScriptConverter().ToPrecision(v->asDouble(), precision, &builder);
QString result = QString::fromLatin1(builder.Finalize());
return Value::fromString(ctx, result);
diff --git a/src/qml/jsruntime/qv4numberobject_p.h b/src/qml/jsruntime/qv4numberobject_p.h
index 096b4b3d9f..a0c2a65e80 100644
--- a/src/qml/jsruntime/qv4numberobject_p.h
+++ b/src/qml/jsruntime/qv4numberobject_p.h
@@ -53,8 +53,8 @@ struct NumberCtor: FunctionObject
{
NumberCtor(ExecutionContext *scope);
- static Value construct(Managed *that, const CallData &d);
- static Value call(Managed *, const CallData &d);
+ static Value construct(Managed *that, CallData *callData);
+ static Value call(Managed *, CallData *callData);
protected:
static const ManagedVTable static_vtbl;
diff --git a/src/qml/jsruntime/qv4object.cpp b/src/qml/jsruntime/qv4object.cpp
index c3c444b7b9..14584da46d 100644
--- a/src/qml/jsruntime/qv4object.cpp
+++ b/src/qml/jsruntime/qv4object.cpp
@@ -47,6 +47,7 @@
#include "qv4argumentsobject_p.h"
#include "qv4mm_p.h"
#include "qv4lookup_p.h"
+#include "qv4scopedvalue_p.h"
#include <private/qqmljsengine_p.h>
#include <private/qqmljslexer_p.h>
@@ -134,19 +135,19 @@ Value Object::getValue(const Value &thisObject, const Property *p, PropertyAttri
if (!getter)
return Value::undefinedValue();
- CALLDATA(0);
- d.thisObject = thisObject;
- return getter->call(d);
+ ScopedCallData callData(getter->engine(), 0);
+ callData->thisObject = thisObject;
+ return getter->call(callData);
}
void Object::putValue(Property *pd, PropertyAttributes attrs, const Value &value)
{
if (attrs.isAccessor()) {
if (pd->set) {
- CALLDATA(1);
- d.args[0] = value;
- d.thisObject = Value::fromObject(this);
- pd->set->call(d);
+ ScopedCallData callData(pd->set->engine(), 1);
+ callData->args[0] = value;
+ callData->thisObject = Value::fromObject(this);
+ pd->set->call(callData);
return;
}
goto reject;
@@ -164,50 +165,54 @@ void Object::putValue(Property *pd, PropertyAttributes attrs, const Value &value
}
-void Object::inplaceBinOp(ExecutionContext *, BinOp op, String *name, const Value &rhs)
+void Object::inplaceBinOp(ExecutionContext *ctx, BinOp op, String *name, const ValueRef rhs)
{
- Value v = get(name);
- Value result;
- op(&result, v, rhs);
+ ValueScope scope(ctx);
+ ScopedValue v(scope, get(name));
+ ScopedValue result(scope);
+ op(result, v, rhs);
put(name, result);
}
-void Object::inplaceBinOp(ExecutionContext *ctx, BinOp op, const Value &index, const Value &rhs)
+void Object::inplaceBinOp(ExecutionContext *ctx, BinOp op, const ValueRef index, const ValueRef rhs)
{
- uint idx = index.asArrayIndex();
+ ValueScope scope(ctx);
+ uint idx = index->asArrayIndex();
if (idx < UINT_MAX) {
bool hasProperty = false;
- Value v = getIndexed(idx, &hasProperty);
- Value result;
- op(&result, v, rhs);
+ ScopedValue v(scope, getIndexed(idx, &hasProperty));
+ ScopedValue result(scope);
+ op(result, v, rhs);
putIndexed(idx, result);
return;
}
- String *name = index.toString(ctx);
+ String *name = index->toString(ctx);
assert(name);
inplaceBinOp(ctx, op, name, rhs);
}
-void Object::inplaceBinOp(ExecutionContext *ctx, BinOpContext op, String *name, const Value &rhs)
+void Object::inplaceBinOp(ExecutionContext *ctx, BinOpContext op, String *name, const ValueRef rhs)
{
- Value v = get(name);
- Value result;
- op(ctx, &result, v, rhs);
+ ValueScope scope(ctx);
+ ScopedValue v(scope, get(name));
+ ScopedValue result(scope);
+ op(ctx, result, v, rhs);
put(name, result);
}
-void Object::inplaceBinOp(ExecutionContext *ctx, BinOpContext op, const Value &index, const Value &rhs)
+void Object::inplaceBinOp(ExecutionContext *ctx, BinOpContext op, const ValueRef index, const ValueRef rhs)
{
- uint idx = index.asArrayIndex();
+ ValueScope scope(ctx);
+ uint idx = index->asArrayIndex();
if (idx < UINT_MAX) {
bool hasProperty = false;
- Value v = getIndexed(idx, &hasProperty);
- Value result;
- op(ctx, &result, v, rhs);
+ ScopedValue v(scope, getIndexed(idx, &hasProperty));
+ ScopedValue result(scope);
+ op(ctx, result, v, rhs);
putIndexed(idx, result);
return;
}
- String *name = index.toString(ctx);
+ String *name = index->toString(ctx);
assert(name);
inplaceBinOp(ctx, op, name, rhs);
}
@@ -773,10 +778,10 @@ void Object::internalPut(String *name, const Value &value)
if (pd && attrs.isAccessor()) {
assert(pd->setter() != 0);
- CALLDATA(1);
- d.args[0] = value;
- d.thisObject = Value::fromObject(this);
- pd->setter()->call(d);
+ ScopedCallData callData(engine(), 1);
+ callData->args[0] = value;
+ callData->thisObject = Value::fromObject(this);
+ pd->setter()->call(callData);
return;
}
@@ -851,10 +856,10 @@ void Object::internalPutIndexed(uint index, const Value &value)
if (pd && attrs.isAccessor()) {
assert(pd->setter() != 0);
- CALLDATA(1);
- d.args[0] = value;
- d.thisObject = Value::fromObject(this);
- pd->setter()->call(d);
+ ScopedCallData callData(engine(), 1);
+ callData->args[0] = value;
+ callData->thisObject = Value::fromObject(this);
+ pd->setter()->call(callData);
return;
}
@@ -1132,18 +1137,21 @@ void Object::copyArrayData(Object *other)
Value Object::arrayIndexOf(Value v, uint fromIndex, uint endIndex, ExecutionContext *ctx, Object *o)
{
+ ValueScope scope(engine());
+ ScopedValue value(scope);
+
if (o->protoHasArray() || o->arrayAttributes) {
// lets be safe and slow
for (uint i = fromIndex; i < endIndex; ++i) {
bool exists;
- Value value = o->getIndexed(i, &exists);
- if (exists && __qmljs_strict_equal(value, v))
+ value = o->getIndexed(i, &exists);
+ if (exists && __qmljs_strict_equal(value, ValueRef(&v)))
return Value::fromDouble(i);
}
} else if (sparseArray) {
for (SparseArrayNode *n = sparseArray->lowerBound(fromIndex); n != sparseArray->end() && n->key() < endIndex; n = n->nextNode()) {
- Value value = o->getValue(arrayData + n->value, arrayAttributes ? arrayAttributes[n->value] : Attr_Data);
- if (__qmljs_strict_equal(value, v))
+ value = o->getValue(arrayData + n->value, arrayAttributes ? arrayAttributes[n->value] : Attr_Data);
+ if (__qmljs_strict_equal(value, ValueRef(&v)))
return Value::fromDouble(n->key());
}
} else {
@@ -1154,8 +1162,8 @@ Value Object::arrayIndexOf(Value v, uint fromIndex, uint endIndex, ExecutionCont
pd += fromIndex;
while (pd < end) {
if (!arrayAttributes || !arrayAttributes[pd - arrayData].isGeneric()) {
- Value value = o->getValue(pd, arrayAttributes ? arrayAttributes[pd - arrayData] : Attr_Data);
- if (__qmljs_strict_equal(value, v))
+ value = o->getValue(pd, arrayAttributes ? arrayAttributes[pd - arrayData] : Attr_Data);
+ if (__qmljs_strict_equal(value, ValueRef(&v)))
return Value::fromDouble(pd - arrayData);
}
++pd;
@@ -1246,6 +1254,9 @@ void Object::arraySort(ExecutionContext *context, Object *thisObject, const Valu
}
}
+ if (!(comparefn.isUndefined() || comparefn.asObject()))
+ context->throwTypeError();
+
ArrayElementLessThan lessThan(context, thisObject, comparefn);
Property *begin = arrayData;
diff --git a/src/qml/jsruntime/qv4object_p.h b/src/qml/jsruntime/qv4object_p.h
index 995749ff74..c6329b9665 100644
--- a/src/qml/jsruntime/qv4object_p.h
+++ b/src/qml/jsruntime/qv4object_p.h
@@ -156,10 +156,10 @@ struct Q_QML_EXPORT Object: Managed {
void putValue(Property *pd, PropertyAttributes attrs, const Value &value);
- void inplaceBinOp(ExecutionContext *, BinOp op, String *name, const Value &rhs);
- void inplaceBinOp(ExecutionContext *ctx, BinOp op, const Value &index, const Value &rhs);
- void inplaceBinOp(ExecutionContext *ctx, BinOpContext op, String *name, const Value &rhs);
- void inplaceBinOp(ExecutionContext *ctx, BinOpContext op, const Value &index, const Value &rhs);
+ void inplaceBinOp(ExecutionContext *, BinOp op, String *name, const ValueRef rhs);
+ void inplaceBinOp(ExecutionContext *ctx, BinOp op, const ValueRef index, const ValueRef rhs);
+ void inplaceBinOp(ExecutionContext *ctx, BinOpContext op, String *name, const ValueRef rhs);
+ void inplaceBinOp(ExecutionContext *ctx, BinOpContext op, const ValueRef index, const ValueRef rhs);
/* The spec default: Writable: true, Enumerable: false, Configurable: true */
void defineDefaultProperty(String *name, Value value);
diff --git a/src/qml/jsruntime/qv4objectproto.cpp b/src/qml/jsruntime/qv4objectproto.cpp
index fbf86645e2..2f8f6375f0 100644
--- a/src/qml/jsruntime/qv4objectproto.cpp
+++ b/src/qml/jsruntime/qv4objectproto.cpp
@@ -42,6 +42,7 @@
#include "qv4objectproto_p.h"
#include "qv4mm_p.h"
+#include "qv4scopedvalue_p.h"
#include <QtCore/qnumeric.h>
#include <QtCore/qmath.h>
#include <QtCore/QDateTime>
@@ -78,25 +79,25 @@ ObjectCtor::ObjectCtor(ExecutionContext *scope)
vtbl = &static_vtbl;
}
-Value ObjectCtor::construct(Managed *that, const CallData &d)
+Value ObjectCtor::construct(Managed *that, CallData *callData)
{
ObjectCtor *ctor = static_cast<ObjectCtor *>(that);
ExecutionEngine *v4 = that->engine();
- if (!d.argc || d.args[0].isUndefined() || d.args[0].isNull()) {
+ if (!callData->argc || callData->args[0].isUndefined() || callData->args[0].isNull()) {
Object *obj = v4->newObject();
Value proto = ctor->get(v4->id_prototype);
if (proto.isObject())
obj->setPrototype(proto.objectValue());
return Value::fromObject(obj);
}
- return __qmljs_to_object(v4->current, d.args[0]);
+ return __qmljs_to_object(v4->current, ValueRef(&callData->args[0]));
}
-Value ObjectCtor::call(Managed *m, const CallData &d)
+Value ObjectCtor::call(Managed *m, CallData *callData)
{
- if (!d.argc || d.args[0].isUndefined() || d.args[0].isNull())
+ if (!callData->argc || callData->args[0].isUndefined() || callData->args[0].isNull())
return Value::fromObject(m->engine()->newObject());
- return __qmljs_to_object(m->engine()->current, d.args[0]);
+ return __qmljs_to_object(m->engine()->current, ValueRef(&callData->args[0]));
}
void ObjectPrototype::init(ExecutionContext *ctx, const Value &ctor)
@@ -372,7 +373,7 @@ Value ObjectPrototype::method_toString(SimpleCallContext *ctx)
} else if (ctx->thisObject.isNull()) {
return Value::fromString(ctx, QStringLiteral("[object Null]"));
} else {
- Value obj = __qmljs_to_object(ctx, ctx->thisObject);
+ Value obj = __qmljs_to_object(ctx, ValueRef(&ctx->thisObject));
QString className = obj.objectValue()->className();
return Value::fromString(ctx, QString::fromUtf8("[object %1]").arg(className));
}
@@ -385,9 +386,9 @@ Value ObjectPrototype::method_toLocaleString(SimpleCallContext *ctx)
FunctionObject *f = ts.asFunctionObject();
if (!f)
ctx->throwTypeError();
- CALLDATA(0);
- d.thisObject = Value::fromObject(o);
- return f->call(d);
+ ScopedCallData callData(ctx->engine, 0);
+ callData->thisObject = Value::fromObject(o);
+ return f->call(callData);
}
Value ObjectPrototype::method_valueOf(SimpleCallContext *ctx)
diff --git a/src/qml/jsruntime/qv4objectproto_p.h b/src/qml/jsruntime/qv4objectproto_p.h
index be51c41580..33a115f203 100644
--- a/src/qml/jsruntime/qv4objectproto_p.h
+++ b/src/qml/jsruntime/qv4objectproto_p.h
@@ -53,8 +53,8 @@ struct ObjectCtor: FunctionObject
{
ObjectCtor(ExecutionContext *scope);
- static Value construct(Managed *that, const CallData &d);
- static Value call(Managed *that, const CallData &d);
+ static Value construct(Managed *that, CallData *callData);
+ static Value call(Managed *that, CallData *callData);
protected:
static const ManagedVTable static_vtbl;
diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp
index 9e80c82165..1e868ef3fe 100644
--- a/src/qml/jsruntime/qv4qobjectwrapper.cpp
+++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp
@@ -62,6 +62,7 @@
#include <private/qv4objectproto_p.h>
#include <private/qv4jsonobject_p.h>
#include <private/qv4regexpobject_p.h>
+#include <private/qv4scopedvalue_p.h>
#include <QtQml/qjsvalue.h>
#include <QtCore/qjsonarray.h>
@@ -700,19 +701,19 @@ struct QObjectSlotDispatcher : public QtPrivate::QSlotObjectBase
QV4::ExecutionEngine *v4 = f->internalClass->engine;
QV4::ExecutionContext *ctx = v4->current;
- CALLDATA(argCount);
- d.thisObject = This->thisObject.isEmpty() ? Value::fromObject(v4->globalObject) : This->thisObject.value();
+ QV4::ScopedCallData callData(v4, argCount);
+ callData->thisObject = This->thisObject.isEmpty() ? Value::fromObject(v4->globalObject) : This->thisObject.value();
for (int ii = 0; ii < argCount; ++ii) {
int type = argsTypes[ii + 1];
if (type == qMetaTypeId<QVariant>()) {
- d.args[ii] = v4->v8Engine->fromVariant(*((QVariant *)metaArgs[ii + 1]));
+ callData->args[ii] = v4->v8Engine->fromVariant(*((QVariant *)metaArgs[ii + 1]));
} else {
- d.args[ii] = v4->v8Engine->fromVariant(QVariant(type, metaArgs[ii + 1]));
+ callData->args[ii] = v4->v8Engine->fromVariant(QVariant(type, metaArgs[ii + 1]));
}
}
try {
- f->call(d);
+ f->call(callData);
} catch (QV4::Exception &e) {
e.accept(ctx);
QQmlError error;
@@ -739,14 +740,15 @@ struct QObjectSlotDispatcher : public QtPrivate::QSlotObjectBase
return;
}
- QV4::Value function = *reinterpret_cast<QV4::Value*>(metaArgs[1]);
- QV4::Value thisObject = *reinterpret_cast<QV4::Value*>(metaArgs[2]);
+ QV4::ValueScope scope(v4);
+ QV4::ScopedValue function(scope, *reinterpret_cast<QV4::Value*>(metaArgs[1]));
+ QV4::ScopedValue thisObject(scope, *reinterpret_cast<QV4::Value*>(metaArgs[2]));
QObject *receiverToDisconnect = reinterpret_cast<QObject*>(metaArgs[3]);
int slotIndexToDisconnect = *reinterpret_cast<int*>(metaArgs[4]);
if (slotIndexToDisconnect != -1) {
// This is a QObject function wrapper
- if (connection->thisObject.isEmpty() == thisObject.isEmpty() &&
+ if (connection->thisObject.isEmpty() == thisObject->isEmpty() &&
(connection->thisObject.isEmpty() || __qmljs_strict_equal(connection->thisObject, thisObject))) {
QPair<QObject *, int> connectedFunctionData = extractQtMethod(connection->function.value().asFunctionObject());
@@ -759,7 +761,7 @@ struct QObjectSlotDispatcher : public QtPrivate::QSlotObjectBase
} else {
// This is a normal JS function
if (__qmljs_strict_equal(connection->function, function) &&
- connection->thisObject.isEmpty() == thisObject.isEmpty() &&
+ connection->thisObject.isEmpty() == thisObject->isEmpty() &&
(connection->thisObject.isEmpty() || __qmljs_strict_equal(connection->thisObject, thisObject))) {
*ret = true;
return;
@@ -1009,13 +1011,13 @@ private:
namespace {
struct CallArgs
{
- CallArgs(int length, QV4::Value *args) : _length(length), _args(args) {}
+ CallArgs(int length, const QV4::Value *args) : _length(length), _args(args) {}
int Length() const { return _length; }
QV4::Value operator[](int idx) { return _args[idx]; }
private:
int _length;
- QV4::Value *_args;
+ const QV4::Value *_args;
};
}
@@ -1667,7 +1669,7 @@ QV4::Value QObjectMethod::method_toString(QV4::ExecutionContext *ctx)
return QV4::Value::fromString(ctx, result);
}
-QV4::Value QObjectMethod::method_destroy(QV4::ExecutionContext *ctx, Value *args, int argc)
+QV4::Value QObjectMethod::method_destroy(QV4::ExecutionContext *ctx, const Value *args, int argc)
{
if (!m_object)
return QV4::Value::undefinedValue();
@@ -1686,17 +1688,17 @@ QV4::Value QObjectMethod::method_destroy(QV4::ExecutionContext *ctx, Value *args
return QV4::Value::undefinedValue();
}
-Value QObjectMethod::call(Managed *m, const CallData &d)
+Value QObjectMethod::call(Managed *m, CallData *callData)
{
QObjectMethod *This = static_cast<QObjectMethod*>(m);
- return This->callInternal(d);
+ return This->callInternal(callData);
}
-Value QObjectMethod::callInternal(const CallData &d)
+Value QObjectMethod::callInternal(CallData *callData)
{
ExecutionContext *context = engine()->current;
if (m_index == DestroyMethod)
- return method_destroy(context, d.args, d.argc);
+ return method_destroy(context, callData->args, callData->argc);
else if (m_index == ToStringMethod)
return method_toString(context);
@@ -1731,7 +1733,7 @@ Value QObjectMethod::callInternal(const CallData &d)
if (method.isV4Function()) {
QV4::Value rv = QV4::Value::undefinedValue();
- QQmlV4Function func(d.argc, d.args, &rv, m_qmlGlobal.value(),
+ QQmlV4Function func(callData->argc, callData->args, &rv, m_qmlGlobal.value(),
QmlContextWrapper::getContext(m_qmlGlobal.value()),
v8Engine);
QQmlV4Function *funcptr = &func;
@@ -1742,7 +1744,7 @@ Value QObjectMethod::callInternal(const CallData &d)
return rv;
}
- CallArgs callArgs(d.argc, d.args);
+ CallArgs callArgs(callData->argc, callData->args);
if (!method.isOverload()) {
return CallPrecise(object, method, v8Engine, callArgs);
} else {
diff --git a/src/qml/jsruntime/qv4qobjectwrapper_p.h b/src/qml/jsruntime/qv4qobjectwrapper_p.h
index 39af02f38b..3a48fee1ec 100644
--- a/src/qml/jsruntime/qv4qobjectwrapper_p.h
+++ b/src/qml/jsruntime/qv4qobjectwrapper_p.h
@@ -135,15 +135,15 @@ private:
QObjectMethod(QV4::ExecutionContext *scope, QObject *object, int index, const QV4::Value &qmlGlobal);
QV4::Value method_toString(QV4::ExecutionContext *ctx);
- QV4::Value method_destroy(QV4::ExecutionContext *ctx, Value *args, int argc);
+ QV4::Value method_destroy(QV4::ExecutionContext *ctx, const Value *args, int argc);
QPointer<QObject> m_object;
int m_index;
QV4::PersistentValue m_qmlGlobal;
- static Value call(Managed *, const CallData &d);
+ static Value call(Managed *, CallData *callData);
- Value callInternal(const CallData &d);
+ Value callInternal(CallData *callData);
static void destroy(Managed *that)
{
diff --git a/src/qml/jsruntime/qv4regexpobject.cpp b/src/qml/jsruntime/qv4regexpobject.cpp
index c213c78aeb..448d10180c 100644
--- a/src/qml/jsruntime/qv4regexpobject.cpp
+++ b/src/qml/jsruntime/qv4regexpobject.cpp
@@ -45,6 +45,7 @@
#include "qv4objectproto_p.h"
#include "qv4stringobject_p.h"
#include "qv4mm_p.h"
+#include "qv4scopedvalue_p.h"
#include <private/qqmljsengine_p.h>
#include <private/qqmljslexer_p.h>
@@ -228,13 +229,15 @@ RegExpCtor::RegExpCtor(ExecutionContext *scope)
vtbl = &static_vtbl;
}
-Value RegExpCtor::construct(Managed *m, const CallData &d)
+Value RegExpCtor::construct(Managed *m, CallData *callData)
{
- Value r = d.argc > 0 ? d.args[0] : Value::undefinedValue();
- Value f = d.argc > 1 ? d.args[1] : Value::undefinedValue();
ExecutionContext *ctx = m->engine()->current;
- if (RegExpObject *re = r.as<RegExpObject>()) {
- if (!f.isUndefined())
+ ValueScope scope(ctx);
+
+ ScopedValue r(scope, callData->argc > 0 ? callData->args[0] : Value::undefinedValue());
+ ScopedValue f(scope, callData->argc > 1 ? callData->args[1] : Value::undefinedValue());
+ if (RegExpObject *re = r->as<RegExpObject>()) {
+ if (!f->isUndefined())
ctx->throwTypeError();
RegExpObject *o = ctx->engine->newRegExpObject(re->value, re->global);
@@ -242,15 +245,15 @@ Value RegExpCtor::construct(Managed *m, const CallData &d)
}
QString pattern;
- if (!r.isUndefined())
- pattern = r.toString(ctx)->toQString();
+ if (!r->isUndefined())
+ pattern = r->toString(ctx)->toQString();
bool global = false;
bool ignoreCase = false;
bool multiLine = false;
- if (!f.isUndefined()) {
+ if (!f->isUndefined()) {
f = __qmljs_to_string(f, ctx);
- QString str = f.stringValue()->toQString();
+ QString str = f->stringValue()->toQString();
for (int i = 0; i < str.length(); ++i) {
if (str.at(i) == QChar('g') && !global) {
global = true;
@@ -272,14 +275,14 @@ Value RegExpCtor::construct(Managed *m, const CallData &d)
return Value::fromObject(o);
}
-Value RegExpCtor::call(Managed *that, const CallData &d)
+Value RegExpCtor::call(Managed *that, CallData *callData)
{
- if (d.argc > 0 && d.args[0].as<RegExpObject>()) {
- if (d.argc == 1 || d.args[1].isUndefined())
- return d.args[0];
+ if (callData->argc > 0 && callData->args[0].as<RegExpObject>()) {
+ if (callData->argc == 1 || callData->args[1].isUndefined())
+ return callData->args[0];
}
- return construct(that, d);
+ return construct(that, callData);
}
void RegExpPrototype::init(ExecutionContext *ctx, const Value &ctor)
@@ -295,13 +298,15 @@ void RegExpPrototype::init(ExecutionContext *ctx, const Value &ctor)
Value RegExpPrototype::method_exec(SimpleCallContext *ctx)
{
+ ValueScope scope(ctx);
+
RegExpObject *r = ctx->thisObject.as<RegExpObject>();
if (!r)
ctx->throwTypeError();
- Value arg = ctx->argument(0);
+ ScopedValue arg(scope, ctx->argument(0));
arg = __qmljs_to_string(arg, ctx);
- QString s = arg.stringValue()->toQString();
+ QString s = arg->stringValue()->toQString();
int offset = r->global ? r->lastIndexProperty(ctx)->value.toInt32() : 0;
if (offset < 0 || offset > s.length()) {
@@ -358,10 +363,9 @@ Value RegExpPrototype::method_compile(SimpleCallContext *ctx)
if (!r)
ctx->throwTypeError();
- CallData d;
- d.args = ctx->arguments;
- d.argc = ctx->argumentCount;
- RegExpObject *re = ctx->engine->regExpCtor.asFunctionObject()->construct(d).as<RegExpObject>();
+ ScopedCallData callData(ctx->engine, ctx->argumentCount);
+ memcpy(callData->args, ctx->arguments, ctx->argumentCount*sizeof(Value));
+ RegExpObject *re = ctx->engine->regExpCtor.asFunctionObject()->construct(callData).as<RegExpObject>();
r->value = re->value;
r->global = re->global;
diff --git a/src/qml/jsruntime/qv4regexpobject_p.h b/src/qml/jsruntime/qv4regexpobject_p.h
index 80868d90db..a17802e2ff 100644
--- a/src/qml/jsruntime/qv4regexpobject_p.h
+++ b/src/qml/jsruntime/qv4regexpobject_p.h
@@ -105,8 +105,8 @@ struct RegExpCtor: FunctionObject
{
RegExpCtor(ExecutionContext *scope);
- static Value construct(Managed *m, const CallData &d);
- static Value call(Managed *that, const CallData &d);
+ static Value construct(Managed *m, CallData *callData);
+ static Value call(Managed *that, CallData *callData);
protected:
static const ManagedVTable static_vtbl;
diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp
index 33521efb02..733f353330 100644
--- a/src/qml/jsruntime/qv4runtime.cpp
+++ b/src/qml/jsruntime/qv4runtime.cpp
@@ -51,6 +51,7 @@
#include "qv4function_p.h"
#include "qv4exception_p.h"
#include "private/qlocale_tools_p.h"
+#include "qv4scopedvalue_p.h"
#include <QtCore/qmath.h>
#include <QtCore/qnumeric.h>
@@ -119,17 +120,17 @@ void __qmljs_numberToString(QString *result, double num, int radix)
result->prepend(QLatin1Char('-'));
}
-void __qmljs_init_closure(ExecutionContext *ctx, Value *result, int functionId)
+void __qmljs_init_closure(ExecutionContext *ctx, ValueRef result, int functionId)
{
QV4::Function *clos = ctx->compilationUnit->runtimeFunctions[functionId];
assert(clos);
*result = Value::fromObject(FunctionObject::creatScriptFunction(ctx, clos));
}
-void __qmljs_delete_subscript(ExecutionContext *ctx, Value *result, const Value &base, const Value &index)
+void __qmljs_delete_subscript(ExecutionContext *ctx, ValueRef result, const ValueRef base, const ValueRef index)
{
- if (Object *o = base.asObject()) {
- uint n = index.asArrayIndex();
+ if (Object *o = base->asObject()) {
+ uint n = index->asArrayIndex();
if (n < UINT_MAX) {
Value res = Value::fromBoolean(o->deleteIndexedProperty(n));
if (result)
@@ -138,35 +139,37 @@ void __qmljs_delete_subscript(ExecutionContext *ctx, Value *result, const Value
}
}
- String *name = index.toString(ctx);
+ String *name = index->toString(ctx);
__qmljs_delete_member(ctx, result, base, name);
}
-void __qmljs_delete_member(ExecutionContext *ctx, Value *result, const Value &base, String *name)
+void __qmljs_delete_member(ExecutionContext *ctx, ValueRef result, const ValueRef base, String *name)
{
- Object *obj = base.toObject(ctx);
+ Object *obj = base->toObject(ctx);
Value res = Value::fromBoolean(obj->deleteProperty(name));
if (result)
*result = res;
}
-void __qmljs_delete_name(ExecutionContext *ctx, Value *result, String *name)
+void __qmljs_delete_name(ExecutionContext *ctx, ValueRef result, String *name)
{
Value res = Value::fromBoolean(ctx->deleteProperty(name));
if (result)
*result = res;
}
-void __qmljs_add_helper(ExecutionContext *ctx, Value *result, const Value &left, const Value &right)
+void __qmljs_add_helper(ExecutionContext *ctx, ValueRef result, const ValueRef left, const ValueRef right)
{
- Value pleft = __qmljs_to_primitive(left, PREFERREDTYPE_HINT);
- Value pright = __qmljs_to_primitive(right, PREFERREDTYPE_HINT);
- if (pleft.isString() || pright.isString()) {
- if (!pleft.isString())
+ ValueScope scope(ctx);
+
+ ScopedValue pleft(scope, __qmljs_to_primitive(left, PREFERREDTYPE_HINT));
+ ScopedValue pright(scope, __qmljs_to_primitive(right, PREFERREDTYPE_HINT));
+ if (pleft->isString() || pright->isString()) {
+ if (!pleft->isString())
pleft = __qmljs_to_string(pleft, ctx);
- if (!pright.isString())
+ if (!pright->isString())
pright = __qmljs_to_string(pright, ctx);
- String *string = __qmljs_string_concat(ctx, pleft.stringValue(), pright.stringValue());
+ String *string = __qmljs_string_concat(ctx, pleft->stringValue(), pright->stringValue());
*result = Value::fromString(string);
return;
}
@@ -175,212 +178,223 @@ void __qmljs_add_helper(ExecutionContext *ctx, Value *result, const Value &left,
*result = Value::fromDouble(x + y);
}
-void __qmljs_instanceof(ExecutionContext *ctx, Value *result, const Value &left, const Value &right)
+void __qmljs_instanceof(ExecutionContext *ctx, ValueRef result, const ValueRef left, const ValueRef right)
{
- Object *o = right.asObject();
+ Object *o = right->asObject();
if (!o)
ctx->throwTypeError();
- bool r = o->hasInstance(left);
+ bool r = o->hasInstance(*left);
*result = Value::fromBoolean(r);
}
-void __qmljs_in(ExecutionContext *ctx, Value *result, const Value &left, const Value &right)
+void __qmljs_in(ExecutionContext *ctx, ValueRef result, const ValueRef left, const ValueRef right)
{
- if (!right.isObject())
+ if (!right->isObject())
ctx->throwTypeError();
- String *s = left.toString(ctx);
- bool r = right.objectValue()->__hasProperty__(s);
+ String *s = left->toString(ctx);
+ bool r = right->objectValue()->__hasProperty__(s);
*result = Value::fromBoolean(r);
}
-void __qmljs_inplace_bit_and_name(ExecutionContext *ctx, String *name, const Value &value)
+static void inplaceBitOp(ExecutionContext *ctx, String *name, const ValueRef value, BinOp op)
+{
+ ValueScope scope(ctx);
+ ScopedValue lhs(scope, ctx->getProperty(name));
+ ScopedValue result(scope);
+ op(result, lhs, value);
+ ctx->setProperty(name, result);
+}
+
+
+void __qmljs_inplace_bit_and_name(ExecutionContext *ctx, String *name, const ValueRef value)
{
- ctx->inplaceBitOp(name, value, __qmljs_bit_and);
+ inplaceBitOp(ctx, name, value, __qmljs_bit_and);
}
-void __qmljs_inplace_bit_or_name(ExecutionContext *ctx, String *name, const Value &value)
+void __qmljs_inplace_bit_or_name(ExecutionContext *ctx, String *name, const ValueRef value)
{
- ctx->inplaceBitOp(name, value, __qmljs_bit_or);
+ inplaceBitOp(ctx, name, value, __qmljs_bit_or);
}
-void __qmljs_inplace_bit_xor_name(ExecutionContext *ctx, String *name, const Value &value)
+void __qmljs_inplace_bit_xor_name(ExecutionContext *ctx, String *name, const ValueRef value)
{
- ctx->inplaceBitOp(name, value, __qmljs_bit_xor);
+ inplaceBitOp(ctx, name, value, __qmljs_bit_xor);
}
-void __qmljs_inplace_add_name(ExecutionContext *ctx, String *name, const Value &value)
+void __qmljs_inplace_add_name(ExecutionContext *ctx, String *name, const ValueRef value)
{
- Value lhs = ctx->getProperty(name);
- Value result;
- __qmljs_add(ctx, &result, lhs, value);
+ ValueScope scope(ctx);
+ ScopedValue lhs(scope, ctx->getProperty(name));
+ ScopedValue result(scope);
+ __qmljs_add(ctx, result, lhs, value);
ctx->setProperty(name, result);
}
-void __qmljs_inplace_sub_name(ExecutionContext *ctx, String *name, const Value &value)
+void __qmljs_inplace_sub_name(ExecutionContext *ctx, String *name, const ValueRef value)
{
- ctx->inplaceBitOp(name, value, __qmljs_sub);
+ inplaceBitOp(ctx, name, value, __qmljs_sub);
}
-void __qmljs_inplace_mul_name(ExecutionContext *ctx, String *name, const Value &value)
+void __qmljs_inplace_mul_name(ExecutionContext *ctx, String *name, const ValueRef value)
{
- ctx->inplaceBitOp(name, value, __qmljs_mul);
+ inplaceBitOp(ctx, name, value, __qmljs_mul);
}
-void __qmljs_inplace_div_name(ExecutionContext *ctx, String *name, const Value &value)
+void __qmljs_inplace_div_name(ExecutionContext *ctx, String *name, const ValueRef value)
{
- ctx->inplaceBitOp(name, value, __qmljs_div);
+ inplaceBitOp(ctx, name, value, __qmljs_div);
}
-void __qmljs_inplace_mod_name(ExecutionContext *ctx, String *name, const Value &value)
+void __qmljs_inplace_mod_name(ExecutionContext *ctx, String *name, const ValueRef value)
{
- ctx->inplaceBitOp(name, value, __qmljs_mod);
+ inplaceBitOp(ctx, name, value, __qmljs_mod);
}
-void __qmljs_inplace_shl_name(ExecutionContext *ctx, String *name, const Value &value)
+void __qmljs_inplace_shl_name(ExecutionContext *ctx, String *name, const ValueRef value)
{
- ctx->inplaceBitOp(name, value, __qmljs_shl);
+ inplaceBitOp(ctx, name, value, __qmljs_shl);
}
-void __qmljs_inplace_shr_name(ExecutionContext *ctx, String *name, const Value &value)
+void __qmljs_inplace_shr_name(ExecutionContext *ctx, String *name, const ValueRef value)
{
- ctx->inplaceBitOp(name, value, __qmljs_shr);
+ inplaceBitOp(ctx, name, value, __qmljs_shr);
}
-void __qmljs_inplace_ushr_name(ExecutionContext *ctx, String *name, const Value &value)
+void __qmljs_inplace_ushr_name(ExecutionContext *ctx, String *name, const ValueRef value)
{
- ctx->inplaceBitOp(name, value, __qmljs_ushr);
+ inplaceBitOp(ctx, name, value, __qmljs_ushr);
}
-void __qmljs_inplace_bit_and_element(ExecutionContext *ctx, const Value &base, const Value &index, const Value &rhs)
+void __qmljs_inplace_bit_and_element(ExecutionContext *ctx, const ValueRef base, const ValueRef index, const ValueRef rhs)
{
- Object *obj = base.toObject(ctx);
+ Object *obj = base->toObject(ctx);
obj->inplaceBinOp(ctx, __qmljs_bit_and, index, rhs);
}
-void __qmljs_inplace_bit_or_element(ExecutionContext *ctx, const Value &base, const Value &index, const Value &rhs)
+void __qmljs_inplace_bit_or_element(ExecutionContext *ctx, const ValueRef base, const ValueRef index, const ValueRef rhs)
{
- Object *obj = base.toObject(ctx);
+ Object *obj = base->toObject(ctx);
obj->inplaceBinOp(ctx, __qmljs_bit_or, index, rhs);
}
-void __qmljs_inplace_bit_xor_element(ExecutionContext *ctx, const Value &base, const Value &index, const Value &rhs)
+void __qmljs_inplace_bit_xor_element(ExecutionContext *ctx, const ValueRef base, const ValueRef index, const ValueRef rhs)
{
- Object *obj = base.toObject(ctx);
+ Object *obj = base->toObject(ctx);
obj->inplaceBinOp(ctx, __qmljs_bit_xor, index, rhs);
}
-void __qmljs_inplace_add_element(ExecutionContext *ctx, const Value &base, const Value &index, const Value &rhs)
+void __qmljs_inplace_add_element(ExecutionContext *ctx, const ValueRef base, const ValueRef index, const ValueRef rhs)
{
- Object *obj = base.toObject(ctx);
+ Object *obj = base->toObject(ctx);
obj->inplaceBinOp(ctx, __qmljs_add, index, rhs);
}
-void __qmljs_inplace_sub_element(ExecutionContext *ctx, const Value &base, const Value &index, const Value &rhs)
+void __qmljs_inplace_sub_element(ExecutionContext *ctx, const ValueRef base, const ValueRef index, const ValueRef rhs)
{
- Object *obj = base.toObject(ctx);
+ Object *obj = base->toObject(ctx);
obj->inplaceBinOp(ctx, __qmljs_sub, index, rhs);
}
-void __qmljs_inplace_mul_element(ExecutionContext *ctx, const Value &base, const Value &index, const Value &rhs)
+void __qmljs_inplace_mul_element(ExecutionContext *ctx, const ValueRef base, const ValueRef index, const ValueRef rhs)
{
- Object *obj = base.toObject(ctx);
+ Object *obj = base->toObject(ctx);
obj->inplaceBinOp(ctx, __qmljs_mul, index, rhs);
}
-void __qmljs_inplace_div_element(ExecutionContext *ctx, const Value &base, const Value &index, const Value &rhs)
+void __qmljs_inplace_div_element(ExecutionContext *ctx, const ValueRef base, const ValueRef index, const ValueRef rhs)
{
- Object *obj = base.toObject(ctx);
+ Object *obj = base->toObject(ctx);
obj->inplaceBinOp(ctx, __qmljs_div, index, rhs);
}
-void __qmljs_inplace_mod_element(ExecutionContext *ctx, const Value &base, const Value &index, const Value &rhs)
+void __qmljs_inplace_mod_element(ExecutionContext *ctx, const ValueRef base, const ValueRef index, const ValueRef rhs)
{
- Object *obj = base.toObject(ctx);
+ Object *obj = base->toObject(ctx);
obj->inplaceBinOp(ctx, __qmljs_mod, index, rhs);
}
-void __qmljs_inplace_shl_element(ExecutionContext *ctx, const Value &base, const Value &index, const Value &rhs)
+void __qmljs_inplace_shl_element(ExecutionContext *ctx, const ValueRef base, const ValueRef index, const ValueRef rhs)
{
- Object *obj = base.toObject(ctx);
+ Object *obj = base->toObject(ctx);
obj->inplaceBinOp(ctx, __qmljs_shl, index, rhs);
}
-void __qmljs_inplace_shr_element(ExecutionContext *ctx, const Value &base, const Value &index, const Value &rhs)
+void __qmljs_inplace_shr_element(ExecutionContext *ctx, const ValueRef base, const ValueRef index, const ValueRef rhs)
{
- Object *obj = base.toObject(ctx);
+ Object *obj = base->toObject(ctx);
obj->inplaceBinOp(ctx, __qmljs_shr, index, rhs);
}
-void __qmljs_inplace_ushr_element(ExecutionContext *ctx, const Value &base, const Value &index, const Value &rhs)
+void __qmljs_inplace_ushr_element(ExecutionContext *ctx, const ValueRef base, const ValueRef index, const ValueRef rhs)
{
- Object *obj = base.toObject(ctx);
+ Object *obj = base->toObject(ctx);
obj->inplaceBinOp(ctx, __qmljs_ushr, index, rhs);
}
-void __qmljs_inplace_bit_and_member(ExecutionContext *ctx, const Value &base, String *name, const Value &rhs)
+void __qmljs_inplace_bit_and_member(ExecutionContext *ctx, const ValueRef base, String *name, const ValueRef rhs)
{
- Object *o = base.toObject(ctx);
+ Object *o = base->toObject(ctx);
o->inplaceBinOp(ctx, __qmljs_bit_and, name, rhs);
}
-void __qmljs_inplace_bit_or_member(ExecutionContext *ctx, const Value &base, String *name, const Value &rhs)
+void __qmljs_inplace_bit_or_member(ExecutionContext *ctx, const ValueRef base, String *name, const ValueRef rhs)
{
- Object *o = base.toObject(ctx);
+ Object *o = base->toObject(ctx);
o->inplaceBinOp(ctx, __qmljs_bit_or, name, rhs);
}
-void __qmljs_inplace_bit_xor_member(ExecutionContext *ctx, const Value &base, String *name, const Value &rhs)
+void __qmljs_inplace_bit_xor_member(ExecutionContext *ctx, const ValueRef base, String *name, const ValueRef rhs)
{
- Object *o = base.toObject(ctx);
+ Object *o = base->toObject(ctx);
o->inplaceBinOp(ctx, __qmljs_bit_xor, name, rhs);
}
-void __qmljs_inplace_add_member(ExecutionContext *ctx, const Value &base, String *name, const Value &rhs)
+void __qmljs_inplace_add_member(ExecutionContext *ctx, const ValueRef base, String *name, const ValueRef rhs)
{
- Object *o = base.toObject(ctx);
+ Object *o = base->toObject(ctx);
o->inplaceBinOp(ctx, __qmljs_add, name, rhs);
}
-void __qmljs_inplace_sub_member(ExecutionContext *ctx, const Value &base, String *name, const Value &rhs)
+void __qmljs_inplace_sub_member(ExecutionContext *ctx, const ValueRef base, String *name, const ValueRef rhs)
{
- Object *o = base.toObject(ctx);
+ Object *o = base->toObject(ctx);
o->inplaceBinOp(ctx, __qmljs_sub, name, rhs);
}
-void __qmljs_inplace_mul_member(ExecutionContext *ctx, const Value &base, String *name, const Value &rhs)
+void __qmljs_inplace_mul_member(ExecutionContext *ctx, const ValueRef base, String *name, const ValueRef rhs)
{
- Object *o = base.toObject(ctx);
+ Object *o = base->toObject(ctx);
o->inplaceBinOp(ctx, __qmljs_mul, name, rhs);
}
-void __qmljs_inplace_div_member(ExecutionContext *ctx, const Value &base, String *name, const Value &rhs)
+void __qmljs_inplace_div_member(ExecutionContext *ctx, const ValueRef base, String *name, const ValueRef rhs)
{
- Object *o = base.toObject(ctx);
+ Object *o = base->toObject(ctx);
o->inplaceBinOp(ctx, __qmljs_div, name, rhs);
}
-void __qmljs_inplace_mod_member(ExecutionContext *ctx, const Value &base, String *name, const Value &rhs)
+void __qmljs_inplace_mod_member(ExecutionContext *ctx, const ValueRef base, String *name, const ValueRef rhs)
{
- Object *o = base.toObject(ctx);
+ Object *o = base->toObject(ctx);
o->inplaceBinOp(ctx, __qmljs_mod, name, rhs);
}
-void __qmljs_inplace_shl_member(ExecutionContext *ctx, const Value &base, String *name, const Value &rhs)
+void __qmljs_inplace_shl_member(ExecutionContext *ctx, const ValueRef base, String *name, const ValueRef rhs)
{
- Object *o = base.toObject(ctx);
+ Object *o = base->toObject(ctx);
o->inplaceBinOp(ctx, __qmljs_shl, name, rhs);
}
-void __qmljs_inplace_shr_member(ExecutionContext *ctx, const Value &base, String *name, const Value &rhs)
+void __qmljs_inplace_shr_member(ExecutionContext *ctx, const ValueRef base, String *name, const ValueRef rhs)
{
- Object *o = base.toObject(ctx);
+ Object *o = base->toObject(ctx);
o->inplaceBinOp(ctx, __qmljs_shr, name, rhs);
}
-void __qmljs_inplace_ushr_member(ExecutionContext *ctx, const Value &base, String *name, const Value &rhs)
+void __qmljs_inplace_ushr_member(ExecutionContext *ctx, const ValueRef base, String *name, const ValueRef rhs)
{
- Object *o = base.toObject(ctx);
+ Object *o = base->toObject(ctx);
o->inplaceBinOp(ctx, __qmljs_ushr, name, rhs);
}
@@ -446,18 +460,18 @@ Value __qmljs_object_default_value(Object *object, int typeHint)
Value conv = object->get(meth1);
if (FunctionObject *o = conv.asFunctionObject()) {
- CALLDATA(0);
- d.thisObject = Value::fromObject(object);
- Value r = o->call(d);
+ ScopedCallData callData(engine, 0);
+ callData->thisObject = Value::fromObject(object);
+ Value r = o->call(callData);
if (r.isPrimitive())
return r;
}
conv = object->get(meth2);
if (FunctionObject *o = conv.asFunctionObject()) {
- CALLDATA(0);
- d.thisObject = Value::fromObject(object);
- Value r = o->call(d);
+ ScopedCallData callData(engine, 0);
+ callData->thisObject = Value::fromObject(object);
+ Value r = o->call(callData);
if (r.isPrimitive())
return r;
}
@@ -466,74 +480,74 @@ Value __qmljs_object_default_value(Object *object, int typeHint)
return Value::undefinedValue();
}
-Bool __qmljs_to_boolean(const Value &value)
+Bool __qmljs_to_boolean(const ValueRef value)
{
- return value.toBoolean();
+ return value->toBoolean();
}
-Object *__qmljs_convert_to_object(ExecutionContext *ctx, const Value &value)
+Object *__qmljs_convert_to_object(ExecutionContext *ctx, const ValueRef value)
{
- assert(!value.isObject());
- switch (value.type()) {
+ assert(!value->isObject());
+ switch (value->type()) {
case Value::Undefined_Type:
case Value::Null_Type:
ctx->throwTypeError();
case Value::Boolean_Type:
- return ctx->engine->newBooleanObject(value);
+ return ctx->engine->newBooleanObject(*value);
case Value::String_Type:
- return ctx->engine->newStringObject(value);
+ return ctx->engine->newStringObject(*value);
break;
case Value::Object_Type:
Q_UNREACHABLE();
case Value::Integer_Type:
default: // double
- return ctx->engine->newNumberObject(value);
+ return ctx->engine->newNumberObject(*value);
}
}
-String *__qmljs_convert_to_string(ExecutionContext *ctx, const Value &value)
+String *__qmljs_convert_to_string(ExecutionContext *ctx, const ValueRef value)
{
- switch (value.type()) {
+ switch (value->type()) {
case Value::Undefined_Type:
return ctx->engine->id_undefined;
case Value::Null_Type:
return ctx->engine->id_null;
case Value::Boolean_Type:
- if (value.booleanValue())
+ if (value->booleanValue())
return ctx->engine->id_true;
else
return ctx->engine->id_false;
case Value::String_Type:
- return value.stringValue();
+ return value->stringValue();
case Value::Object_Type: {
Value prim = __qmljs_to_primitive(value, STRING_HINT);
if (prim.isPrimitive())
- return __qmljs_convert_to_string(ctx, prim);
+ return __qmljs_convert_to_string(ctx, ValueRef(&prim));
else
ctx->throwTypeError();
}
case Value::Integer_Type:
- return __qmljs_string_from_number(ctx, value.int_32).stringValue();
+ return __qmljs_string_from_number(ctx, value->int_32).stringValue();
default: // double
- return __qmljs_string_from_number(ctx, value.doubleValue()).stringValue();
+ return __qmljs_string_from_number(ctx, value->doubleValue()).stringValue();
} // switch
}
-void __qmljs_set_property(ExecutionContext *ctx, const Value &object, String *name, const Value &value)
+void __qmljs_set_property(ExecutionContext *ctx, const ValueRef object, String *name, const ValueRef value)
{
- Object *o = object.toObject(ctx);
- o->put(name, value);
+ Object *o = object->toObject(ctx);
+ o->put(name, *value);
}
-void __qmljs_get_element(ExecutionContext *ctx, Value *result, const Value &object, const Value &index)
+void __qmljs_get_element(ExecutionContext *ctx, ValueRef result, const ValueRef object, const ValueRef index)
{
- uint idx = index.asArrayIndex();
+ uint idx = index->asArrayIndex();
- Object *o = object.asObject();
+ Object *o = object->asObject();
if (!o) {
if (idx < UINT_MAX) {
- if (String *str = object.asString()) {
+ if (String *str = object->asString()) {
if (idx >= (uint)str->toQString().length()) {
if (result)
*result = Value::undefinedValue();
@@ -546,8 +560,8 @@ void __qmljs_get_element(ExecutionContext *ctx, Value *result, const Value &obje
}
}
- if (object.isNull() || object.isUndefined()) {
- QString message = QStringLiteral("Cannot read property '%1' of %2").arg(index.toQString()).arg(object.toQString());
+ if (object->isNullOrUndefined()) {
+ QString message = QStringLiteral("Cannot read property '%1' of %2").arg(index->toQString()).arg(object->toQString());
ctx->throwTypeError(message);
}
@@ -570,17 +584,17 @@ void __qmljs_get_element(ExecutionContext *ctx, Value *result, const Value &obje
return;
}
- String *name = index.toString(ctx);
+ String *name = index->toString(ctx);
Value res = o->get(name);
if (result)
*result = res;
}
-void __qmljs_set_element(ExecutionContext *ctx, const Value &object, const Value &index, const Value &value)
+void __qmljs_set_element(ExecutionContext *ctx, const ValueRef object, const ValueRef index, const ValueRef value)
{
- Object *o = object.toObject(ctx);
+ Object *o = object->toObject(ctx);
- uint idx = index.asArrayIndex();
+ uint idx = index->asArrayIndex();
if (idx < UINT_MAX) {
uint pidx = o->propertyIndexFromArrayIndex(idx);
if (pidx < UINT_MAX) {
@@ -592,7 +606,7 @@ void __qmljs_set_element(ExecutionContext *ctx, const Value &object, const Value
Property *p = o->arrayData + pidx;
if (!o->arrayAttributes || o->arrayAttributes[pidx].isData()) {
- p->value = value;
+ p->value = *value;
return;
}
@@ -604,55 +618,55 @@ void __qmljs_set_element(ExecutionContext *ctx, const Value &object, const Value
return;
}
- CALLDATA(1);
- d.args[0] = value;
- d.thisObject = Value::fromObject(o);
- setter->call(d);
+ ScopedCallData callData(ctx->engine, 1);
+ callData->thisObject = Value::fromObject(o);
+ callData->args[0] = *value;
+ setter->call(callData);
return;
}
}
- o->putIndexed(idx, value);
+ o->putIndexed(idx, *value);
return;
}
- String *name = index.toString(ctx);
- o->put(name, value);
+ String *name = index->toString(ctx);
+ o->put(name, *value);
}
-void __qmljs_foreach_iterator_object(ExecutionContext *ctx, Value *result, const Value &in)
+void __qmljs_foreach_iterator_object(ExecutionContext *ctx, ValueRef result, const ValueRef in)
{
Object *o = 0;
- if (!in.isNull() && !in.isUndefined())
- o = in.toObject(ctx);
+ if (!in->isNullOrUndefined())
+ o = in->toObject(ctx);
Object *it = ctx->engine->newForEachIteratorObject(ctx, o);
*result = Value::fromObject(it);
}
-void __qmljs_foreach_next_property_name(Value *result, const Value &foreach_iterator)
+void __qmljs_foreach_next_property_name(ValueRef result, const ValueRef foreach_iterator)
{
- assert(foreach_iterator.isObject());
+ assert(foreach_iterator->isObject());
- ForEachIteratorObject *it = static_cast<ForEachIteratorObject *>(foreach_iterator.objectValue());
+ ForEachIteratorObject *it = static_cast<ForEachIteratorObject *>(foreach_iterator->objectValue());
assert(it->as<ForEachIteratorObject>());
*result = it->nextPropertyName();
}
-void __qmljs_set_activation_property(ExecutionContext *ctx, String *name, const Value &value)
+void __qmljs_set_activation_property(ExecutionContext *ctx, String *name, const ValueRef value)
{
- ctx->setProperty(name, value);
+ ctx->setProperty(name, *value);
}
-void __qmljs_get_property(ExecutionContext *ctx, Value *result, const Value &object, String *name)
+void __qmljs_get_property(ExecutionContext *ctx, ValueRef result, const ValueRef object, String *name)
{
Value res;
- Managed *m = object.asManaged();
+ Managed *m = object->asManaged();
if (m) {
res = m->get(name);
} else {
- if (object.isNull() || object.isUndefined()) {
- QString message = QStringLiteral("Cannot read property '%1' of %2").arg(name->toQString()).arg(object.toQString());
+ if (object->isNullOrUndefined()) {
+ QString message = QStringLiteral("Cannot read property '%1' of %2").arg(name->toQString()).arg(object->toQString());
ctx->throwTypeError(message);
}
@@ -663,62 +677,64 @@ void __qmljs_get_property(ExecutionContext *ctx, Value *result, const Value &obj
*result = res;
}
-void __qmljs_get_activation_property(ExecutionContext *ctx, Value *result, String *name)
+void __qmljs_get_activation_property(ExecutionContext *ctx, ValueRef result, String *name)
{
*result = ctx->getProperty(name);
}
-uint __qmljs_equal_helper(const Value &x, const Value &y)
+uint __qmljs_equal_helper(const ValueRef x, const ValueRef y)
{
- Q_ASSERT(x.type() != y.type());
+ Q_ASSERT(x->type() != y->type());
- if (x.isNumber() && y.isNumber())
- return x.asDouble() == y.asDouble();
- if (x.isNull() && y.isUndefined()) {
+ if (x->isNumber() && y->isNumber())
+ return x->asDouble() == y->asDouble();
+ if (x->isNull() && y->isUndefined()) {
return true;
- } else if (x.isUndefined() && y.isNull()) {
+ } else if (x->isUndefined() && y->isNull()) {
return true;
- } else if (x.isNumber() && y.isString()) {
+ } else if (x->isNumber() && y->isString()) {
double dy = __qmljs_to_number(y);
- return x.asDouble() == dy;
- } else if (x.isString() && y.isNumber()) {
+ return x->asDouble() == dy;
+ } else if (x->isString() && y->isNumber()) {
double dx = __qmljs_to_number(x);
- return dx == y.asDouble();
- } else if (x.isBoolean()) {
- Value nx = Value::fromDouble((double) x.booleanValue());
- return __qmljs_cmp_eq(nx, y);
- } else if (y.isBoolean()) {
- Value ny = Value::fromDouble((double) y.booleanValue());
- return __qmljs_cmp_eq(x, ny);
- } else if ((x.isNumber() || x.isString()) && y.isObject()) {
+ return dx == y->asDouble();
+ } else if (x->isBoolean()) {
+ Value nx = Value::fromDouble((double) x->booleanValue());
+ return __qmljs_cmp_eq(ValueRef(&nx), y);
+ } else if (y->isBoolean()) {
+ Value ny = Value::fromDouble((double) y->booleanValue());
+ return __qmljs_cmp_eq(x, ValueRef(&ny));
+ } else if ((x->isNumber() || x->isString()) && y->isObject()) {
Value py = __qmljs_to_primitive(y, PREFERREDTYPE_HINT);
- return __qmljs_cmp_eq(x, py);
- } else if (x.isObject() && (y.isNumber() || y.isString())) {
+ return __qmljs_cmp_eq(x, ValueRef(&py));
+ } else if (x->isObject() && (y->isNumber() || y->isString())) {
Value px = __qmljs_to_primitive(x, PREFERREDTYPE_HINT);
- return __qmljs_cmp_eq(px, y);
+ return __qmljs_cmp_eq(ValueRef(&px), y);
}
return false;
}
-Bool __qmljs_strict_equal(const Value &x, const Value &y)
+Bool __qmljs_strict_equal(const ValueRef x, const ValueRef y)
{
TRACE2(x, y);
- if (x.rawValue() == y.rawValue())
+ if (x->rawValue() == y->rawValue())
// NaN != NaN
- return (x.tag & QV4::Value::NotDouble_Mask) != QV4::Value::NaN_Mask;
+ return (x->tag & QV4::Value::NotDouble_Mask) != QV4::Value::NaN_Mask;
- if (x.isNumber())
- return y.isNumber() && x.asDouble() == y.asDouble();
- if (x.isString())
- return y.isString() && x.stringValue()->isEqualTo(y.stringValue());
+ if (x->isNumber())
+ return y->isNumber() && x->asDouble() == y->asDouble();
+ if (x->isString())
+ return y->isString() && x->stringValue()->isEqualTo(y->stringValue());
return false;
}
-void __qmljs_call_global_lookup(ExecutionContext *context, Value *result, uint index, Value *args, int argc)
+void __qmljs_call_global_lookup(ExecutionContext *context, ValueRef result, uint index, CallDataRef callData)
{
+ Q_ASSERT(callData->thisObject.isUndefined());
+
Lookup *l = context->lookups + index;
Value v;
l->globalGetter(l, context, &v);
@@ -726,29 +742,28 @@ void __qmljs_call_global_lookup(ExecutionContext *context, Value *result, uint i
if (!o)
context->throwTypeError();
- Value thisObject = Value::undefinedValue();
-
if (o == context->engine->evalFunction && l->name->isEqualTo(context->engine->id_eval)) {
- Value res = static_cast<EvalFunction *>(o)->evalCall(thisObject, args, argc, true);
+ Value res = static_cast<EvalFunction *>(o)->evalCall(callData->thisObject, callData->args, callData->argc, true);
if (result)
*result = res;
return;
}
- CallData d;
- d.thisObject = thisObject;
- d.args = args;
- d.argc = argc;
- Value res = o->call(d);
+ Value res = o->call(callData);
if (result)
*result = res;
}
-void __qmljs_call_activation_property(ExecutionContext *context, Value *result, String *name, Value *args, int argc)
+void __qmljs_call_activation_property(ExecutionContext *context, ValueRef result, String *name, CallDataRef callData)
{
+ Q_ASSERT(callData->thisObject.isUndefined());
+
Object *base;
Value func = context->getPropertyAndBase(name, &base);
+ if (base)
+ callData->thisObject = Value::fromObject(base);
+
FunctionObject *o = func.asFunctionObject();
if (!o) {
QString objectAsString = QStringLiteral("[null]");
@@ -758,110 +773,88 @@ void __qmljs_call_activation_property(ExecutionContext *context, Value *result,
context->throwTypeError(msg);
}
- Value thisObject = base ? Value::fromObject(base) : Value::undefinedValue();
-
if (o == context->engine->evalFunction && name->isEqualTo(context->engine->id_eval)) {
- Value res = static_cast<EvalFunction *>(o)->evalCall(thisObject, args, argc, true);
+ Value res = static_cast<EvalFunction *>(o)->evalCall(callData->thisObject, callData->args, callData->argc, true);
if (result)
*result = res;
return;
}
- CallData d;
- d.thisObject = thisObject;
- d.args = args;
- d.argc = argc;
- Value res = o->call(d);
+ Value res = o->call(callData);
if (result)
*result = res;
}
-void __qmljs_call_property(ExecutionContext *context, Value *result, const Value &thatObject, String *name, Value *args, int argc)
+void __qmljs_call_property(ExecutionContext *context, ValueRef result, String *name, CallDataRef callData)
{
- Value thisObject = thatObject;
- Managed *baseObject = thisObject.asManaged();
+ Managed *baseObject = callData->thisObject.asManaged();
if (!baseObject) {
- if (thisObject.isNull() || thisObject.isUndefined()) {
- QString message = QStringLiteral("Cannot call method '%1' of %2").arg(name->toQString()).arg(thisObject.toQString());
+ if (callData->thisObject.isNullOrUndefined()) {
+ QString message = QStringLiteral("Cannot call method '%1' of %2").arg(name->toQString()).arg(callData->thisObject.toQString());
context->throwTypeError(message);
}
- baseObject = __qmljs_convert_to_object(context, thisObject);
- thisObject = Value::fromObject(static_cast<Object *>(baseObject));
+ baseObject = __qmljs_convert_to_object(context, ValueRef(&callData->thisObject));
+ callData->thisObject = Value::fromObject(static_cast<Object *>(baseObject));
}
- Value func = baseObject->get(name);
- FunctionObject *o = func.asFunctionObject();
+ FunctionObject *o = baseObject->get(name).asFunctionObject();
if (!o) {
- QString error = QString("Property '%1' of object %2 is not a function").arg(name->toQString(), thisObject.toQString());
+ QString error = QString("Property '%1' of object %2 is not a function").arg(name->toQString(), callData->thisObject.toQString());
context->throwTypeError(error);
}
- CallData d;
- d.thisObject = thisObject;
- d.args = args;
- d.argc = argc;
- Value res = o->call(d);
+ Value res = o->call(callData);
if (result)
*result = res;
}
-void __qmljs_call_property_lookup(ExecutionContext *context, Value *result, const Value &thisObject, uint index, Value *args, int argc)
+void __qmljs_call_property_lookup(ExecutionContext *context, ValueRef result, uint index, CallDataRef callData)
{
Value func;
Lookup *l = context->lookups + index;
- l->getter(l, &func, thisObject);
+ l->getter(l, &func, callData->thisObject);
Object *o = func.asObject();
if (!o)
context->throwTypeError();
- CallData d;
- d.thisObject = thisObject;
- d.args = args;
- d.argc = argc;
- Value res = o->call(d);
+ Value res = o->call(callData);
if (result)
*result = res;
}
-void __qmljs_call_element(ExecutionContext *context, Value *result, const Value &that, const Value &index, Value *args, int argc)
+void __qmljs_call_element(ExecutionContext *context, ValueRef result, const ValueRef index, CallDataRef callData)
{
- Object *baseObject = that.toObject(context);
- Value thisObject = Value::fromObject(baseObject);
+ Object *baseObject = callData->thisObject.toObject(context);
+ callData->thisObject = Value::fromObject(baseObject);
- Value func = baseObject->get(index.toString(context));
- Object *o = func.asObject();
+ Object *o = baseObject->get(index->toString(context)).asObject();
if (!o)
context->throwTypeError();
- CallData d;
- d.thisObject = thisObject;
- d.args = args;
- d.argc = argc;
- Value res = o->call(d);
+ Value res = o->call(callData);
if (result)
*result = res;
}
-void __qmljs_call_value(ExecutionContext *context, Value *result, const Value *thisObject, const Value &func, Value *args, int argc)
+void __qmljs_call_value(ExecutionContext *context, ValueRef result, const ValueRef func, CallDataRef callData)
{
- Object *o = func.asObject();
+ Object *o = func->asObject();
if (!o)
context->throwTypeError();
- CallData d;
- d.thisObject = thisObject ? *thisObject : Value::undefinedValue();
- d.args = args;
- d.argc = argc;
- Value res = o->call(d);
+
+ Value res = o->call(callData);
if (result)
*result = res;
}
-void __qmljs_construct_global_lookup(ExecutionContext *context, Value *result, uint index, Value *args, int argc)
+void __qmljs_construct_global_lookup(ExecutionContext *context, ValueRef result, uint index, CallDataRef callData)
{
+ Q_ASSERT(callData->thisObject.isUndefined());
+
Value func;
Lookup *l = context->lookups + index;
@@ -871,65 +864,60 @@ void __qmljs_construct_global_lookup(ExecutionContext *context, Value *result, u
if (!f)
context->throwTypeError();
- CallData d;
- d.args = args;
- d.argc = argc;
- Value res = f->construct(d);
+ Value res = f->construct(callData);
if (result)
*result = res;
}
-void __qmljs_construct_activation_property(ExecutionContext *context, Value *result, String *name, Value *args, int argc)
+void __qmljs_construct_activation_property(ExecutionContext *context, ValueRef result, String *name, CallDataRef callData)
{
Value func = context->getProperty(name);
- __qmljs_construct_value(context, result, func, args, argc);
+ Object *f = func.asObject();
+ if (!f)
+ context->throwTypeError();
+
+ Value res = f->construct(callData);
+ if (result)
+ *result = res;
}
-void __qmljs_construct_value(ExecutionContext *context, Value *result, const Value &func, Value *args, int argc)
+void __qmljs_construct_value(ExecutionContext *context, ValueRef result, const ValueRef func, CallDataRef callData)
{
- if (Object *f = func.asObject()) {
- CallData d;
- d.args = args;
- d.argc = argc;
- Value res = f->construct(d);
- if (result)
- *result = res;
- return;
- }
+ Object *f = func->asObject();
+ if (!f)
+ context->throwTypeError();
- context->throwTypeError();
+ Value res = f->construct(callData);
+ if (result)
+ *result = res;
}
-void __qmljs_construct_property(ExecutionContext *context, Value *result, const Value &base, String *name, Value *args, int argc)
+void __qmljs_construct_property(ExecutionContext *context, ValueRef result, const ValueRef base, String *name, CallDataRef callData)
{
- Object *thisObject = base.toObject(context);
+ Object *thisObject = base->toObject(context);
Value func = thisObject->get(name);
- if (Object *f = func.asObject()) {
- CallData d;
- d.args = args;
- d.argc = argc;
- Value res = f->construct(d);
- if (result)
- *result = res;
- return;
- }
+ Object *f = func.asObject();
+ if (!f)
+ context->throwTypeError();
- context->throwTypeError();
+ Value res = f->construct(callData);
+ if (result)
+ *result = res;
}
-void __qmljs_throw(ExecutionContext *context, const Value &value)
+void __qmljs_throw(ExecutionContext *context, const ValueRef value)
{
- Exception::throwException(context, value);
+ Exception::throwException(context, *value);
}
-void __qmljs_builtin_typeof(ExecutionContext *ctx, Value *result, const Value &value)
+void __qmljs_builtin_typeof(ExecutionContext *ctx, ValueRef result, const ValueRef value)
{
if (!result)
return;
String *res = 0;
- switch (value.type()) {
+ switch (value->type()) {
case Value::Undefined_Type:
res = ctx->engine->id_undefined;
break;
@@ -943,7 +931,7 @@ void __qmljs_builtin_typeof(ExecutionContext *ctx, Value *result, const Value &v
res = ctx->engine->id_string;
break;
case Value::Object_Type:
- if (value.objectValue()->asFunctionObject())
+ if (value->objectValue()->asFunctionObject())
res = ctx->engine->id_function;
else
res = ctx->engine->id_object; // ### implementation-defined
@@ -955,36 +943,41 @@ void __qmljs_builtin_typeof(ExecutionContext *ctx, Value *result, const Value &v
*result = Value::fromString(res);
}
-void __qmljs_builtin_typeof_name(ExecutionContext *context, Value *result, String *name)
+void __qmljs_builtin_typeof_name(ExecutionContext *context, ValueRef result, String *name)
{
- Value res;
- __qmljs_builtin_typeof(context, &res, context->getPropertyNoThrow(name));
+ ValueScope scope(context);
+ ScopedValue res(scope);
+ ScopedValue prop(scope, context->getPropertyNoThrow(name));
+ __qmljs_builtin_typeof(context, res, prop);
if (result)
*result = res;
}
-void __qmljs_builtin_typeof_member(ExecutionContext *context, Value *result, const Value &base,
+void __qmljs_builtin_typeof_member(ExecutionContext *context, ValueRef result, const ValueRef base,
String *name)
{
- Object *obj = base.toObject(context);
- Value res;
- __qmljs_builtin_typeof(context, &res, obj->get(name));
+ ValueScope scope(context);
+ Object *obj = base->toObject(context);
+ ScopedValue res(scope);
+ ScopedValue prop(scope, obj->get(name));
+ __qmljs_builtin_typeof(context, res, prop);
if (result)
*result = res;
}
-void __qmljs_builtin_typeof_element(ExecutionContext *context, Value *result, const Value &base,
- const Value &index)
+void __qmljs_builtin_typeof_element(ExecutionContext *context, ValueRef result, const ValueRef base, const ValueRef index)
{
- String *name = index.toString(context);
- Object *obj = base.toObject(context);
- Value res;
- __qmljs_builtin_typeof(context, &res, obj->get(name));
+ ValueScope scope(context);
+ String *name = index->toString(context);
+ Object *obj = base->toObject(context);
+ ScopedValue res(scope);
+ ScopedValue prop(scope, obj->get(name));
+ __qmljs_builtin_typeof(context, res, prop);
if (result)
*result = res;
}
-void __qmljs_builtin_post_increment(Value *result, Value *val)
+void __qmljs_builtin_post_increment(ValueRef result, ValueRef val)
{
if (val->isInteger() && val->integerValue() < INT_MAX) {
if (result)
@@ -993,13 +986,13 @@ void __qmljs_builtin_post_increment(Value *result, Value *val)
return;
}
- double d = __qmljs_to_number(*val);
+ double d = val->toNumber();
*val = Value::fromDouble(d + 1);
if (result)
*result = Value::fromDouble(d);
}
-void __qmljs_builtin_post_increment_name(ExecutionContext *context, Value *result, String *name)
+void __qmljs_builtin_post_increment_name(ExecutionContext *context, ValueRef result, String *name)
{
Value v = context->getProperty(name);
@@ -1008,7 +1001,7 @@ void __qmljs_builtin_post_increment_name(ExecutionContext *context, Value *resul
*result = v;
v.int_32 += 1;
} else {
- double d = __qmljs_to_number(v);
+ double d = v.toNumber();
if (result)
*result = Value::fromDouble(d);
v = Value::fromDouble(d + 1);
@@ -1017,9 +1010,9 @@ void __qmljs_builtin_post_increment_name(ExecutionContext *context, Value *resul
context->setProperty(name, v);
}
-void __qmljs_builtin_post_increment_member(ExecutionContext *context, Value *result, const Value &base, String *name)
+void __qmljs_builtin_post_increment_member(ExecutionContext *context, ValueRef result, const ValueRef base, String *name)
{
- Object *o = base.toObject(context);
+ Object *o = base->toObject(context);
Value v = o->get(name);
@@ -1028,7 +1021,7 @@ void __qmljs_builtin_post_increment_member(ExecutionContext *context, Value *res
*result = v;
v.int_32 += 1;
} else {
- double d = __qmljs_to_number(v);
+ double d = v.toNumber();
if (result)
*result = Value::fromDouble(d);
v = Value::fromDouble(d + 1);
@@ -1037,9 +1030,9 @@ void __qmljs_builtin_post_increment_member(ExecutionContext *context, Value *res
o->put(name, v);
}
-void __qmljs_builtin_post_increment_element(ExecutionContext *context, Value *result, const Value &base, const Value *index)
+void __qmljs_builtin_post_increment_element(ExecutionContext *context, ValueRef result, const ValueRef base, const ValueRef index)
{
- Object *o = base.toObject(context);
+ Object *o = base->toObject(context);
uint idx = index->asArrayIndex();
@@ -1055,7 +1048,7 @@ void __qmljs_builtin_post_increment_element(ExecutionContext *context, Value *re
*result = v;
v.int_32 += 1;
} else {
- double d = __qmljs_to_number(v);
+ double d = v.toNumber();
if (result)
*result = Value::fromDouble(d);
v = Value::fromDouble(d + 1);
@@ -1064,7 +1057,7 @@ void __qmljs_builtin_post_increment_element(ExecutionContext *context, Value *re
o->putIndexed(idx, v);
}
-void __qmljs_builtin_post_decrement(Value *result, Value *val)
+void __qmljs_builtin_post_decrement(ValueRef result, ValueRef val)
{
if (val->isInteger() && val->integerValue() > INT_MIN) {
if (result)
@@ -1073,13 +1066,13 @@ void __qmljs_builtin_post_decrement(Value *result, Value *val)
return;
}
- double d = __qmljs_to_number(*val);
+ double d = val->toNumber();
*val = Value::fromDouble(d - 1);
if (result)
*result = Value::fromDouble(d);
}
-void __qmljs_builtin_post_decrement_name(ExecutionContext *context, Value *result, String *name)
+void __qmljs_builtin_post_decrement_name(ExecutionContext *context, ValueRef result, String *name)
{
Value v = context->getProperty(name);
@@ -1088,7 +1081,7 @@ void __qmljs_builtin_post_decrement_name(ExecutionContext *context, Value *resul
*result = v;
v.int_32 -= 1;
} else {
- double d = __qmljs_to_number(v);
+ double d = v.toNumber();
if (result)
*result = Value::fromDouble(d);
v = Value::fromDouble(d - 1);
@@ -1097,9 +1090,9 @@ void __qmljs_builtin_post_decrement_name(ExecutionContext *context, Value *resul
context->setProperty(name, v);
}
-void __qmljs_builtin_post_decrement_member(ExecutionContext *context, Value *result, const Value &base, String *name)
+void __qmljs_builtin_post_decrement_member(ExecutionContext *context, ValueRef result, const ValueRef base, String *name)
{
- Object *o = base.toObject(context);
+ Object *o = base->toObject(context);
Value v = o->get(name);
@@ -1108,7 +1101,7 @@ void __qmljs_builtin_post_decrement_member(ExecutionContext *context, Value *res
*result = v;
v.int_32 -= 1;
} else {
- double d = __qmljs_to_number(v);
+ double d = v.toNumber();
if (result)
*result = Value::fromDouble(d);
v = Value::fromDouble(d - 1);
@@ -1117,14 +1110,14 @@ void __qmljs_builtin_post_decrement_member(ExecutionContext *context, Value *res
o->put(name, v);
}
-void __qmljs_builtin_post_decrement_element(ExecutionContext *context, Value *result, const Value &base, const Value &index)
+void __qmljs_builtin_post_decrement_element(ExecutionContext *context, ValueRef result, const ValueRef base, const ValueRef index)
{
- Object *o = base.toObject(context);
+ Object *o = base->toObject(context);
- uint idx = index.asArrayIndex();
+ uint idx = index->asArrayIndex();
if (idx == UINT_MAX) {
- String *s = index.toString(context);
+ String *s = index->toString(context);
return __qmljs_builtin_post_decrement_member(context, result, base, s);
}
@@ -1135,7 +1128,7 @@ void __qmljs_builtin_post_decrement_element(ExecutionContext *context, Value *re
*result = v;
v.int_32 -= 1;
} else {
- double d = __qmljs_to_number(v);
+ double d = v.toNumber();
if (result)
*result = Value::fromDouble(d);
v = Value::fromDouble(d - 1);
@@ -1144,15 +1137,15 @@ void __qmljs_builtin_post_decrement_element(ExecutionContext *context, Value *re
o->putIndexed(idx, v);
}
-ExecutionContext *__qmljs_builtin_push_with_scope(const Value &o, ExecutionContext *ctx)
+ExecutionContext *__qmljs_builtin_push_with_scope(const ValueRef o, ExecutionContext *ctx)
{
- Object *obj = o.toObject(ctx);
+ Object *obj = o->toObject(ctx);
return ctx->newWithContext(obj);
}
-ExecutionContext *__qmljs_builtin_push_catch_scope(String *exceptionVarName, const Value &exceptionValue, ExecutionContext *ctx)
+ExecutionContext *__qmljs_builtin_push_catch_scope(String *exceptionVarName, const ValueRef exceptionValue, ExecutionContext *ctx)
{
- return ctx->newCatchContext(exceptionVarName, exceptionValue);
+ return ctx->newCatchContext(exceptionVarName, *exceptionValue);
}
ExecutionContext *__qmljs_builtin_pop_scope(ExecutionContext *ctx)
@@ -1165,9 +1158,9 @@ void __qmljs_builtin_declare_var(ExecutionContext *ctx, bool deletable, String *
ctx->createMutableBinding(name, deletable);
}
-void __qmljs_builtin_define_property(ExecutionContext *ctx, const Value &object, String *name, Value *val)
+void __qmljs_builtin_define_property(ExecutionContext *ctx, const ValueRef object, String *name, ValueRef val)
{
- Object *o = object.asObject();
+ Object *o = object->asObject();
assert(o);
uint idx = name->asArrayIndex();
@@ -1175,7 +1168,7 @@ void __qmljs_builtin_define_property(ExecutionContext *ctx, const Value &object,
pd->value = val ? *val : Value::undefinedValue();
}
-void __qmljs_builtin_define_array(ExecutionContext *ctx, Value *array, Value *values, uint length)
+void __qmljs_builtin_define_array(ExecutionContext *ctx, ValueRef array, Value *values, uint length)
{
ArrayObject *a = ctx->engine->newArrayObject();
@@ -1200,9 +1193,9 @@ void __qmljs_builtin_define_array(ExecutionContext *ctx, Value *array, Value *va
*array = Value::fromObject(a);
}
-void __qmljs_builtin_define_getter_setter(ExecutionContext *ctx, const Value &object, String *name, const Value *getter, const Value *setter)
+void __qmljs_builtin_define_getter_setter(ExecutionContext *ctx, const ValueRef object, String *name, const ValueRef getter, const ValueRef setter)
{
- Object *o = object.asObject();
+ Object *o = object->asObject();
assert(o);
uint idx = name->asArrayIndex();
@@ -1211,7 +1204,7 @@ void __qmljs_builtin_define_getter_setter(ExecutionContext *ctx, const Value &ob
pd->setSetter(setter ? setter->asFunctionObject() : 0);
}
-void __qmljs_builtin_define_object_literal(QV4::ExecutionContext *ctx, QV4::Value *result, const QV4::Value *args, int classId)
+void __qmljs_builtin_define_object_literal(QV4::ExecutionContext *ctx, ValueRef result, const QV4::Value *args, int classId)
{
QV4::InternalClass *klass = ctx->compilationUnit->runtimeClasses[classId];
Object *o = ctx->engine->newObject(klass);
@@ -1230,7 +1223,7 @@ void __qmljs_builtin_define_object_literal(QV4::ExecutionContext *ctx, QV4::Valu
*result = Value::fromObject(o);
}
-void __qmljs_builtin_setup_arguments_object(ExecutionContext *ctx, Value *result)
+void __qmljs_builtin_setup_arguments_object(ExecutionContext *ctx, ValueRef result)
{
assert(ctx->type >= ExecutionContext::Type_CallContext);
CallContext *c = static_cast<CallContext *>(ctx);
@@ -1238,38 +1231,38 @@ void __qmljs_builtin_setup_arguments_object(ExecutionContext *ctx, Value *result
*result = Value::fromObject(args);
}
-void __qmljs_increment(Value *result, const Value &value)
+void __qmljs_increment(QV4::ValueRef result, const QV4::ValueRef value)
{
TRACE1(value);
- if (value.isInteger())
- *result = Value::fromInt32(value.integerValue() + 1);
+ if (value->isInteger())
+ *result = Value::fromInt32(value->integerValue() + 1);
else {
- double d = __qmljs_to_number(value);
+ double d = value->toNumber();
*result = Value::fromDouble(d + 1);
}
}
-void __qmljs_decrement(Value *result, const Value &value)
+void __qmljs_decrement(QV4::ValueRef result, const QV4::ValueRef value)
{
TRACE1(value);
- if (value.isInteger())
- *result = Value::fromInt32(value.integerValue() - 1);
+ if (value->isInteger())
+ *result = Value::fromInt32(value->integerValue() - 1);
else {
- double d = __qmljs_to_number(value);
+ double d = value->toNumber();
*result = Value::fromDouble(d - 1);
}
}
-void __qmljs_value_to_double(double *result, const Value &value)
+void __qmljs_value_to_double(double *result, const ValueRef value)
{
- *result = __qmljs_to_number(value);
+ *result = value->toNumber();
}
-int __qmljs_value_to_int32(const Value &value)
+int __qmljs_value_to_int32(const ValueRef value)
{
- return value.toInt32();
+ return value->toInt32();
}
int __qmljs_double_to_int32(const double &d)
@@ -1277,9 +1270,9 @@ int __qmljs_double_to_int32(const double &d)
return Value::toInt32(d);
}
-unsigned __qmljs_value_to_uint32(const Value &value)
+unsigned __qmljs_value_to_uint32(const ValueRef value)
{
- return value.toUInt32();
+ return value->toUInt32();
}
unsigned __qmljs_double_to_uint32(const double &d)
@@ -1287,12 +1280,12 @@ unsigned __qmljs_double_to_uint32(const double &d)
return Value::toUInt32(d);
}
-void __qmljs_value_from_string(Value *result, String *string)
+void __qmljs_value_from_string(ValueRef result, String *string)
{
*result = Value::fromString(string);
}
-void __qmljs_lookup_runtime_regexp(ExecutionContext *ctx, Value *result, int id)
+void __qmljs_lookup_runtime_regexp(ExecutionContext *ctx, ValueRef result, int id)
{
*result = ctx->compilationUnit->runtimeRegularExpressions[id];
}
diff --git a/src/qml/jsruntime/qv4runtime_p.h b/src/qml/jsruntime/qv4runtime_p.h
index b38f833ad0..d1ca86fddd 100644
--- a/src/qml/jsruntime/qv4runtime_p.h
+++ b/src/qml/jsruntime/qv4runtime_p.h
@@ -44,7 +44,7 @@
#include "qv4global_p.h"
#include "qv4value_p.h"
#include "qv4math_p.h"
-
+#include "qv4scopedvalue_p.h"
#include <QtCore/QString>
#include <QtCore/qnumeric.h>
@@ -91,47 +91,47 @@ struct ExecutionEngine;
struct InternalClass;
// context
-void __qmljs_call_activation_property(QV4::ExecutionContext *, QV4::Value *result, QV4::String *name, QV4::Value *args, int argc);
-void __qmljs_call_property(QV4::ExecutionContext *context, QV4::Value *result, const QV4::Value &that, QV4::String *name, QV4::Value *args, int argc);
-void __qmljs_call_property_lookup(QV4::ExecutionContext *context, QV4::Value *result, const QV4::Value &thisObject, uint index, QV4::Value *args, int argc);
-void __qmljs_call_element(QV4::ExecutionContext *context, QV4::Value *result, const QV4::Value &that, const QV4::Value &index, QV4::Value *args, int argc);
-void __qmljs_call_value(QV4::ExecutionContext *context, QV4::Value *result, const QV4::Value *thisObject, const QV4::Value &func, QV4::Value *args, int argc);
-
-void __qmljs_construct_activation_property(QV4::ExecutionContext *, QV4::Value *result, QV4::String *name, QV4::Value *args, int argc);
-void __qmljs_construct_property(QV4::ExecutionContext *context, QV4::Value *result, const QV4::Value &base, QV4::String *name, QV4::Value *args, int argc);
-void __qmljs_construct_value(QV4::ExecutionContext *context, QV4::Value *result, const QV4::Value &func, QV4::Value *args, int argc);
-
-void __qmljs_builtin_typeof(QV4::ExecutionContext *ctx, QV4::Value *result, const QV4::Value &val);
-void __qmljs_builtin_typeof_name(QV4::ExecutionContext *context, QV4::Value* result, QV4::String *name);
-void __qmljs_builtin_typeof_member(QV4::ExecutionContext* context, QV4::Value* result, const QV4::Value &base, QV4::String *name);
-void __qmljs_builtin_typeof_element(QV4::ExecutionContext* context, QV4::Value *result, const QV4::Value &base, const QV4::Value &index);
-
-void __qmljs_builtin_post_increment(QV4::Value *result, QV4::Value *val);
-void __qmljs_builtin_post_increment_name(QV4::ExecutionContext *context, QV4::Value *result, QV4::String *name);
-void __qmljs_builtin_post_increment_member(QV4::ExecutionContext *context, QV4::Value *result, const QV4::Value &base, QV4::String *name);
-void __qmljs_builtin_post_increment_element(QV4::ExecutionContext *context, QV4::Value *result, const QV4::Value &base, const QV4::Value *index);
-
-void __qmljs_builtin_post_decrement(QV4::Value *result, QV4::Value *val);
-void __qmljs_builtin_post_decrement_name(QV4::ExecutionContext *context, QV4::Value *result, QV4::String *name);
-void __qmljs_builtin_post_decrement_member(QV4::ExecutionContext *context, QV4::Value *result, const QV4::Value &base, QV4::String *name);
-void __qmljs_builtin_post_decrement_element(QV4::ExecutionContext *context, QV4::Value *result, const QV4::Value &base, const QV4::Value &index);
+void __qmljs_call_activation_property(QV4::ExecutionContext *, QV4::ValueRef result, QV4::String *name, CallDataRef callData);
+void __qmljs_call_property(QV4::ExecutionContext *context, QV4::ValueRef result, QV4::String *name, CallDataRef callData);
+void __qmljs_call_property_lookup(ExecutionContext *context, ValueRef result, uint index, CallDataRef callData);
+void __qmljs_call_element(ExecutionContext *context, ValueRef result, const ValueRef index, CallDataRef callData);
+void __qmljs_call_value(QV4::ExecutionContext *context, QV4::ValueRef result, const QV4::ValueRef func, CallDataRef callData);
+
+void __qmljs_construct_activation_property(QV4::ExecutionContext *, QV4::ValueRef result, QV4::String *name, CallDataRef callData);
+void __qmljs_construct_property(QV4::ExecutionContext *context, QV4::ValueRef result, const QV4::ValueRef base, QV4::String *name, CallDataRef callData);
+void __qmljs_construct_value(QV4::ExecutionContext *context, QV4::ValueRef result, const QV4::ValueRef func, CallDataRef callData);
+
+void __qmljs_builtin_typeof(QV4::ExecutionContext *ctx, QV4::ValueRef result, const QV4::ValueRef val);
+void __qmljs_builtin_typeof_name(QV4::ExecutionContext *context, QV4::ValueRef result, QV4::String *name);
+void __qmljs_builtin_typeof_member(QV4::ExecutionContext* context, QV4::ValueRef result, const QV4::ValueRef base, QV4::String *name);
+void __qmljs_builtin_typeof_element(QV4::ExecutionContext* context, QV4::ValueRef result, const QV4::ValueRef base, const QV4::ValueRef index);
+
+void __qmljs_builtin_post_increment(QV4::ValueRef result, QV4::ValueRef val);
+void __qmljs_builtin_post_increment_name(QV4::ExecutionContext *context, QV4::ValueRef result, QV4::String *name);
+void __qmljs_builtin_post_increment_member(QV4::ExecutionContext *context, QV4::ValueRef result, const QV4::ValueRef base, QV4::String *name);
+void __qmljs_builtin_post_increment_element(QV4::ExecutionContext *context, QV4::ValueRef result, const QV4::ValueRef base, const QV4::ValueRef index);
+
+void __qmljs_builtin_post_decrement(QV4::ValueRef result, QV4::ValueRef val);
+void __qmljs_builtin_post_decrement_name(QV4::ExecutionContext *context, QV4::ValueRef result, QV4::String *name);
+void __qmljs_builtin_post_decrement_member(QV4::ExecutionContext *context, QV4::ValueRef result, const QV4::ValueRef base, QV4::String *name);
+void __qmljs_builtin_post_decrement_element(QV4::ExecutionContext *context, QV4::ValueRef result, const QV4::ValueRef base, const QV4::ValueRef index);
void Q_NORETURN __qmljs_builtin_rethrow(QV4::ExecutionContext *context);
-QV4::ExecutionContext *__qmljs_builtin_push_with_scope(const QV4::Value &o, QV4::ExecutionContext *ctx);
-QV4::ExecutionContext *__qmljs_builtin_push_catch_scope(QV4::String *exceptionVarName, const QV4::Value &exceptionValue, QV4::ExecutionContext *ctx);
+QV4::ExecutionContext *__qmljs_builtin_push_with_scope(const QV4::ValueRef o, QV4::ExecutionContext *ctx);
+QV4::ExecutionContext *__qmljs_builtin_push_catch_scope(QV4::String *exceptionVarName, const QV4::ValueRef exceptionValue, QV4::ExecutionContext *ctx);
QV4::ExecutionContext *__qmljs_builtin_pop_scope(QV4::ExecutionContext *ctx);
void __qmljs_builtin_declare_var(QV4::ExecutionContext *ctx, bool deletable, QV4::String *name);
-void __qmljs_builtin_define_property(QV4::ExecutionContext *ctx, const QV4::Value &object, QV4::String *name, QV4::Value *val);
-void __qmljs_builtin_define_array(QV4::ExecutionContext *ctx, QV4::Value *array, QV4::Value *values, uint length);
-void __qmljs_builtin_define_getter_setter(QV4::ExecutionContext *ctx, const QV4::Value &object, QV4::String *name, const QV4::Value *getter, const QV4::Value *setter);
-void __qmljs_builtin_define_object_literal(QV4::ExecutionContext *ctx, QV4::Value *result, const QV4::Value *args, int classId);
-void __qmljs_builtin_setup_arguments_object(ExecutionContext *ctx, QV4::Value *result);
+void __qmljs_builtin_define_property(QV4::ExecutionContext *ctx, const QV4::ValueRef object, QV4::String *name, QV4::ValueRef val);
+void __qmljs_builtin_define_array(QV4::ExecutionContext *ctx, QV4::ValueRef array, QV4::Value *values, uint length);
+void __qmljs_builtin_define_getter_setter(QV4::ExecutionContext *ctx, const QV4::ValueRef object, QV4::String *name, const QV4::ValueRef getter, const QV4::ValueRef setter);
+void __qmljs_builtin_define_object_literal(QV4::ExecutionContext *ctx, QV4::ValueRef result, const QV4::Value *args, int classId);
+void __qmljs_builtin_setup_arguments_object(ExecutionContext *ctx, QV4::ValueRef result);
-void __qmljs_value_from_string(QV4::Value *result, QV4::String *string);
-void __qmljs_lookup_runtime_regexp(QV4::ExecutionContext *ctx, QV4::Value *result, int id);
+void __qmljs_value_from_string(QV4::ValueRef result, QV4::String *string);
+void __qmljs_lookup_runtime_regexp(QV4::ExecutionContext *ctx, QV4::ValueRef result, int id);
// constructors
-void __qmljs_init_closure(QV4::ExecutionContext *ctx, QV4::Value *result, int functionId);
+void __qmljs_init_closure(QV4::ExecutionContext *ctx, QV4::ValueRef result, int functionId);
// strings
Q_QML_EXPORT double __qmljs_string_to_number(const QString &s);
@@ -140,192 +140,172 @@ QV4::String *__qmljs_string_concat(QV4::ExecutionContext *ctx, QV4::String *firs
// objects
Q_QML_EXPORT QV4::Value __qmljs_object_default_value(QV4::Object *object, int typeHint);
-void __qmljs_set_activation_property(QV4::ExecutionContext *ctx, QV4::String *name, const QV4::Value& value);
-void __qmljs_set_property(QV4::ExecutionContext *ctx, const QV4::Value &object, QV4::String *name, const QV4::Value &value);
-void __qmljs_get_property(QV4::ExecutionContext *ctx, QV4::Value *result, const QV4::Value &object, QV4::String *name);
-void __qmljs_get_activation_property(QV4::ExecutionContext *ctx, QV4::Value *result, QV4::String *name);
+void __qmljs_set_activation_property(QV4::ExecutionContext *ctx, QV4::String *name, const QV4::ValueRef value);
+void __qmljs_set_property(QV4::ExecutionContext *ctx, const QV4::ValueRef object, QV4::String *name, const QV4::ValueRef value);
+void __qmljs_get_property(QV4::ExecutionContext *ctx, QV4::ValueRef result, const QV4::ValueRef object, QV4::String *name);
+void __qmljs_get_activation_property(QV4::ExecutionContext *ctx, QV4::ValueRef result, QV4::String *name);
-void __qmljs_call_global_lookup(QV4::ExecutionContext *context, QV4::Value *result, uint index, QV4::Value *args, int argc);
-void __qmljs_construct_global_lookup(QV4::ExecutionContext *context, QV4::Value *result, uint index, QV4::Value *args, int argc);
+void __qmljs_call_global_lookup(QV4::ExecutionContext *context, QV4::ValueRef result, uint index, CallDataRef callData);
+void __qmljs_construct_global_lookup(QV4::ExecutionContext *context, QV4::ValueRef result, uint index, CallDataRef callData);
-void __qmljs_get_element(QV4::ExecutionContext *ctx, QV4::Value *retval, const QV4::Value &object, const QV4::Value &index);
-void __qmljs_set_element(QV4::ExecutionContext *ctx, const QV4::Value &object, const QV4::Value &index, const QV4::Value &value);
+void __qmljs_get_element(QV4::ExecutionContext *ctx, QV4::ValueRef retval, const QV4::ValueRef object, const QV4::ValueRef index);
+void __qmljs_set_element(QV4::ExecutionContext *ctx, const QV4::ValueRef object, const QV4::ValueRef index, const QV4::ValueRef value);
// For each
-void __qmljs_foreach_iterator_object(QV4::ExecutionContext *ctx, QV4::Value *result, const QV4::Value &in);
-void __qmljs_foreach_next_property_name(QV4::Value *result, const QV4::Value &foreach_iterator);
+void __qmljs_foreach_iterator_object(QV4::ExecutionContext *ctx, QV4::ValueRef result, const QV4::ValueRef in);
+void __qmljs_foreach_next_property_name(QV4::ValueRef result, const ValueRef foreach_iterator);
// type conversion and testing
-QV4::Value __qmljs_to_primitive(const QV4::Value &value, int typeHint);
-Q_QML_EXPORT QV4::Bool __qmljs_to_boolean(const QV4::Value &value);
-double __qmljs_to_number(const QV4::Value &value);
-QV4::Value __qmljs_to_string(const QV4::Value &value, QV4::ExecutionContext *ctx);
-Q_QML_EXPORT QV4::String *__qmljs_convert_to_string(QV4::ExecutionContext *ctx, const QV4::Value &value);
+QV4::Value __qmljs_to_primitive(const ValueRef value, int typeHint);
+Q_QML_EXPORT QV4::Bool __qmljs_to_boolean(const QV4::ValueRef value);
+double __qmljs_to_number(const QV4::ValueRef value);
+QV4::Value __qmljs_to_string(const ValueRef value, QV4::ExecutionContext *ctx);
+Q_QML_EXPORT QV4::String *__qmljs_convert_to_string(QV4::ExecutionContext *ctx, const ValueRef value);
void __qmljs_numberToString(QString *result, double num, int radix = 10);
-QV4::Value __qmljs_to_object(QV4::ExecutionContext *ctx, const QV4::Value &value);
-QV4::Object *__qmljs_convert_to_object(QV4::ExecutionContext *ctx, const QV4::Value &value);
+QV4::Value __qmljs_to_object(QV4::ExecutionContext *ctx, const ValueRef value);
+QV4::Object *__qmljs_convert_to_object(QV4::ExecutionContext *ctx, const ValueRef value);
-QV4::Bool __qmljs_equal_helper(const Value &x, const Value &y);
-Q_QML_EXPORT QV4::Bool __qmljs_strict_equal(const QV4::Value &x, const QV4::Value &y);
+QV4::Bool __qmljs_equal_helper(const ValueRef x, const ValueRef y);
+Q_QML_EXPORT QV4::Bool __qmljs_strict_equal(const ValueRef x, const ValueRef y);
// unary operators
-typedef void (*UnaryOpName)(QV4::Value *, const QV4::Value &);
-void __qmljs_uplus(QV4::Value *result, const QV4::Value &value);
-void __qmljs_uminus(QV4::Value *result, const QV4::Value &value);
-void __qmljs_compl(QV4::Value *result, const QV4::Value &value);
-void __qmljs_not(QV4::Value *result, const QV4::Value &value);
-void __qmljs_increment(QV4::Value *result, const QV4::Value &value);
-void __qmljs_decrement(QV4::Value *result, const QV4::Value &value);
-
-Q_QML_EXPORT void __qmljs_value_to_double(double *result, const Value &value);
-Q_QML_EXPORT int __qmljs_value_to_int32(const Value &value);
+typedef void (*UnaryOpName)(QV4::ValueRef, const QV4::ValueRef);
+void __qmljs_uplus(QV4::ValueRef result, const QV4::ValueRef value);
+void __qmljs_uminus(QV4::ValueRef result, const QV4::ValueRef value);
+void __qmljs_compl(QV4::ValueRef result, const QV4::ValueRef value);
+void __qmljs_not(QV4::ValueRef result, const QV4::ValueRef value);
+void __qmljs_increment(QV4::ValueRef result, const QV4::ValueRef value);
+void __qmljs_decrement(QV4::ValueRef result, const QV4::ValueRef value);
+
+Q_QML_EXPORT void __qmljs_value_to_double(double *result, const ValueRef value);
+Q_QML_EXPORT int __qmljs_value_to_int32(const ValueRef value);
Q_QML_EXPORT int __qmljs_double_to_int32(const double &d);
-Q_QML_EXPORT unsigned __qmljs_value_to_uint32(const Value &value);
+Q_QML_EXPORT unsigned __qmljs_value_to_uint32(const ValueRef value);
Q_QML_EXPORT unsigned __qmljs_double_to_uint32(const double &d);
-void __qmljs_delete_subscript(QV4::ExecutionContext *ctx, QV4::Value *result, const QV4::Value &base, const QV4::Value &index);
-void __qmljs_delete_member(QV4::ExecutionContext *ctx, QV4::Value *result, const QV4::Value &base, QV4::String *name);
-void __qmljs_delete_name(QV4::ExecutionContext *ctx, QV4::Value *result, QV4::String *name);
+void __qmljs_delete_subscript(QV4::ExecutionContext *ctx, QV4::ValueRef result, const QV4::ValueRef base, const QV4::ValueRef index);
+void __qmljs_delete_member(QV4::ExecutionContext *ctx, QV4::ValueRef result, const QV4::ValueRef base, QV4::String *name);
+void __qmljs_delete_name(QV4::ExecutionContext *ctx, QV4::ValueRef result, QV4::String *name);
-void Q_NORETURN __qmljs_throw(QV4::ExecutionContext*, const QV4::Value &value);
+void Q_NORETURN __qmljs_throw(QV4::ExecutionContext*, const QV4::ValueRef value);
// binary operators
-typedef void (*BinOp)(QV4::Value *result, const QV4::Value &left, const QV4::Value &right);
-typedef void (*BinOpContext)(QV4::ExecutionContext *ctx, QV4::Value *result, const QV4::Value &left, const QV4::Value &right);
-
-void __qmljs_instanceof(QV4::ExecutionContext *ctx, QV4::Value *result, const QV4::Value &left, const QV4::Value &right);
-void __qmljs_in(QV4::ExecutionContext *ctx, QV4::Value *result, const QV4::Value &left, const QV4::Value &right);
-void __qmljs_add(ExecutionContext *ctx, QV4::Value *result, const QV4::Value &left, const QV4::Value &right);
-void __qmljs_bit_or(QV4::Value *result, const QV4::Value &left, const QV4::Value &right);
-void __qmljs_bit_xor(QV4::Value *result, const QV4::Value &left, const QV4::Value &right);
-void __qmljs_bit_and(QV4::Value *result, const QV4::Value &left, const QV4::Value &right);
-void __qmljs_sub(QV4::Value *result, const QV4::Value &left, const QV4::Value &right);
-void __qmljs_mul(QV4::Value *result, const QV4::Value &left, const QV4::Value &right);
-void __qmljs_div(QV4::Value *result, const QV4::Value &left, const QV4::Value &right);
-void __qmljs_mod(QV4::Value *result, const QV4::Value &left, const QV4::Value &right);
-void __qmljs_shl(QV4::Value *result, const QV4::Value &left, const QV4::Value &right);
-void __qmljs_shr(QV4::Value *result, const QV4::Value &left, const QV4::Value &right);
-void __qmljs_ushr(QV4::Value *result, const QV4::Value &left, const QV4::Value &right);
-void __qmljs_gt(QV4::Value *result, const QV4::Value &left, const QV4::Value &right);
-void __qmljs_lt(QV4::Value *result, const QV4::Value &left, const QV4::Value &right);
-void __qmljs_ge(QV4::Value *result, const QV4::Value &left, const QV4::Value &right);
-void __qmljs_le(QV4::Value *result, const QV4::Value &left, const QV4::Value &right);
-void __qmljs_eq(QV4::Value *result, const QV4::Value &left, const QV4::Value &right);
-void __qmljs_ne(QV4::Value *result, const QV4::Value &left, const QV4::Value &right);
-void __qmljs_se(QV4::Value *result, const QV4::Value &left, const QV4::Value &right);
-void __qmljs_sne(QV4::Value *result, const QV4::Value &left, const QV4::Value &right);
-
-void __qmljs_add_helper(QV4::ExecutionContext *ctx, QV4::Value *result, const QV4::Value &left, const QV4::Value &right);
-
-
-typedef void (*InplaceBinOpName)(QV4::ExecutionContext *ctx, QV4::String *name, const QV4::Value &value);
-void __qmljs_inplace_bit_and_name(QV4::ExecutionContext *ctx, QV4::String *name, const QV4::Value &value);
-void __qmljs_inplace_bit_or_name(QV4::ExecutionContext *ctx, QV4::String *name, const QV4::Value &value);
-void __qmljs_inplace_bit_xor_name(QV4::ExecutionContext *ctx, QV4::String *name, const QV4::Value &value);
-void __qmljs_inplace_add_name(QV4::ExecutionContext *ctx, QV4::String *name, const QV4::Value &value);
-void __qmljs_inplace_sub_name(QV4::ExecutionContext *ctx, QV4::String *name, const QV4::Value &value);
-void __qmljs_inplace_mul_name(QV4::ExecutionContext *ctx, QV4::String *name, const QV4::Value &value);
-void __qmljs_inplace_div_name(QV4::ExecutionContext *ctx, QV4::String *name, const QV4::Value &value);
-void __qmljs_inplace_mod_name(QV4::ExecutionContext *ctx, QV4::String *name, const QV4::Value &value);
-void __qmljs_inplace_shl_name(QV4::ExecutionContext *ctx, QV4::String *name, const QV4::Value &value);
-void __qmljs_inplace_shr_name(QV4::ExecutionContext *ctx, QV4::String *name, const QV4::Value &value);
-void __qmljs_inplace_ushr_name(QV4::ExecutionContext *ctx, QV4::String *name, const QV4::Value &value);
-
-typedef void (*InplaceBinOpElement)(QV4::ExecutionContext *ctx, const QV4::Value &base, const QV4::Value &index, const QV4::Value &rhs);
-void __qmljs_inplace_bit_and_element(QV4::ExecutionContext *ctx, const QV4::Value &base, const QV4::Value &index, const QV4::Value &rhs);
-void __qmljs_inplace_bit_or_element(QV4::ExecutionContext *ctx, const QV4::Value &base, const QV4::Value &index, const QV4::Value &rhs);
-void __qmljs_inplace_bit_xor_element(QV4::ExecutionContext *ctx, const QV4::Value &base, const QV4::Value &index, const QV4::Value &rhs);
-void __qmljs_inplace_add_element(QV4::ExecutionContext *ctx, const QV4::Value &base, const QV4::Value &index, const QV4::Value &rhs);
-void __qmljs_inplace_sub_element(QV4::ExecutionContext *ctx, const QV4::Value &base, const QV4::Value &index, const QV4::Value &rhs);
-void __qmljs_inplace_mul_element(QV4::ExecutionContext *ctx, const QV4::Value &base, const QV4::Value &index, const QV4::Value &rhs);
-void __qmljs_inplace_div_element(QV4::ExecutionContext *ctx, const QV4::Value &base, const QV4::Value &index, const QV4::Value &rhs);
-void __qmljs_inplace_mod_element(QV4::ExecutionContext *ctx, const QV4::Value &base, const QV4::Value &index, const QV4::Value &rhs);
-void __qmljs_inplace_shl_element(QV4::ExecutionContext *ctx, const QV4::Value &base, const QV4::Value &index, const QV4::Value &rhs);
-void __qmljs_inplace_shr_element(QV4::ExecutionContext *ctx, const QV4::Value &base, const QV4::Value &index, const QV4::Value &rhs);
-void __qmljs_inplace_ushr_element(QV4::ExecutionContext *ctx, const QV4::Value &base, const QV4::Value &index, const QV4::Value &rhs);
-
-typedef void (*InplaceBinOpMember)(QV4::ExecutionContext *ctx, const QV4::Value &base, QV4::String *name, const QV4::Value &rhs);
-void __qmljs_inplace_bit_and_member(QV4::ExecutionContext *ctx, const QV4::Value &base, QV4::String *name, const QV4::Value &rhs);
-void __qmljs_inplace_bit_or_member(QV4::ExecutionContext *ctx, const QV4::Value &base, QV4::String *name, const QV4::Value &rhs);
-void __qmljs_inplace_bit_xor_member(QV4::ExecutionContext *ctx, const QV4::Value &base, QV4::String *name, const QV4::Value &rhs);
-void __qmljs_inplace_add_member(QV4::ExecutionContext *ctx, const QV4::Value &base, QV4::String *name, const QV4::Value &rhs);
-void __qmljs_inplace_sub_member(QV4::ExecutionContext *ctx, const QV4::Value &base, QV4::String *name, const QV4::Value &rhs);
-void __qmljs_inplace_mul_member(QV4::ExecutionContext *ctx, const QV4::Value &base, QV4::String *name, const QV4::Value &rhs);
-void __qmljs_inplace_div_member(QV4::ExecutionContext *ctx, const QV4::Value &base, QV4::String *name, const QV4::Value &rhs);
-void __qmljs_inplace_mod_member(QV4::ExecutionContext *ctx, const QV4::Value &base, QV4::String *name, const QV4::Value &rhs);
-void __qmljs_inplace_shl_member(QV4::ExecutionContext *ctx, const QV4::Value &base, QV4::String *name, const QV4::Value &rhs);
-void __qmljs_inplace_shr_member(QV4::ExecutionContext *ctx, const QV4::Value &base, QV4::String *name, const QV4::Value &rhs);
-void __qmljs_inplace_ushr_member(QV4::ExecutionContext *ctx, const QV4::Value &base, QV4::String *name, const QV4::Value &rhs);
-
-typedef QV4::Bool (*CmpOp)(const QV4::Value &left, const QV4::Value &right);
-QV4::Bool __qmljs_cmp_gt(const QV4::Value &left, const QV4::Value &right);
-QV4::Bool __qmljs_cmp_lt(const QV4::Value &left, const QV4::Value &right);
-QV4::Bool __qmljs_cmp_ge(const QV4::Value &left, const QV4::Value &right);
-QV4::Bool __qmljs_cmp_le(const QV4::Value &left, const QV4::Value &right);
-QV4::Bool __qmljs_cmp_eq(const QV4::Value &left, const QV4::Value &right);
-QV4::Bool __qmljs_cmp_ne(const QV4::Value &left, const QV4::Value &right);
-QV4::Bool __qmljs_cmp_se(const QV4::Value &left, const QV4::Value &right);
-QV4::Bool __qmljs_cmp_sne(const QV4::Value &left, const QV4::Value &right);
-
-typedef QV4::Bool (*CmpOpContext)(QV4::ExecutionContext *ctx, const QV4::Value &left, const QV4::Value &right);
-QV4::Bool __qmljs_cmp_instanceof(QV4::ExecutionContext *ctx, const QV4::Value &left, const QV4::Value &right);
-QV4::Bool __qmljs_cmp_in(QV4::ExecutionContext *ctx, const QV4::Value &left, const QV4::Value &right);
+typedef void (*BinOp)(QV4::ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right);
+typedef void (*BinOpContext)(QV4::ExecutionContext *ctx, QV4::ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right);
+
+void __qmljs_instanceof(QV4::ExecutionContext *ctx, QV4::ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right);
+void __qmljs_in(QV4::ExecutionContext *ctx, QV4::ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right);
+void __qmljs_add(ExecutionContext *ctx, QV4::ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right);
+void __qmljs_bit_or(QV4::ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right);
+void __qmljs_bit_xor(QV4::ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right);
+void __qmljs_bit_and(QV4::ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right);
+void __qmljs_sub(QV4::ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right);
+void __qmljs_mul(QV4::ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right);
+void __qmljs_div(QV4::ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right);
+void __qmljs_mod(QV4::ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right);
+void __qmljs_shl(QV4::ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right);
+void __qmljs_shr(QV4::ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right);
+void __qmljs_ushr(QV4::ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right);
+void __qmljs_gt(QV4::ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right);
+void __qmljs_lt(QV4::ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right);
+void __qmljs_ge(QV4::ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right);
+void __qmljs_le(QV4::ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right);
+void __qmljs_eq(QV4::ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right);
+void __qmljs_ne(QV4::ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right);
+void __qmljs_se(QV4::ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right);
+void __qmljs_sne(QV4::ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right);
+
+void __qmljs_add_helper(QV4::ExecutionContext *ctx, QV4::ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right);
+
+
+typedef void (*InplaceBinOpName)(QV4::ExecutionContext *ctx, QV4::String *name, const QV4::ValueRef value);
+void __qmljs_inplace_bit_and_name(QV4::ExecutionContext *ctx, QV4::String *name, const QV4::ValueRef value);
+void __qmljs_inplace_bit_or_name(QV4::ExecutionContext *ctx, QV4::String *name, const QV4::ValueRef value);
+void __qmljs_inplace_bit_xor_name(QV4::ExecutionContext *ctx, QV4::String *name, const QV4::ValueRef value);
+void __qmljs_inplace_add_name(QV4::ExecutionContext *ctx, QV4::String *name, const ValueRef value);
+void __qmljs_inplace_sub_name(QV4::ExecutionContext *ctx, QV4::String *name, const ValueRef value);
+void __qmljs_inplace_mul_name(QV4::ExecutionContext *ctx, QV4::String *name, const ValueRef value);
+void __qmljs_inplace_div_name(QV4::ExecutionContext *ctx, QV4::String *name, const ValueRef value);
+void __qmljs_inplace_mod_name(QV4::ExecutionContext *ctx, QV4::String *name, const ValueRef value);
+void __qmljs_inplace_shl_name(QV4::ExecutionContext *ctx, QV4::String *name, const ValueRef value);
+void __qmljs_inplace_shr_name(QV4::ExecutionContext *ctx, QV4::String *name, const ValueRef value);
+void __qmljs_inplace_ushr_name(QV4::ExecutionContext *ctx, QV4::String *name, const ValueRef value);
+
+typedef void (*InplaceBinOpElement)(QV4::ExecutionContext *ctx, const QV4::ValueRef base, const QV4::ValueRef index, const QV4::ValueRef rhs);
+void __qmljs_inplace_bit_and_element(QV4::ExecutionContext *ctx, const QV4::ValueRef base, const QV4::ValueRef index, const QV4::ValueRef rhs);
+void __qmljs_inplace_bit_or_element(QV4::ExecutionContext *ctx, const QV4::ValueRef base, const QV4::ValueRef index, const QV4::ValueRef rhs);
+void __qmljs_inplace_bit_xor_element(QV4::ExecutionContext *ctx, const QV4::ValueRef base, const QV4::ValueRef index, const QV4::ValueRef rhs);
+void __qmljs_inplace_add_element(QV4::ExecutionContext *ctx, const QV4::ValueRef base, const QV4::ValueRef index, const QV4::ValueRef rhs);
+void __qmljs_inplace_sub_element(QV4::ExecutionContext *ctx, const QV4::ValueRef base, const QV4::ValueRef index, const QV4::ValueRef rhs);
+void __qmljs_inplace_mul_element(QV4::ExecutionContext *ctx, const QV4::ValueRef base, const QV4::ValueRef index, const QV4::ValueRef rhs);
+void __qmljs_inplace_div_element(QV4::ExecutionContext *ctx, const QV4::ValueRef base, const QV4::ValueRef index, const QV4::ValueRef rhs);
+void __qmljs_inplace_mod_element(QV4::ExecutionContext *ctx, const QV4::ValueRef base, const QV4::ValueRef index, const QV4::ValueRef rhs);
+void __qmljs_inplace_shl_element(QV4::ExecutionContext *ctx, const QV4::ValueRef base, const QV4::ValueRef index, const QV4::ValueRef rhs);
+void __qmljs_inplace_shr_element(QV4::ExecutionContext *ctx, const QV4::ValueRef base, const QV4::ValueRef index, const QV4::ValueRef rhs);
+void __qmljs_inplace_ushr_element(QV4::ExecutionContext *ctx, const QV4::ValueRef base, const QV4::ValueRef index, const QV4::ValueRef rhs);
+
+typedef void (*InplaceBinOpMember)(QV4::ExecutionContext *ctx, const QV4::ValueRef base, QV4::String *name, const QV4::ValueRef rhs);
+void __qmljs_inplace_bit_and_member(QV4::ExecutionContext *ctx, const QV4::ValueRef base, QV4::String *name, const QV4::ValueRef rhs);
+void __qmljs_inplace_bit_or_member(QV4::ExecutionContext *ctx, const QV4::ValueRef base, QV4::String *name, const QV4::ValueRef rhs);
+void __qmljs_inplace_bit_xor_member(QV4::ExecutionContext *ctx, const QV4::ValueRef base, QV4::String *name, const QV4::ValueRef rhs);
+void __qmljs_inplace_add_member(QV4::ExecutionContext *ctx, const QV4::ValueRef base, QV4::String *name, const QV4::ValueRef rhs);
+void __qmljs_inplace_sub_member(QV4::ExecutionContext *ctx, const QV4::ValueRef base, QV4::String *name, const QV4::ValueRef rhs);
+void __qmljs_inplace_mul_member(QV4::ExecutionContext *ctx, const QV4::ValueRef base, QV4::String *name, const QV4::ValueRef rhs);
+void __qmljs_inplace_div_member(QV4::ExecutionContext *ctx, const QV4::ValueRef base, QV4::String *name, const QV4::ValueRef rhs);
+void __qmljs_inplace_mod_member(QV4::ExecutionContext *ctx, const QV4::ValueRef base, QV4::String *name, const QV4::ValueRef rhs);
+void __qmljs_inplace_shl_member(QV4::ExecutionContext *ctx, const QV4::ValueRef base, QV4::String *name, const QV4::ValueRef rhs);
+void __qmljs_inplace_shr_member(QV4::ExecutionContext *ctx, const QV4::ValueRef base, QV4::String *name, const QV4::ValueRef rhs);
+void __qmljs_inplace_ushr_member(QV4::ExecutionContext *ctx, const QV4::ValueRef base, QV4::String *name, const QV4::ValueRef rhs);
+
+typedef QV4::Bool (*CmpOp)(const QV4::ValueRef left, const QV4::ValueRef right);
+QV4::Bool __qmljs_cmp_gt(const QV4::ValueRef left, const QV4::ValueRef right);
+QV4::Bool __qmljs_cmp_lt(const QV4::ValueRef left, const QV4::ValueRef right);
+QV4::Bool __qmljs_cmp_ge(const QV4::ValueRef left, const QV4::ValueRef right);
+QV4::Bool __qmljs_cmp_le(const QV4::ValueRef left, const QV4::ValueRef right);
+QV4::Bool __qmljs_cmp_eq(const QV4::ValueRef left, const QV4::ValueRef right);
+QV4::Bool __qmljs_cmp_ne(const QV4::ValueRef left, const QV4::ValueRef right);
+QV4::Bool __qmljs_cmp_se(const QV4::ValueRef left, const QV4::ValueRef right);
+QV4::Bool __qmljs_cmp_sne(const QV4::ValueRef left, const QV4::ValueRef right);
+
+typedef QV4::Bool (*CmpOpContext)(QV4::ExecutionContext *ctx, const QV4::ValueRef left, const QV4::ValueRef right);
+QV4::Bool __qmljs_cmp_instanceof(QV4::ExecutionContext *ctx, const QV4::ValueRef left, const QV4::ValueRef right);
+QV4::Bool __qmljs_cmp_in(QV4::ExecutionContext *ctx, const QV4::ValueRef left, const QV4::ValueRef right);
// type conversion and testing
-inline QV4::Value __qmljs_to_primitive(const QV4::Value &value, int typeHint)
+inline QV4::Value __qmljs_to_primitive(const QV4::ValueRef value, int typeHint)
{
- QV4::Object *o = value.asObject();
+ QV4::Object *o = value->asObject();
if (!o)
- return value;
+ return *value;
return __qmljs_object_default_value(o, typeHint);
}
-inline double __qmljs_to_number(const QV4::Value &value)
-{
- switch (value.type()) {
- case QV4::Value::Undefined_Type:
- return std::numeric_limits<double>::quiet_NaN();
- case QV4::Value::Null_Type:
- return 0;
- case QV4::Value::Boolean_Type:
- return (value.booleanValue() ? 1. : 0.);
- case QV4::Value::Integer_Type:
- return value.int_32;
- case QV4::Value::String_Type:
- return __qmljs_string_to_number(value.stringValue()->toQString());
- case QV4::Value::Object_Type: {
- QV4::Value prim = __qmljs_to_primitive(value, QV4::NUMBER_HINT);
- return __qmljs_to_number(prim);
- }
- default: // double
- return value.doubleValue();
- }
+inline double __qmljs_to_number(const ValueRef value)
+{
+ return value->toNumber();
}
-Q_QML_EXPORT int __qmljs_value_to_int32(const QV4::Value &value);
-Q_QML_EXPORT unsigned __qmljs_value_to_uint32(const QV4::Value &value);
-
-inline QV4::Value __qmljs_to_string(const QV4::Value &value, QV4::ExecutionContext *ctx)
+inline QV4::Value __qmljs_to_string(const QV4::ValueRef value, QV4::ExecutionContext *ctx)
{
- if (value.isString())
- return value;
+ if (value->isString())
+ return *value;
return QV4::Value::fromString(__qmljs_convert_to_string(ctx, value));
}
-inline QV4::Value __qmljs_to_object(QV4::ExecutionContext *ctx, const QV4::Value &value)
+inline QV4::Value __qmljs_to_object(QV4::ExecutionContext *ctx, const QV4::ValueRef value)
{
- if (value.isObject())
- return value;
+ if (value->isObject())
+ return *value;
return QV4::Value::fromObject(__qmljs_convert_to_object(ctx, value));
}
-inline void __qmljs_uplus(QV4::Value *result, const QV4::Value &value)
+inline void __qmljs_uplus(QV4::ValueRef result, const QV4::ValueRef value)
{
TRACE1(value);
- *result = value;
+ result = value;
if (result->tryIntegerConversion())
return;
@@ -333,47 +313,47 @@ inline void __qmljs_uplus(QV4::Value *result, const QV4::Value &value)
*result = QV4::Value::fromDouble(n);
}
-inline void __qmljs_uminus(QV4::Value *result, const QV4::Value &value)
+inline void __qmljs_uminus(QV4::ValueRef result, const QV4::ValueRef value)
{
TRACE1(value);
// +0 != -0, so we need to convert to double when negating 0
- if (value.isInteger() && value.integerValue())
- *result = QV4::Value::fromInt32(-value.integerValue());
+ if (value->isInteger() && value->integerValue())
+ *result = QV4::Value::fromInt32(-value->integerValue());
else {
double n = __qmljs_to_number(value);
*result = QV4::Value::fromDouble(-n);
}
}
-inline void __qmljs_compl(QV4::Value *result, const QV4::Value &value)
+inline void __qmljs_compl(QV4::ValueRef result, const QV4::ValueRef value)
{
TRACE1(value);
int n;
- if (value.isConvertibleToInt())
- n = value.int_32;
+ if (value->isConvertibleToInt())
+ n = value->int_32;
else
n = QV4::Value::toInt32(__qmljs_to_number(value));
*result = QV4::Value::fromInt32(~n);
}
-inline void __qmljs_not(QV4::Value *result, const QV4::Value &value)
+inline void __qmljs_not(QV4::ValueRef result, const QV4::ValueRef value)
{
TRACE1(value);
- bool b = value.toBoolean();
+ bool b = value->toBoolean();
*result = QV4::Value::fromBoolean(!b);
}
// binary operators
-inline void __qmljs_bit_or(QV4::Value *result, const QV4::Value &left, const QV4::Value &right)
+inline void __qmljs_bit_or(ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right)
{
TRACE2(left, right);
- if (QV4::Value::integerCompatible(left, right)) {
- *result = QV4::Value::fromInt32(left.integerValue() | right.integerValue());
+ if (QV4::Value::integerCompatible(*left, *right)) {
+ *result = QV4::Value::fromInt32(left->integerValue() | right->integerValue());
return;
}
@@ -382,12 +362,12 @@ inline void __qmljs_bit_or(QV4::Value *result, const QV4::Value &left, const QV4
*result = QV4::Value::fromInt32(lval | rval);
}
-inline void __qmljs_bit_xor(QV4::Value *result, const QV4::Value &left, const QV4::Value &right)
+inline void __qmljs_bit_xor(QV4::ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right)
{
TRACE2(left, right);
- if (QV4::Value::integerCompatible(left, right)) {
- *result = QV4::Value::fromInt32(left.integerValue() ^ right.integerValue());
+ if (QV4::Value::integerCompatible(*left, *right)) {
+ *result = QV4::Value::fromInt32(left->integerValue() ^ right->integerValue());
return;
}
@@ -396,12 +376,12 @@ inline void __qmljs_bit_xor(QV4::Value *result, const QV4::Value &left, const QV
*result = QV4::Value::fromInt32(lval ^ rval);
}
-inline void __qmljs_bit_and(QV4::Value *result, const QV4::Value &left, const QV4::Value &right)
+inline void __qmljs_bit_and(ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right)
{
TRACE2(left, right);
- if (QV4::Value::integerCompatible(left, right)) {
- *result = QV4::Value::fromInt32(left.integerValue() & right.integerValue());
+ if (QV4::Value::integerCompatible(*left, *right)) {
+ *result = QV4::Value::fromInt32(left->integerValue() & right->integerValue());
return;
}
@@ -410,29 +390,29 @@ inline void __qmljs_bit_and(QV4::Value *result, const QV4::Value &left, const QV
*result = QV4::Value::fromInt32(lval & rval);
}
-inline void __qmljs_add(QV4::ExecutionContext *ctx, QV4::Value *result, const QV4::Value &left, const QV4::Value &right)
+inline void __qmljs_add(QV4::ExecutionContext *ctx, ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right)
{
TRACE2(left, right);
- if (QV4::Value::integerCompatible(left, right)) {
- *result = add_int32(left.integerValue(), right.integerValue());
+ if (QV4::Value::integerCompatible(*left, *right)) {
+ *result = add_int32(left->integerValue(), right->integerValue());
return;
}
- if (QV4::Value::bothDouble(left, right)) {
- *result = QV4::Value::fromDouble(left.doubleValue() + right.doubleValue());
+ if (QV4::Value::bothDouble(*left, *right)) {
+ *result = QV4::Value::fromDouble(left->doubleValue() + right->doubleValue());
return;
}
__qmljs_add_helper(ctx, result, left, right);
}
-inline void __qmljs_sub(QV4::Value *result, const QV4::Value &left, const QV4::Value &right)
+inline void __qmljs_sub(QV4::ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right)
{
TRACE2(left, right);
- if (QV4::Value::integerCompatible(left, right)) {
- *result = sub_int32(left.integerValue(), right.integerValue());
+ if (QV4::Value::integerCompatible(*left, *right)) {
+ *result = sub_int32(left->integerValue(), right->integerValue());
return;
}
@@ -441,12 +421,12 @@ inline void __qmljs_sub(QV4::Value *result, const QV4::Value &left, const QV4::V
*result = QV4::Value::fromDouble(lval - rval);
}
-inline void __qmljs_mul(QV4::Value *result, const QV4::Value &left, const QV4::Value &right)
+inline void __qmljs_mul(ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right)
{
TRACE2(left, right);
- if (QV4::Value::integerCompatible(left, right)) {
- *result = mul_int32(left.integerValue(), right.integerValue());
+ if (QV4::Value::integerCompatible(*left, *right)) {
+ *result = mul_int32(left->integerValue(), right->integerValue());
return;
}
@@ -455,7 +435,7 @@ inline void __qmljs_mul(QV4::Value *result, const QV4::Value &left, const QV4::V
*result = QV4::Value::fromDouble(lval * rval);
}
-inline void __qmljs_div(QV4::Value *result, const QV4::Value &left, const QV4::Value &right)
+inline void __qmljs_div(QV4::ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right)
{
TRACE2(left, right);
@@ -464,13 +444,13 @@ inline void __qmljs_div(QV4::Value *result, const QV4::Value &left, const QV4::V
*result = QV4::Value::fromDouble(lval / rval);
}
-inline void __qmljs_mod(QV4::Value *result, const QV4::Value &left, const QV4::Value &right)
+inline void __qmljs_mod(ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right)
{
TRACE2(left, right);
- if (QV4::Value::integerCompatible(left, right) && right.integerValue() != 0) {
- int intRes = left.integerValue() % right.integerValue();
- if (intRes != 0 || left.integerValue() >= 0) {
+ if (QV4::Value::integerCompatible(*left, *right) && right->integerValue() != 0) {
+ int intRes = left->integerValue() % right->integerValue();
+ if (intRes != 0 || left->integerValue() >= 0) {
*result = QV4::Value::fromInt32(intRes);
return;
}
@@ -481,12 +461,12 @@ inline void __qmljs_mod(QV4::Value *result, const QV4::Value &left, const QV4::V
*result = QV4::Value::fromDouble(std::fmod(lval, rval));
}
-inline void __qmljs_shl(QV4::Value *result, const QV4::Value &left, const QV4::Value &right)
+inline void __qmljs_shl(QV4::ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right)
{
TRACE2(left, right);
- if (QV4::Value::integerCompatible(left, right)) {
- *result = QV4::Value::fromInt32(left.integerValue() << ((uint(right.integerValue()) & 0x1f)));
+ if (QV4::Value::integerCompatible(*left, *right)) {
+ *result = QV4::Value::fromInt32(left->integerValue() << ((uint(right->integerValue()) & 0x1f)));
return;
}
@@ -495,12 +475,12 @@ inline void __qmljs_shl(QV4::Value *result, const QV4::Value &left, const QV4::V
*result = QV4::Value::fromInt32(lval << rval);
}
-inline void __qmljs_shr(QV4::Value *result, const QV4::Value &left, const QV4::Value &right)
+inline void __qmljs_shr(ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right)
{
TRACE2(left, right);
- if (QV4::Value::integerCompatible(left, right)) {
- *result = QV4::Value::fromInt32(left.integerValue() >> ((uint(right.integerValue()) & 0x1f)));
+ if (QV4::Value::integerCompatible(*left, *right)) {
+ *result = QV4::Value::fromInt32(left->integerValue() >> ((uint(right->integerValue()) & 0x1f)));
return;
}
@@ -509,13 +489,13 @@ inline void __qmljs_shr(QV4::Value *result, const QV4::Value &left, const QV4::V
*result = QV4::Value::fromInt32(lval >> rval);
}
-inline void __qmljs_ushr(QV4::Value *result, const QV4::Value &left, const QV4::Value &right)
+inline void __qmljs_ushr(QV4::ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right)
{
TRACE2(left, right);
uint res;
- if (QV4::Value::integerCompatible(left, right)) {
- res = uint(left.integerValue()) >> (uint(right.integerValue()) & 0x1f);
+ if (QV4::Value::integerCompatible(*left, *right)) {
+ res = uint(left->integerValue()) >> (uint(right->integerValue()) & 0x1f);
} else {
unsigned lval = QV4::Value::toUInt32(__qmljs_to_number(left));
unsigned rval = QV4::Value::toUInt32(__qmljs_to_number(right)) & 0x1f;
@@ -528,49 +508,49 @@ inline void __qmljs_ushr(QV4::Value *result, const QV4::Value &left, const QV4::
*result = QV4::Value::fromInt32(res);
}
-inline void __qmljs_gt(QV4::Value *result, const QV4::Value &left, const QV4::Value &right)
+inline void __qmljs_gt(ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right)
{
TRACE2(left, right);
*result = QV4::Value::fromBoolean(__qmljs_cmp_gt(left, right));
}
-inline void __qmljs_lt(QV4::Value *result, const QV4::Value &left, const QV4::Value &right)
+inline void __qmljs_lt(QV4::ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right)
{
TRACE2(left, right);
*result = QV4::Value::fromBoolean(__qmljs_cmp_lt(left, right));
}
-inline void __qmljs_ge(QV4::Value *result, const QV4::Value &left, const QV4::Value &right)
+inline void __qmljs_ge(ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right)
{
TRACE2(left, right);
*result = QV4::Value::fromBoolean(__qmljs_cmp_ge(left, right));
}
-inline void __qmljs_le(QV4::Value *result, const QV4::Value &left, const QV4::Value &right)
+inline void __qmljs_le(ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right)
{
TRACE2(left, right);
*result = QV4::Value::fromBoolean(__qmljs_cmp_le(left, right));
}
-inline void __qmljs_eq(QV4::Value *result, const QV4::Value &left, const QV4::Value &right)
+inline void __qmljs_eq(QV4::ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right)
{
TRACE2(left, right);
*result = QV4::Value::fromBoolean(__qmljs_cmp_eq(left, right));
}
-inline void __qmljs_ne(QV4::Value *result, const QV4::Value &left, const QV4::Value &right)
+inline void __qmljs_ne(ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right)
{
TRACE2(left, right);
*result = QV4::Value::fromBoolean(!__qmljs_cmp_eq(left, right));
}
-inline void __qmljs_se(QV4::Value *result, const QV4::Value &left, const QV4::Value &right)
+inline void __qmljs_se(QV4::ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right)
{
TRACE2(left, right);
@@ -578,7 +558,7 @@ inline void __qmljs_se(QV4::Value *result, const QV4::Value &left, const QV4::Va
*result = QV4::Value::fromBoolean(r);
}
-inline void __qmljs_sne(QV4::Value *result, const QV4::Value &left, const QV4::Value &right)
+inline void __qmljs_sne(ValueRef result, const QV4::ValueRef left, const QV4::ValueRef right)
{
TRACE2(left, right);
@@ -586,12 +566,13 @@ inline void __qmljs_sne(QV4::Value *result, const QV4::Value &left, const QV4::V
*result = QV4::Value::fromBoolean(r);
}
-inline QV4::Bool __qmljs_cmp_gt(const QV4::Value &left, const QV4::Value &right)
+inline QV4::Bool __qmljs_cmp_gt(const QV4::ValueRef left, const QV4::ValueRef right)
{
TRACE2(left, right);
- if (QV4::Value::integerCompatible(left, right))
- return left.integerValue() > right.integerValue();
+ if (QV4::Value::integerCompatible(*left, *right))
+ return left->integerValue() > right->integerValue();
+ // Safe, as l & r are primitive values
QV4::Value l = __qmljs_to_primitive(left, QV4::NUMBER_HINT);
QV4::Value r = __qmljs_to_primitive(right, QV4::NUMBER_HINT);
@@ -600,17 +581,17 @@ inline QV4::Bool __qmljs_cmp_gt(const QV4::Value &left, const QV4::Value &right)
} else if (l.isString() && r.isString()) {
return r.stringValue()->compare(l.stringValue());
} else {
- double dl = __qmljs_to_number(l);
- double dr = __qmljs_to_number(r);
+ double dl = __qmljs_to_number(ValueRef(&l));
+ double dr = __qmljs_to_number(ValueRef(&r));
return dl > dr;
}
}
-inline QV4::Bool __qmljs_cmp_lt(const QV4::Value &left, const QV4::Value &right)
+inline QV4::Bool __qmljs_cmp_lt(const QV4::ValueRef left, const QV4::ValueRef right)
{
TRACE2(left, right);
- if (QV4::Value::integerCompatible(left, right))
- return left.integerValue() < right.integerValue();
+ if (QV4::Value::integerCompatible(*left, *right))
+ return left->integerValue() < right->integerValue();
QV4::Value l = __qmljs_to_primitive(left, QV4::NUMBER_HINT);
QV4::Value r = __qmljs_to_primitive(right, QV4::NUMBER_HINT);
@@ -620,17 +601,17 @@ inline QV4::Bool __qmljs_cmp_lt(const QV4::Value &left, const QV4::Value &right)
} else if (l.isString() && r.isString()) {
return l.stringValue()->compare(r.stringValue());
} else {
- double dl = __qmljs_to_number(l);
- double dr = __qmljs_to_number(r);
+ double dl = __qmljs_to_number(ValueRef(&l));
+ double dr = __qmljs_to_number(ValueRef(&r));
return dl < dr;
}
}
-inline QV4::Bool __qmljs_cmp_ge(const QV4::Value &left, const QV4::Value &right)
+inline QV4::Bool __qmljs_cmp_ge(const QV4::ValueRef left, const QV4::ValueRef right)
{
TRACE2(left, right);
- if (QV4::Value::integerCompatible(left, right))
- return left.integerValue() >= right.integerValue();
+ if (QV4::Value::integerCompatible(*left, *right))
+ return left->integerValue() >= right->integerValue();
QV4::Value l = __qmljs_to_primitive(left, QV4::NUMBER_HINT);
QV4::Value r = __qmljs_to_primitive(right, QV4::NUMBER_HINT);
@@ -640,17 +621,17 @@ inline QV4::Bool __qmljs_cmp_ge(const QV4::Value &left, const QV4::Value &right)
} else if (l.isString() && r.isString()) {
return !l.stringValue()->compare(r.stringValue());
} else {
- double dl = __qmljs_to_number(l);
- double dr = __qmljs_to_number(r);
+ double dl = __qmljs_to_number(ValueRef(&l));
+ double dr = __qmljs_to_number(ValueRef(&r));
return dl >= dr;
}
}
-inline QV4::Bool __qmljs_cmp_le(const QV4::Value &left, const QV4::Value &right)
+inline QV4::Bool __qmljs_cmp_le(const QV4::ValueRef left, const QV4::ValueRef right)
{
TRACE2(left, right);
- if (QV4::Value::integerCompatible(left, right))
- return left.integerValue() <= right.integerValue();
+ if (QV4::Value::integerCompatible(*left, *right))
+ return left->integerValue() <= right->integerValue();
QV4::Value l = __qmljs_to_primitive(left, QV4::NUMBER_HINT);
QV4::Value r = __qmljs_to_primitive(right, QV4::NUMBER_HINT);
@@ -660,51 +641,51 @@ inline QV4::Bool __qmljs_cmp_le(const QV4::Value &left, const QV4::Value &right)
} else if (l.isString() && r.isString()) {
return !r.stringValue()->compare(l.stringValue());
} else {
- double dl = __qmljs_to_number(l);
- double dr = __qmljs_to_number(r);
+ double dl = __qmljs_to_number(ValueRef(&l));
+ double dr = __qmljs_to_number(ValueRef(&r));
return dl <= dr;
}
}
-inline QV4::Bool __qmljs_cmp_eq(const QV4::Value &left, const QV4::Value &right)
+inline QV4::Bool __qmljs_cmp_eq(const QV4::ValueRef left, const QV4::ValueRef right)
{
TRACE2(left, right);
- if (left.val == right.val)
+ if (left->val == right->val)
// NaN != NaN
- return (left.tag & QV4::Value::NotDouble_Mask) != QV4::Value::NaN_Mask;
+ return (left->tag & QV4::Value::NotDouble_Mask) != QV4::Value::NaN_Mask;
- if (left.type() == right.type()) {
- if (left.isManaged())
- return left.managed()->isEqualTo(right.managed());
+ if (left->type() == right->type()) {
+ if (left->isManaged())
+ return left->managed()->isEqualTo(right->managed());
return false;
}
return __qmljs_equal_helper(left, right);
}
-inline QV4::Bool __qmljs_cmp_ne(const QV4::Value &left, const QV4::Value &right)
+inline QV4::Bool __qmljs_cmp_ne(const QV4::ValueRef left, const QV4::ValueRef right)
{
TRACE2(left, right);
return !__qmljs_cmp_eq(left, right);
}
-inline QV4::Bool __qmljs_cmp_se(const QV4::Value &left, const QV4::Value &right)
+inline QV4::Bool __qmljs_cmp_se(const QV4::ValueRef left, const QV4::ValueRef right)
{
TRACE2(left, right);
return __qmljs_strict_equal(left, right);
}
-inline QV4::Bool __qmljs_cmp_sne(const QV4::Value &left, const QV4::Value &right)
+inline QV4::Bool __qmljs_cmp_sne(const QV4::ValueRef left, const QV4::ValueRef right)
{
TRACE2(left, right);
return ! __qmljs_strict_equal(left, right);
}
-inline QV4::Bool __qmljs_cmp_instanceof(QV4::ExecutionContext *ctx, const QV4::Value &left, const QV4::Value &right)
+inline QV4::Bool __qmljs_cmp_instanceof(QV4::ExecutionContext *ctx, const QV4::ValueRef left, const QV4::ValueRef right)
{
TRACE2(left, right);
@@ -713,7 +694,7 @@ inline QV4::Bool __qmljs_cmp_instanceof(QV4::ExecutionContext *ctx, const QV4::V
return v.booleanValue();
}
-inline uint __qmljs_cmp_in(QV4::ExecutionContext *ctx, const QV4::Value &left, const QV4::Value &right)
+inline uint __qmljs_cmp_in(QV4::ExecutionContext *ctx, const QV4::ValueRef left, const QV4::ValueRef right)
{
TRACE2(left, right);
diff --git a/src/qml/jsruntime/qv4scopedvalue_p.h b/src/qml/jsruntime/qv4scopedvalue_p.h
new file mode 100644
index 0000000000..a0e0d784a7
--- /dev/null
+++ b/src/qml/jsruntime/qv4scopedvalue_p.h
@@ -0,0 +1,287 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtQml 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 QV4SCOPEDVALUE_P_H
+#define QV4SCOPEDVALUE_P_H
+
+#include "qv4engine_p.h"
+#include "qv4value_def_p.h"
+
+QT_BEGIN_NAMESPACE
+
+#define SAVE_JS_STACK(ctx) Value *__jsStack = ctx->engine->jsStackTop
+#define CHECK_JS_STACK(ctx) Q_ASSERT(__jsStack == ctx->engine->jsStackTop)
+
+namespace QV4 {
+
+struct ScopedValueArray {
+ ScopedValueArray(ExecutionEngine *e, int size)
+ : engine(e)
+#ifndef QT_NO_DEBUG
+ , size(size)
+#endif
+ {
+ ptr = e->stackPush(size);
+ }
+
+ ~ScopedValueArray() {
+#ifndef QT_NO_DEBUG
+ engine->stackPop(size);
+ Q_ASSERT(engine->jsStackTop == ptr);
+#else
+ engine->jsStackTop = ptr;
+#endif
+ }
+
+ ExecutionEngine *engine;
+#ifndef QT_NO_DEBUG
+ int size;
+#endif
+ Value *ptr;
+};
+
+struct ScopedValue;
+
+struct ValueScope {
+ ValueScope(ExecutionContext *ctx)
+ : engine(ctx->engine)
+ {
+ mark = ctx->engine->jsStackTop;
+ }
+
+ ValueScope(ExecutionEngine *e)
+ : engine(e)
+ {
+ mark = e->jsStackTop;
+ }
+
+ ~ValueScope() {
+ Q_ASSERT(engine->jsStackTop >= mark);
+ engine->jsStackTop = mark;
+ }
+
+ ExecutionEngine *engine;
+ Value *mark;
+};
+
+struct ScopedValue;
+struct ValueRef;
+
+struct ReturnedValue
+{
+ ReturnedValue(const Value &v)
+ : v(v) {}
+ // no destructor
+
+
+private:
+ friend struct ValueRef;
+ friend struct ScopedValue;
+ QV4::Value v;
+};
+
+struct ScopedValue
+{
+ ScopedValue(const ValueScope &scope)
+ {
+ ptr = scope.engine->jsStackTop++;
+ }
+
+ ScopedValue(const ValueScope &scope, const Value &v)
+ {
+ ptr = scope.engine->jsStackTop++;
+ *ptr = v;
+ }
+
+ ScopedValue(const ValueScope &scope, const ReturnedValue &v)
+ {
+ ptr = scope.engine->jsStackTop++;
+ *ptr = v.v;
+ }
+
+ ScopedValue &operator=(const Value &v) {
+ *ptr = v;
+ return *this;
+ }
+
+ ScopedValue &operator=(const ReturnedValue &v) {
+ *ptr = v.v;
+ return *this;
+ }
+
+ ScopedValue &operator=(const ScopedValue &other) {
+ *ptr = *other.ptr;
+ return *this;
+ }
+
+ Value *operator->() {
+ return ptr;
+ }
+
+ operator const Value &() const {
+ return *ptr;
+ }
+
+ Value *ptr;
+};
+
+struct ScopedCallData {
+ ScopedCallData(ExecutionEngine *e, int argc)
+ : engine(e)
+ // ### this check currently won't work because of exceptions
+#ifndef QT_NO_DEBUG
+ , size(qMax(argc, (int)QV4::Global::ReservedArgumentCount) + offsetof(QV4::CallData, args)/sizeof(QV4::Value))
+#endif
+ {
+ ptr = reinterpret_cast<CallData *>(e->stackPush(qMax(argc, (int)QV4::Global::ReservedArgumentCount) + offsetof(QV4::CallData, args)/sizeof(QV4::Value)));
+ ptr->tag = 0;
+ ptr->argc = argc;
+ }
+
+ ~ScopedCallData() {
+#ifndef QT_NO_DEBUG
+ engine->stackPop(size);
+ Q_ASSERT((void *)engine->jsStackTop == (void *)ptr);
+#else
+ engine->jsStackTop = reinterpret_cast<Value *>(ptr);
+#endif
+ }
+
+ CallData *operator->() {
+ return ptr;
+ }
+
+ operator CallData *() const {
+ return ptr;
+ }
+
+
+ ExecutionEngine *engine;
+#ifndef QT_NO_DEBUG
+ int size;
+#endif
+ CallData *ptr;
+};
+
+struct ValueRef {
+ ValueRef(const ScopedValue &v)
+ : ptr(v.ptr) {}
+ ValueRef(const PersistentValue &v)
+ : ptr(&v.d->value) {}
+ ValueRef(PersistentValuePrivate *p)
+ : ptr(&p->value) {}
+ // Important: Do NOT add a copy constructor to this class
+ // adding a copy constructor actually changes the calling convention, ie.
+ // is not even binary compatible. Adding it would break assumptions made
+ // in the jit'ed code.
+ ValueRef &operator=(const ScopedValue &o)
+ { *ptr = *o.ptr; return *this; }
+ ValueRef &operator=(const ValueRef &o)
+ { *ptr = *o.ptr; return *this; }
+ ValueRef &operator=(const Value &v)
+ { *ptr = v; return *this; }
+ ValueRef &operator=(const ReturnedValue &v) {
+ *ptr = v.v;
+ return *this;
+ }
+
+ operator const Value *() const {
+ return ptr;
+ }
+ const Value *operator->() const {
+ return ptr;
+ }
+
+ operator Value *() {
+ return ptr;
+ }
+ Value *operator->() {
+ return ptr;
+ }
+
+ static ValueRef fromRawValue(Value *v) {
+ return ValueRef(v);
+ }
+ static const ValueRef fromRawValue(const Value *v) {
+ return ValueRef(const_cast<Value *>(v));
+ }
+ // ### get rid of this one!
+ ValueRef(Value *v) { ptr = v; }
+private:
+ Value *ptr;
+};
+
+
+struct CallDataRef {
+ CallDataRef(const ScopedCallData &c)
+ : ptr(c.ptr) {}
+ CallDataRef(CallData *v) { ptr = v; }
+ // Important: Do NOT add a copy constructor to this class
+ // adding a copy constructor actually changes the calling convention, ie.
+ // is not even binary compatible. Adding it would break assumptions made
+ // in the jit'ed code.
+ CallDataRef &operator=(const ScopedCallData &c)
+ { *ptr = *c.ptr; return *this; }
+ CallDataRef &operator=(const CallDataRef &o)
+ { *ptr = *o.ptr; return *this; }
+
+ operator const CallData *() const {
+ return ptr;
+ }
+ const CallData *operator->() const {
+ return ptr;
+ }
+
+ operator CallData *() {
+ return ptr;
+ }
+ CallData *operator->() {
+ return ptr;
+ }
+
+private:
+ CallData *ptr;
+};
+
+}
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/qml/jsruntime/qv4script.cpp b/src/qml/jsruntime/qv4script.cpp
index aef8ac8838..16bab966e9 100644
--- a/src/qml/jsruntime/qv4script.cpp
+++ b/src/qml/jsruntime/qv4script.cpp
@@ -46,6 +46,7 @@
#include "qv4context_p.h"
#include "qv4debugging_p.h"
#include "qv4exception_p.h"
+#include "qv4scopedvalue_p.h"
#include <private/qqmljsengine_p.h>
#include <private/qqmljslexer_p.h>
@@ -74,7 +75,7 @@ QmlBindingWrapper::QmlBindingWrapper(ExecutionContext *scope, Function *f, Objec
scope->engine->popContext();
}
-Value QmlBindingWrapper::call(Managed *that, const CallData &)
+Value QmlBindingWrapper::call(Managed *that, CallData *)
{
ExecutionEngine *engine = that->engine();
QmlBindingWrapper *This = static_cast<QmlBindingWrapper *>(that);
@@ -237,9 +238,9 @@ Value Script::run()
} else {
FunctionObject *f = new (engine->memoryManager) QmlBindingWrapper(scope, vmFunction, qml.value().asObject());
- CALLDATA(0);
- d.thisObject = Value::undefinedValue();
- return f->call(d);
+ ScopedCallData callData(scope->engine, 0);
+ callData->thisObject = Value::undefinedValue();
+ return f->call(callData);
}
}
diff --git a/src/qml/jsruntime/qv4script_p.h b/src/qml/jsruntime/qv4script_p.h
index b3bce6b427..b00e076a2b 100644
--- a/src/qml/jsruntime/qv4script_p.h
+++ b/src/qml/jsruntime/qv4script_p.h
@@ -56,7 +56,7 @@ struct QmlBindingWrapper : FunctionObject {
QmlBindingWrapper(ExecutionContext *scope, Function *f, Object *qml);
- static Value call(Managed *that, const CallData &);
+ static Value call(Managed *that, CallData *);
static void markObjects(Managed *m);
private:
diff --git a/src/qml/jsruntime/qv4sequenceobject.cpp b/src/qml/jsruntime/qv4sequenceobject.cpp
index b7f7317c76..29ca34910c 100644
--- a/src/qml/jsruntime/qv4sequenceobject.cpp
+++ b/src/qml/jsruntime/qv4sequenceobject.cpp
@@ -46,6 +46,7 @@
#include <private/qv4functionobject_p.h>
#include <private/qv4arrayobject_p.h>
#include <private/qqmlengine_p.h>
+#include <private/qv4scopedvalue_p.h>
QT_BEGIN_NAMESPACE
@@ -351,11 +352,11 @@ public:
bool operator()(typename Container::value_type lhs, typename Container::value_type rhs)
{
QV4::Managed *fun = this->m_compareFn.asManaged();
- CALLDATA(2);
- d.args[0] = convertElementToValue(this->m_ctx->engine, lhs);
- d.args[1] = convertElementToValue(this->m_ctx->engine, rhs);
- d.thisObject = QV4::Value::fromObject(this->m_ctx->engine->globalObject);
- QV4::Value result = fun->call(d);
+ ScopedCallData callData(fun->engine(), 2);
+ callData->args[0] = convertElementToValue(this->m_ctx->engine, lhs);
+ callData->args[1] = convertElementToValue(this->m_ctx->engine, rhs);
+ callData->thisObject = QV4::Value::fromObject(this->m_ctx->engine->globalObject);
+ QV4::Value result = fun->call(callData);
return result.toNumber() < 0;
}
diff --git a/src/qml/jsruntime/qv4sparsearray.cpp b/src/qml/jsruntime/qv4sparsearray.cpp
index 835a0d004f..f21855ebc9 100644
--- a/src/qml/jsruntime/qv4sparsearray.cpp
+++ b/src/qml/jsruntime/qv4sparsearray.cpp
@@ -43,6 +43,7 @@
#include "qv4runtime_p.h"
#include "qv4object_p.h"
#include "qv4functionobject_p.h"
+#include "qv4scopedvalue_p.h"
#include <stdlib.h>
#ifdef QT_QMAP_DEBUG
@@ -54,20 +55,21 @@ using namespace QV4;
bool ArrayElementLessThan::operator()(const Property &p1, const Property &p2) const
{
- Value v1 = p1.value;
- Value v2 = p2.value;
- if (v1.isUndefined())
+ if (p1.value.isUndefined())
return false;
- if (v2.isUndefined())
+ if (p2.value.isUndefined())
return true;
- if (!m_comparefn.isUndefined()) {
- Value args[] = { v1, v2 };
+ if (Object *o = m_comparefn.asObject()) {
+ ScopedCallData callData(o->engine(), 2);
+ callData->thisObject = Value::undefinedValue();
+ callData->args[0] = p1.value;
+ callData->args[1] = p2.value;
Value result = Value::undefinedValue();
- __qmljs_call_value(m_context, &result, /*thisObject*/0, m_comparefn, args, 2);
+ __qmljs_call_value(m_context, &result, QV4::ValueRef::fromRawValue(&m_comparefn), callData);
return result.toNumber() <= 0;
}
- return v1.toString(m_context)->toQString() < v2.toString(m_context)->toQString();
+ return p1.value.toString(m_context)->toQString() < p2.value.toString(m_context)->toQString();
}
diff --git a/src/qml/jsruntime/qv4stacktrace.cpp b/src/qml/jsruntime/qv4stacktrace.cpp
index b0fabfd42e..2a27c57e46 100644
--- a/src/qml/jsruntime/qv4stacktrace.cpp
+++ b/src/qml/jsruntime/qv4stacktrace.cpp
@@ -137,7 +137,7 @@ NativeFrame NativeStackTrace::nextFrame() {
continue;
frame.function = f;
- frame.line = f->lineNumberForProgramCounter(pc - reinterpret_cast<quintptr>(f->code));
+ frame.line = f->lineNumberForProgramCounter(pc - reinterpret_cast<quintptr>(f->codePtr));
}
return frame;
diff --git a/src/qml/jsruntime/qv4stringobject.cpp b/src/qml/jsruntime/qv4stringobject.cpp
index 52d98502a3..0a9cb32e6f 100644
--- a/src/qml/jsruntime/qv4stringobject.cpp
+++ b/src/qml/jsruntime/qv4stringobject.cpp
@@ -44,6 +44,7 @@
#include "qv4regexpobject_p.h"
#include "qv4objectproto_p.h"
#include "qv4mm_p.h"
+#include "qv4scopedvalue_p.h"
#include <QtCore/qnumeric.h>
#include <QtCore/qmath.h>
#include <QtCore/QDateTime>
@@ -159,21 +160,21 @@ StringCtor::StringCtor(ExecutionContext *scope)
vtbl = &static_vtbl;
}
-Value StringCtor::construct(Managed *m, const CallData &d)
+Value StringCtor::construct(Managed *m, CallData *callData)
{
Value value;
- if (d.argc)
- value = Value::fromString(d.args[0].toString(m->engine()->current));
+ if (callData->argc)
+ value = Value::fromString(callData->args[0].toString(m->engine()->current));
else
value = Value::fromString(m->engine()->current, QString());
return Value::fromObject(m->engine()->newStringObject(value));
}
-Value StringCtor::call(Managed *m, const CallData &d)
+Value StringCtor::call(Managed *m, CallData *callData)
{
Value value;
- if (d.argc)
- value = Value::fromString(d.args[0].toString(m->engine()->current));
+ if (callData->argc)
+ value = Value::fromString(callData->args[0].toString(m->engine()->current));
else
value = Value::fromString(m->engine()->current, QString());
return value;
@@ -279,12 +280,15 @@ Value StringPrototype::method_charCodeAt(SimpleCallContext *context)
Value StringPrototype::method_concat(SimpleCallContext *context)
{
+ ValueScope scope(context);
+
QString value = getThisString(context, context->thisObject);
+ ScopedValue v(scope);
for (int i = 0; i < context->argumentCount; ++i) {
- Value v = __qmljs_to_string(context->arguments[i], context);
- assert(v.isString());
- value += v.stringValue()->toQString();
+ v = __qmljs_to_string(ValueRef(&context->arguments[i]), context);
+ assert(v->isString());
+ value += v->stringValue()->toQString();
}
return Value::fromString(context, value);
@@ -311,15 +315,17 @@ Value StringPrototype::method_indexOf(SimpleCallContext *context)
Value StringPrototype::method_lastIndexOf(SimpleCallContext *context)
{
+ ValueScope scope(context);
+
const QString value = getThisString(context, context->thisObject);
QString searchString;
if (context->argumentCount) {
- Value v = __qmljs_to_string(context->arguments[0], context);
+ Value v = __qmljs_to_string(ValueRef(&context->arguments[0]), context);
searchString = v.stringValue()->toQString();
}
- Value posArg = context->argumentCount > 1 ? context->arguments[1] : Value::undefinedValue();
+ ScopedValue posArg(scope, context->argumentCount > 1 ? context->arguments[1] : Value::undefinedValue());
double position = __qmljs_to_number(posArg);
if (std::isnan(position))
position = +qInf();
@@ -352,9 +358,9 @@ Value StringPrototype::method_match(SimpleCallContext *context)
Value regexp = context->argumentCount ? context->arguments[0] : Value::undefinedValue();
RegExpObject *rx = regexp.as<RegExpObject>();
if (!rx) {
- CALLDATA(1);
- d.args[0] = regexp;
- rx = context->engine->regExpCtor.asFunctionObject()->construct(d).as<RegExpObject>();
+ ScopedCallData callData(context->engine, 1);
+ callData->args[0] = regexp;
+ rx = context->engine->regExpCtor.asFunctionObject()->construct(callData).as<RegExpObject>();
}
if (!rx)
@@ -366,11 +372,11 @@ Value StringPrototype::method_match(SimpleCallContext *context)
// ### use the standard builtin function, not the one that might be redefined in the proto
FunctionObject *exec = context->engine->regExpClass->prototype->get(context->engine->newString(QStringLiteral("exec")), 0).asFunctionObject();
- CALLDATA(1);
- d.thisObject = Value::fromObject(rx);
- d.args[0] = Value::fromString(s);
+ ScopedCallData callData(context->engine, 1);
+ callData->thisObject = Value::fromObject(rx);
+ callData->args[0] = Value::fromString(s);
if (!global)
- return exec->call(d);
+ return exec->call(callData);
String *lastIndex = context->engine->newString(QStringLiteral("lastIndex"));
rx->put(lastIndex, Value::fromInt32(0));
@@ -379,7 +385,7 @@ Value StringPrototype::method_match(SimpleCallContext *context)
double previousLastIndex = 0;
uint n = 0;
while (1) {
- Value result = exec->call(d);
+ Value result = exec->call(callData);
if (result.isNull())
break;
assert(result.isObject());
@@ -505,8 +511,8 @@ Value StringPrototype::method_replace(SimpleCallContext *ctx)
Value replaceValue = ctx->argument(1);
if (FunctionObject* searchCallback = replaceValue.asFunctionObject()) {
result.reserve(string.length() + 10*numStringMatches);
- CALLDATA(numCaptures + 2);
- d.thisObject = Value::undefinedValue();
+ ScopedCallData callData(ctx->engine, numCaptures + 2);
+ callData->thisObject = Value::undefinedValue();
int lastEnd = 0;
for (int i = 0; i < numStringMatches; ++i) {
for (int k = 0; k < numCaptures; ++k) {
@@ -516,15 +522,15 @@ Value StringPrototype::method_replace(SimpleCallContext *ctx)
Value entry = Value::undefinedValue();
if (start != JSC::Yarr::offsetNoMatch && end != JSC::Yarr::offsetNoMatch)
entry = Value::fromString(ctx, string.mid(start, end - start));
- d.args[k] = entry;
+ callData->args[k] = entry;
}
uint matchStart = matchOffsets[i * numCaptures * 2];
Q_ASSERT(matchStart >= lastEnd);
uint matchEnd = matchOffsets[i * numCaptures * 2 + 1];
- d.args[numCaptures] = Value::fromUInt32(matchStart);
- d.args[numCaptures + 1] = Value::fromString(ctx, string);
+ callData->args[numCaptures] = Value::fromUInt32(matchStart);
+ callData->args[numCaptures + 1] = Value::fromString(ctx, string);
- Value replacement = searchCallback->call(d);
+ Value replacement = searchCallback->call(callData);
result += string.midRef(lastEnd, matchStart - lastEnd);
result += replacement.toString(ctx)->toQString();
lastEnd = matchEnd;
@@ -566,9 +572,9 @@ Value StringPrototype::method_search(SimpleCallContext *ctx)
Value regExpValue = ctx->argument(0);
RegExpObject *regExp = regExpValue.as<RegExpObject>();
if (!regExp) {
- CALLDATA(1);
- d.args[0] = regExpValue;
- regExpValue = ctx->engine->regExpCtor.asFunctionObject()->construct(d);
+ ScopedCallData callData(ctx->engine, 1);
+ callData->args[0] = regExpValue;
+ regExpValue = ctx->engine->regExpCtor.asFunctionObject()->construct(callData);
regExp = regExpValue.as<RegExpObject>();
}
uint* matchOffsets = (uint*)alloca(regExp->value->captureCount() * 2 * sizeof(uint));
@@ -783,7 +789,7 @@ Value StringPrototype::method_trim(SimpleCallContext *ctx)
if (ctx->thisObject.isNull() || ctx->thisObject.isUndefined())
ctx->throwTypeError();
- QString s = __qmljs_to_string(ctx->thisObject, ctx).stringValue()->toQString();
+ QString s = __qmljs_to_string(ValueRef(&ctx->thisObject), ctx).stringValue()->toQString();
const QChar *chars = s.constData();
int start, end;
for (start = 0; start < s.length(); ++start) {
diff --git a/src/qml/jsruntime/qv4stringobject_p.h b/src/qml/jsruntime/qv4stringobject_p.h
index 38d6eeeac5..f9cf89e9d9 100644
--- a/src/qml/jsruntime/qv4stringobject_p.h
+++ b/src/qml/jsruntime/qv4stringobject_p.h
@@ -70,8 +70,8 @@ struct StringCtor: FunctionObject
{
StringCtor(ExecutionContext *scope);
- static Value construct(Managed *m, const CallData &d);
- static Value call(Managed *that, const CallData &d);
+ static Value construct(Managed *m, CallData *callData);
+ static Value call(Managed *that, CallData *callData);
protected:
static const ManagedVTable static_vtbl;
diff --git a/src/qml/jsruntime/qv4unwindhelper_arm_p.h b/src/qml/jsruntime/qv4unwindhelper_arm_p.h
index 6cfdce0e7d..e768544e11 100644
--- a/src/qml/jsruntime/qv4unwindhelper_arm_p.h
+++ b/src/qml/jsruntime/qv4unwindhelper_arm_p.h
@@ -79,7 +79,7 @@ static Function *lookupFunction(void *pc)
if (it == allFunctions.end())
return 0;
- quintptr codeStart = reinterpret_cast<quintptr>(removeThumbBit((void*)(*it)->code));
+ quintptr codeStart = reinterpret_cast<quintptr>(removeThumbBit((void*)(*it)->codePtr));
if (key < codeStart || key >= codeStart + (*it)->codeSize)
return 0;
return *it;
@@ -137,27 +137,27 @@ static unsigned write_prel31(unsigned *addr, void *ptr)
void UnwindHelper::deregisterFunction(Function *function)
{
QMutexLocker locker(&functionProtector);
- allFunctions.remove(reinterpret_cast<quintptr>(function->code));
+ allFunctions.remove(reinterpret_cast<quintptr>(function->codePtr));
}
void UnwindHelper::deregisterFunctions(const QVector<Function *> &functions)
{
QMutexLocker locker(&functionProtector);
foreach (Function *f, functions)
- allFunctions.remove(reinterpret_cast<quintptr>(f->code));
+ allFunctions.remove(reinterpret_cast<quintptr>(f->codePtr));
}
void UnwindHelper::registerFunction(Function *function)
{
QMutexLocker locker(&functionProtector);
- allFunctions.insert(reinterpret_cast<quintptr>(function->code), function);
+ allFunctions.insert(reinterpret_cast<quintptr>(function->codePtr), function);
}
void UnwindHelper::registerFunctions(const QVector<Function *> &functions)
{
QMutexLocker locker(&functionProtector);
foreach (Function *f, functions)
- allFunctions.insert(reinterpret_cast<quintptr>(f->code), f);
+ allFunctions.insert(reinterpret_cast<quintptr>(f->codePtr), f);
}
void UnwindHelper::prepareForUnwind(ExecutionContext *)
@@ -217,7 +217,7 @@ extern "C" Q_DECL_EXPORT void *__gnu_Unwind_Find_exidx(void *pc, int *entryCount
QV4::Function *function = QT_PREPEND_NAMESPACE(QV4::lookupFunction(pc));
if (function) {
*entryCount = 1;
- void * codeStart = QT_PREPEND_NAMESPACE(QV4::removeThumbBit((void*)function->code));
+ void * codeStart = QT_PREPEND_NAMESPACE(QV4::removeThumbBit((void*)function->codePtr));
// At the end of the function we store our synthetic exception table entry.
return (char *)codeStart + function->codeSize;
}
diff --git a/src/qml/jsruntime/qv4unwindhelper_dw2_p.h b/src/qml/jsruntime/qv4unwindhelper_dw2_p.h
index c53d20612c..03533ba526 100644
--- a/src/qml/jsruntime/qv4unwindhelper_dw2_p.h
+++ b/src/qml/jsruntime/qv4unwindhelper_dw2_p.h
@@ -127,7 +127,7 @@ UnwindInfo::~UnwindInfo()
static void ensureUnwindInfo(Function *f)
{
- if (!f->code)
+ if (!f->codePtr)
return; // Not a JIT generated function
ExecutableAllocator::ChunkOfPages *chunk = f->compilationUnit->chunkForFunction(f->compiledFunction->index);
diff --git a/src/qml/jsruntime/qv4value.cpp b/src/qml/jsruntime/qv4value.cpp
index a41262f12f..718b87d2c9 100644
--- a/src/qml/jsruntime/qv4value.cpp
+++ b/src/qml/jsruntime/qv4value.cpp
@@ -48,12 +48,47 @@
using namespace QV4;
+int Value::toInt32() const
+{
+ if (isConvertibleToInt())
+ return int_32;
+ double d;
+ if (isDouble())
+ d = dbl;
+ else
+ d = toNumber();
+
+ const double D32 = 4294967296.0;
+ const double D31 = D32 / 2.0;
+
+ if ((d >= -D31 && d < D31))
+ return static_cast<int>(d);
+
+ return Value::toInt32(d);
+}
+
+unsigned int Value::toUInt32() const
+{
+ if (isConvertibleToInt())
+ return (unsigned) int_32;
+ double d;
+ if (isDouble())
+ d = dbl;
+ else
+ d = toNumber();
+
+ const double D32 = 4294967296.0;
+ if (d >= 0 && d < D32)
+ return static_cast<uint>(d);
+ return toUInt32(d);
+}
+
int Value::toUInt16() const
{
if (isConvertibleToInt())
return (ushort)(uint)integerValue();
- double number = __qmljs_to_number(*this);
+ double number = toNumber();
double D16 = 65536.0;
if ((number >= 0 && number < D16))
@@ -79,12 +114,32 @@ double Value::toInteger() const
if (isConvertibleToInt())
return int_32;
- return Value::toInteger(__qmljs_to_number(*this));
+ return Value::toInteger(toNumber());
}
double Value::toNumber() const
{
- return __qmljs_to_number(*this);
+ QV4::Value v = *this;
+
+ redo:
+ switch (v.type()) {
+ case QV4::Value::Undefined_Type:
+ return std::numeric_limits<double>::quiet_NaN();
+ case QV4::Value::Null_Type:
+ return 0;
+ case QV4::Value::Boolean_Type:
+ return (v.booleanValue() ? 1. : 0.);
+ case QV4::Value::Integer_Type:
+ return v.int_32;
+ case QV4::Value::String_Type:
+ return __qmljs_string_to_number(v.toQString());
+ case QV4::Value::Object_Type: {
+ v = __qmljs_to_primitive(ValueRef::fromRawValue(this), QV4::NUMBER_HINT);
+ goto redo;
+ }
+ default: // double
+ return v.doubleValue();
+ }
}
QString Value::toQString() const
@@ -103,16 +158,18 @@ QString Value::toQString() const
return stringValue()->toQString();
case Value::Object_Type: {
ExecutionContext *ctx = objectValue()->internalClass->engine->current;
+ ValueScope scope(ctx);
try {
- Value prim = __qmljs_to_primitive(*this, STRING_HINT);
- if (prim.isPrimitive())
- return prim.toQString();
+ ScopedValue prim(scope, __qmljs_to_primitive(ValueRef::fromRawValue(this), STRING_HINT));
+ if (prim->isPrimitive())
+ return prim->toQString();
} catch (Exception &e) {
e.accept(ctx);
try {
- Value prim = __qmljs_to_primitive(e.value(), STRING_HINT);
- if (prim.isPrimitive())
- return prim.toQString();
+ ScopedValue ex(scope, e.value());
+ ScopedValue prim(scope, __qmljs_to_primitive(ex, STRING_HINT));
+ if (prim->isPrimitive())
+ return prim->toQString();
} catch(Exception &e) {
e.accept(ctx);
}
@@ -216,9 +273,17 @@ String *Value::toString(ExecutionContext *ctx) const
{
if (isString())
return stringValue();
- return __qmljs_convert_to_string(ctx, *this);
+ return __qmljs_convert_to_string(ctx, ValueRef::fromRawValue(this));
+}
+
+Object *Value::toObject(ExecutionContext *ctx) const
+{
+ if (isObject())
+ return objectValue();
+ return __qmljs_convert_to_object(ctx, ValueRef::fromRawValue(this));
}
+
Value Value::property(ExecutionContext *ctx, String *name) const
{
return isObject() ? objectValue()->get(name) : undefinedValue();
diff --git a/src/qml/jsruntime/qv4value_p.h b/src/qml/jsruntime/qv4value_p.h
index 73d5d0479d..8d6f26ea57 100644
--- a/src/qml/jsruntime/qv4value_p.h
+++ b/src/qml/jsruntime/qv4value_p.h
@@ -59,8 +59,6 @@ QT_BEGIN_NAMESPACE
namespace QV4 {
-double __qmljs_to_number(const QV4::Value &value);
-Q_QML_EXPORT QV4::String *__qmljs_convert_to_string(QV4::ExecutionContext *ctx, const QV4::Value &value);
QV4::Object *__qmljs_convert_to_object(QV4::ExecutionContext *ctx, const QV4::Value &value);
inline Managed *Value::asManaged() const
@@ -193,48 +191,6 @@ inline bool Value::toBoolean() const
}
}
-inline Object *Value::toObject(ExecutionContext *ctx) const
-{
- if (isObject())
- return objectValue();
- return __qmljs_convert_to_object(ctx, *this);
-}
-
-inline int Value::toInt32() const
-{
- if (isConvertibleToInt())
- return int_32;
- double d;
- if (isDouble())
- d = dbl;
- else
- d = __qmljs_to_number(*this);
-
- const double D32 = 4294967296.0;
- const double D31 = D32 / 2.0;
-
- if ((d >= -D31 && d < D31))
- return static_cast<int>(d);
-
- return Value::toInt32(d);
-}
-
-inline unsigned int Value::toUInt32() const
-{
- if (isConvertibleToInt())
- return (unsigned) int_32;
- double d;
- if (isDouble())
- d = dbl;
- else
- d = __qmljs_to_number(*this);
-
- const double D32 = 4294967296.0;
- if (d >= 0 && d < D32)
- return static_cast<uint>(d);
- return toUInt32(d);
-}
-
inline uint Value::asArrayIndex() const
{
if (isInteger() && int_32 >= 0)
@@ -320,10 +276,10 @@ inline ErrorObject *Value::asErrorObject() const
}
// ###
-inline Value Managed::construct(const CallData &d) {
+inline Value Managed::construct(CallData *d) {
return vtbl->construct(this, d);
}
-inline Value Managed::call(const CallData &d) {
+inline Value Managed::call(CallData *d) {
return vtbl->call(this, d);
}
@@ -380,6 +336,7 @@ public:
}
private:
+ friend struct ValueRef;
PersistentValuePrivate *d;
};
@@ -414,6 +371,7 @@ public:
void markOnce();
private:
+ friend struct ValueRef;
PersistentValuePrivate *d;
};
diff --git a/src/qml/jsruntime/qv4vme_moth.cpp b/src/qml/jsruntime/qv4vme_moth.cpp
index d5416105fa..92b0c75e8c 100644
--- a/src/qml/jsruntime/qv4vme_moth.cpp
+++ b/src/qml/jsruntime/qv4vme_moth.cpp
@@ -45,7 +45,7 @@
#include <private/qv4debugging_p.h>
#include <private/qv4exception_p.h>
#include <private/qv4math_p.h>
-
+#include <private/qv4scopedvalue_p.h>
#include <iostream>
#include "qv4alloca_p.h"
@@ -183,7 +183,9 @@ static inline QV4::Value *getValueRef(QV4::ExecutionContext *context,
return c->locals + index;
} else if (param.isTemp()) {
VMSTATS(paramIsTemp);
+#if !defined(QT_NO_DEBUG)
Q_ASSERT(param.index < stackSize);
+#endif
return stack + param.index;
} else if (param.isScopedLocal()) {
VMSTATS(paramIsScopedLocal);
@@ -281,29 +283,29 @@ QV4::Value VME::run(QV4::ExecutionContext *context, const uchar *&code,
MOTH_BEGIN_INSTR(StoreName)
TRACE(inline, "property name = %s", instr.name->toQString().toUtf8().constData());
- __qmljs_set_activation_property(context, runtimeStrings[instr.name], VALUE(instr.source));
+ __qmljs_set_activation_property(context, runtimeStrings[instr.name], VALUEPTR(instr.source));
MOTH_END_INSTR(StoreName)
MOTH_BEGIN_INSTR(LoadElement)
- __qmljs_get_element(context, VALUEPTR(instr.result), VALUE(instr.base), VALUE(instr.index));
+ __qmljs_get_element(context, VALUEPTR(instr.result), VALUEPTR(instr.base), VALUEPTR(instr.index));
MOTH_END_INSTR(LoadElement)
MOTH_BEGIN_INSTR(StoreElement)
- __qmljs_set_element(context, VALUE(instr.base), VALUE(instr.index), VALUE(instr.source));
+ __qmljs_set_element(context, VALUEPTR(instr.base), VALUEPTR(instr.index), VALUEPTR(instr.source));
MOTH_END_INSTR(StoreElement)
MOTH_BEGIN_INSTR(LoadProperty)
- __qmljs_get_property(context, VALUEPTR(instr.result), VALUE(instr.base), runtimeStrings[instr.name]);
+ __qmljs_get_property(context, VALUEPTR(instr.result), VALUEPTR(instr.base), runtimeStrings[instr.name]);
MOTH_END_INSTR(LoadProperty)
MOTH_BEGIN_INSTR(StoreProperty)
- __qmljs_set_property(context, VALUE(instr.base), runtimeStrings[instr.name], VALUE(instr.source));
+ __qmljs_set_property(context, VALUEPTR(instr.base), runtimeStrings[instr.name], VALUEPTR(instr.source));
MOTH_END_INSTR(StoreProperty)
MOTH_BEGIN_INSTR(Push)
TRACE(inline, "stack size: %u", instr.value);
stackSize = instr.value;
- stack = static_cast<QV4::Value *>(alloca(stackSize * sizeof(QV4::Value)));
+ stack = context->engine->stackPush(stackSize);
memset(stack, 0, stackSize * sizeof(QV4::Value));
MOTH_END_INSTR(Push)
@@ -318,33 +320,45 @@ QV4::Value VME::run(QV4::ExecutionContext *context, const uchar *&code,
}
}
#endif // DO_TRACE_INSTR
- Q_ASSERT(instr.args + instr.argc <= stackSize);
- QV4::Value *args = stack + instr.args;
- __qmljs_call_value(context, VALUEPTR(instr.result), /*thisObject*/0, VALUE(instr.dest), args, instr.argc);
+ Q_ASSERT(instr.callData + instr.argc + offsetof(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
+ QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData);
+ callData->tag = 0;
+ callData->argc = instr.argc;
+ callData->thisObject = QV4::Value::undefinedValue();
+ __qmljs_call_value(context, VALUEPTR(instr.result), VALUEPTR(instr.dest), callData);
MOTH_END_INSTR(CallValue)
MOTH_BEGIN_INSTR(CallProperty)
TRACE(property name, "%s, args=%u, argc=%u, this=%s", qPrintable(instr.name->toQString()), instr.args, instr.argc, (VALUE(instr.base)).toString(context)->toQString().toUtf8().constData());
- Q_ASSERT(instr.args + instr.argc <= stackSize);
- QV4::Value *args = stack + instr.args;
- __qmljs_call_property(context, VALUEPTR(instr.result), VALUE(instr.base), runtimeStrings[instr.name], args, instr.argc);
+ Q_ASSERT(instr.callData + instr.argc + offsetof(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
+ QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData);
+ callData->tag = 0;
+ callData->argc = instr.argc;
+ callData->thisObject = VALUE(instr.base);
+ __qmljs_call_property(context, QV4::ValueRef::fromRawValue(VALUEPTR(instr.result)), runtimeStrings[instr.name], callData);
MOTH_END_INSTR(CallProperty)
MOTH_BEGIN_INSTR(CallElement)
- Q_ASSERT(instr.args + instr.argc <= stackSize);
- QV4::Value *args = stack + instr.args;
- __qmljs_call_element(context, VALUEPTR(instr.result), VALUE(instr.base), VALUE(instr.index), args, instr.argc);
+ Q_ASSERT(instr.callData + instr.argc + offsetof(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
+ QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData);
+ callData->tag = 0;
+ callData->argc = instr.argc;
+ callData->thisObject = VALUE(instr.base);
+ __qmljs_call_element(context, VALUEPTR(instr.result), VALUEPTR(instr.index), callData);
MOTH_END_INSTR(CallElement)
MOTH_BEGIN_INSTR(CallActivationProperty)
- Q_ASSERT(instr.args + instr.argc <= stackSize);
TRACE(args, "starting at %d, length %d", instr.args, instr.argc);
- QV4::Value *args = stack + instr.args;
- __qmljs_call_activation_property(context, VALUEPTR(instr.result), runtimeStrings[instr.name], args, instr.argc);
+ Q_ASSERT(instr.callData + instr.argc + offsetof(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
+ QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData);
+ callData->tag = 0;
+ callData->argc = instr.argc;
+ callData->thisObject = QV4::Value::undefinedValue();
+ __qmljs_call_activation_property(context, VALUEPTR(instr.result), runtimeStrings[instr.name], callData);
MOTH_END_INSTR(CallActivationProperty)
MOTH_BEGIN_INSTR(CallBuiltinThrow)
- __qmljs_throw(context, VALUE(instr.arg));
+ __qmljs_throw(context, VALUEPTR(instr.arg));
MOTH_END_INSTR(CallBuiltinThrow)
MOTH_BEGIN_INSTR(EnterTry)
@@ -358,7 +372,7 @@ QV4::Value VME::run(QV4::ExecutionContext *context, const uchar *&code,
ex.accept(context);
VALUE(instr.exceptionVar) = ex.value();
try {
- QV4::ExecutionContext *catchContext = __qmljs_builtin_push_catch_scope(runtimeStrings[instr.exceptionVarName], ex.value(), context);
+ QV4::ExecutionContext *catchContext = __qmljs_builtin_push_catch_scope(runtimeStrings[instr.exceptionVarName], VALUEPTR(instr.exceptionVar), context);
const uchar *catchCode = ((uchar *)&instr.catchOffset) + instr.catchOffset;
run(catchContext, catchCode, stack, stackSize);
code = catchCode;
@@ -380,7 +394,7 @@ QV4::Value VME::run(QV4::ExecutionContext *context, const uchar *&code,
MOTH_END_INSTR(CallBuiltinFinishTry)
MOTH_BEGIN_INSTR(CallBuiltinPushScope)
- context = __qmljs_builtin_push_with_scope(VALUE(instr.arg), context);
+ context = __qmljs_builtin_push_with_scope(VALUEPTR(instr.arg), context);
MOTH_END_INSTR(CallBuiltinPushScope)
MOTH_BEGIN_INSTR(CallBuiltinPopScope)
@@ -388,19 +402,19 @@ QV4::Value VME::run(QV4::ExecutionContext *context, const uchar *&code,
MOTH_END_INSTR(CallBuiltinPopScope)
MOTH_BEGIN_INSTR(CallBuiltinForeachIteratorObject)
- __qmljs_foreach_iterator_object(context, VALUEPTR(instr.result), VALUE(instr.arg));
+ __qmljs_foreach_iterator_object(context, VALUEPTR(instr.result), VALUEPTR(instr.arg));
MOTH_END_INSTR(CallBuiltinForeachIteratorObject)
MOTH_BEGIN_INSTR(CallBuiltinForeachNextPropertyName)
- __qmljs_foreach_next_property_name(VALUEPTR(instr.result), VALUE(instr.arg));
+ __qmljs_foreach_next_property_name(VALUEPTR(instr.result), VALUEPTR(instr.arg));
MOTH_END_INSTR(CallBuiltinForeachNextPropertyName)
MOTH_BEGIN_INSTR(CallBuiltinDeleteMember)
- __qmljs_delete_member(context, VALUEPTR(instr.result), VALUE(instr.base), runtimeStrings[instr.member]);
+ __qmljs_delete_member(context, VALUEPTR(instr.result), VALUEPTR(instr.base), runtimeStrings[instr.member]);
MOTH_END_INSTR(CallBuiltinDeleteMember)
MOTH_BEGIN_INSTR(CallBuiltinDeleteSubscript)
- __qmljs_delete_subscript(context, VALUEPTR(instr.result), VALUE(instr.base), VALUE(instr.index));
+ __qmljs_delete_subscript(context, VALUEPTR(instr.result), VALUEPTR(instr.base), VALUEPTR(instr.index));
MOTH_END_INSTR(CallBuiltinDeleteSubscript)
MOTH_BEGIN_INSTR(CallBuiltinDeleteName)
@@ -408,11 +422,11 @@ QV4::Value VME::run(QV4::ExecutionContext *context, const uchar *&code,
MOTH_END_INSTR(CallBuiltinDeleteName)
MOTH_BEGIN_INSTR(CallBuiltinTypeofMember)
- __qmljs_builtin_typeof_member(context, VALUEPTR(instr.result), VALUE(instr.base), runtimeStrings[instr.member]);
+ __qmljs_builtin_typeof_member(context, VALUEPTR(instr.result), VALUEPTR(instr.base), runtimeStrings[instr.member]);
MOTH_END_INSTR(CallBuiltinTypeofMember)
MOTH_BEGIN_INSTR(CallBuiltinTypeofSubscript)
- __qmljs_builtin_typeof_element(context, VALUEPTR(instr.result), VALUE(instr.base), VALUE(instr.index));
+ __qmljs_builtin_typeof_element(context, VALUEPTR(instr.result), VALUEPTR(instr.base), VALUEPTR(instr.index));
MOTH_END_INSTR(CallBuiltinTypeofSubscript)
MOTH_BEGIN_INSTR(CallBuiltinTypeofName)
@@ -420,15 +434,15 @@ QV4::Value VME::run(QV4::ExecutionContext *context, const uchar *&code,
MOTH_END_INSTR(CallBuiltinTypeofName)
MOTH_BEGIN_INSTR(CallBuiltinTypeofValue)
- __qmljs_builtin_typeof(context, VALUEPTR(instr.result), VALUE(instr.value));
+ __qmljs_builtin_typeof(context, VALUEPTR(instr.result), VALUEPTR(instr.value));
MOTH_END_INSTR(CallBuiltinTypeofValue)
MOTH_BEGIN_INSTR(CallBuiltinPostIncMember)
- __qmljs_builtin_post_increment_member(context, VALUEPTR(instr.result), VALUE(instr.base), runtimeStrings[instr.member]);
+ __qmljs_builtin_post_increment_member(context, VALUEPTR(instr.result), VALUEPTR(instr.base), runtimeStrings[instr.member]);
MOTH_END_INSTR(CallBuiltinTypeofMember)
MOTH_BEGIN_INSTR(CallBuiltinPostIncSubscript)
- __qmljs_builtin_post_increment_element(context, VALUEPTR(instr.result), VALUE(instr.base), VALUEPTR(instr.index));
+ __qmljs_builtin_post_increment_element(context, VALUEPTR(instr.result), VALUEPTR(instr.base), VALUEPTR(instr.index));
MOTH_END_INSTR(CallBuiltinTypeofSubscript)
MOTH_BEGIN_INSTR(CallBuiltinPostIncName)
@@ -440,11 +454,11 @@ QV4::Value VME::run(QV4::ExecutionContext *context, const uchar *&code,
MOTH_END_INSTR(CallBuiltinTypeofValue)
MOTH_BEGIN_INSTR(CallBuiltinPostDecMember)
- __qmljs_builtin_post_decrement_member(context, VALUEPTR(instr.result), VALUE(instr.base), runtimeStrings[instr.member]);
+ __qmljs_builtin_post_decrement_member(context, VALUEPTR(instr.result), VALUEPTR(instr.base), runtimeStrings[instr.member]);
MOTH_END_INSTR(CallBuiltinTypeofMember)
MOTH_BEGIN_INSTR(CallBuiltinPostDecSubscript)
- __qmljs_builtin_post_decrement_element(context, VALUEPTR(instr.result), VALUE(instr.base), VALUE(instr.index));
+ __qmljs_builtin_post_decrement_element(context, VALUEPTR(instr.result), VALUEPTR(instr.base), VALUEPTR(instr.index));
MOTH_END_INSTR(CallBuiltinTypeofSubscript)
MOTH_BEGIN_INSTR(CallBuiltinPostDecName)
@@ -460,11 +474,11 @@ QV4::Value VME::run(QV4::ExecutionContext *context, const uchar *&code,
MOTH_END_INSTR(CallBuiltinDeclareVar)
MOTH_BEGIN_INSTR(CallBuiltinDefineGetterSetter)
- __qmljs_builtin_define_getter_setter(context, VALUE(instr.object), runtimeStrings[instr.name], VALUEPTR(instr.getter), VALUEPTR(instr.setter));
+ __qmljs_builtin_define_getter_setter(context, VALUEPTR(instr.object), runtimeStrings[instr.name], VALUEPTR(instr.getter), VALUEPTR(instr.setter));
MOTH_END_INSTR(CallBuiltinDefineGetterSetter)
MOTH_BEGIN_INSTR(CallBuiltinDefineProperty)
- __qmljs_builtin_define_property(context, VALUE(instr.object), runtimeStrings[instr.name], VALUEPTR(instr.value));
+ __qmljs_builtin_define_property(context, VALUEPTR(instr.object), runtimeStrings[instr.name], VALUEPTR(instr.value));
MOTH_END_INSTR(CallBuiltinDefineProperty)
MOTH_BEGIN_INSTR(CallBuiltinDefineArray)
@@ -483,22 +497,31 @@ QV4::Value VME::run(QV4::ExecutionContext *context, const uchar *&code,
MOTH_END_INSTR(CallBuiltinSetupArgumentsObject)
MOTH_BEGIN_INSTR(CreateValue)
- Q_ASSERT(instr.args + instr.argc <= stackSize);
- QV4::Value *args = stack + instr.args;
- __qmljs_construct_value(context, VALUEPTR(instr.result), VALUE(instr.func), args, instr.argc);
+ Q_ASSERT(instr.callData + instr.argc + offsetof(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
+ QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData);
+ callData->tag = 0;
+ callData->argc = instr.argc;
+ callData->thisObject = QV4::Value::undefinedValue();
+ __qmljs_construct_value(context, VALUEPTR(instr.result), VALUEPTR(instr.func), callData);
MOTH_END_INSTR(CreateValue)
MOTH_BEGIN_INSTR(CreateProperty)
- Q_ASSERT(instr.args + instr.argc <= stackSize);
- QV4::Value *args = stack + instr.args;
- __qmljs_construct_property(context, VALUEPTR(instr.result), VALUE(instr.base), runtimeStrings[instr.name], args, instr.argc);
+ Q_ASSERT(instr.callData + instr.argc + offsetof(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
+ QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData);
+ callData->tag = 0;
+ callData->argc = instr.argc;
+ callData->thisObject = QV4::Value::undefinedValue();
+ __qmljs_construct_property(context, VALUEPTR(instr.result), VALUEPTR(instr.base), runtimeStrings[instr.name], callData);
MOTH_END_INSTR(CreateProperty)
MOTH_BEGIN_INSTR(CreateActivationProperty)
TRACE(inline, "property name = %s, args = %d, argc = %d", instr.name->toQString().toUtf8().constData(), instr.args, instr.argc);
- Q_ASSERT(instr.args + instr.argc <= stackSize);
- QV4::Value *args = stack + instr.args;
- __qmljs_construct_activation_property(context, VALUEPTR(instr.result), runtimeStrings[instr.name], args, instr.argc);
+ Q_ASSERT(instr.callData + instr.argc + offsetof(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
+ QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData);
+ callData->tag = 0;
+ callData->argc = instr.argc;
+ callData->thisObject = QV4::Value::undefinedValue();
+ __qmljs_construct_activation_property(context, VALUEPTR(instr.result), runtimeStrings[instr.name], callData);
MOTH_END_INSTR(CreateActivationProperty)
MOTH_BEGIN_INSTR(Jump)
@@ -506,22 +529,22 @@ QV4::Value VME::run(QV4::ExecutionContext *context, const uchar *&code,
MOTH_END_INSTR(Jump)
MOTH_BEGIN_INSTR(CJump)
- uint cond = __qmljs_to_boolean(VALUE(instr.condition));
+ uint cond = __qmljs_to_boolean(VALUEPTR(instr.condition));
TRACE(condition, "%s", cond ? "TRUE" : "FALSE");
if (cond)
code = ((uchar *)&instr.offset) + instr.offset;
MOTH_END_INSTR(CJump)
MOTH_BEGIN_INSTR(Unop)
- instr.alu(VALUEPTR(instr.result), VALUE(instr.source));
+ instr.alu(QV4::ValueRef::fromRawValue(VALUEPTR(instr.result)), QV4::ValueRef::fromRawValue(VALUEPTR(instr.source)));
MOTH_END_INSTR(Unop)
MOTH_BEGIN_INSTR(Binop)
- instr.alu(VALUEPTR(instr.result), VALUE(instr.lhs), VALUE(instr.rhs));
+ instr.alu(VALUEPTR(instr.result), VALUEPTR(instr.lhs), VALUEPTR(instr.rhs));
MOTH_END_INSTR(Binop)
MOTH_BEGIN_INSTR(BinopContext)
- instr.alu(context, VALUEPTR(instr.result), VALUE(instr.lhs), VALUE(instr.rhs));
+ instr.alu(context, VALUEPTR(instr.result), VALUEPTR(instr.lhs), VALUEPTR(instr.rhs));
MOTH_END_INSTR(BinopContext)
MOTH_BEGIN_INSTR(AddNumberParams)
@@ -552,6 +575,7 @@ QV4::Value VME::run(QV4::ExecutionContext *context, const uchar *&code,
MOTH_END_INSTR(SubNumberParams)
MOTH_BEGIN_INSTR(Ret)
+ context->engine->stackPop(stackSize);
QV4::Value &result = VALUE(instr.result);
// TRACE(Ret, "returning value %s", result.toString(context)->toQString().toUtf8().constData());
return result;
@@ -563,21 +587,21 @@ QV4::Value VME::run(QV4::ExecutionContext *context, const uchar *&code,
MOTH_BEGIN_INSTR(InplaceElementOp)
instr.alu(context,
- VALUE(instr.base),
- VALUE(instr.index),
- VALUE(instr.source));
+ VALUEPTR(instr.base),
+ VALUEPTR(instr.index),
+ VALUEPTR(instr.source));
MOTH_END_INSTR(InplaceElementOp)
MOTH_BEGIN_INSTR(InplaceMemberOp)
instr.alu(context,
- VALUE(instr.base),
+ VALUEPTR(instr.base),
runtimeStrings[instr.member],
- VALUE(instr.source));
+ VALUEPTR(instr.source));
MOTH_END_INSTR(InplaceMemberOp)
MOTH_BEGIN_INSTR(InplaceNameOp)
TRACE(name, "%s", instr.name->toQString().toUtf8().constData());
- instr.alu(context, runtimeStrings[instr.name], VALUE(instr.source));
+ instr.alu(context, runtimeStrings[instr.name], VALUEPTR(instr.source));
MOTH_END_INSTR(InplaceNameOp)
#ifdef MOTH_THREADED_INTERPRETER
diff --git a/src/qml/qml/qqmlcomponent.cpp b/src/qml/qml/qqmlcomponent.cpp
index a70b9064d9..475e69cd77 100644
--- a/src/qml/qml/qqmlcomponent.cpp
+++ b/src/qml/qml/qqmlcomponent.cpp
@@ -62,6 +62,7 @@
#include <private/qv4functionobject_p.h>
#include <private/qv4script_p.h>
+#include <private/qv4scopedvalue_p.h>
#include <QStack>
#include <QStringList>
@@ -1240,12 +1241,12 @@ void QQmlComponent::createObject(QQmlV4Function *args)
if (!valuemap.isEmpty()) {
QQmlComponentExtension *e = componentExtension(v8engine);
- QV4::Value f = QV4::Script::evaluate(QV8Engine::getV4(v8engine), QString::fromLatin1(INITIALPROPERTIES_SOURCE), args->qmlGlobal().asObject());
- CALLDATA(2);
- d.thisObject = QV4::Value::fromObject(v4engine->globalObject);
- d.args[0] = object;
- d.args[1] = valuemap;
- f.asFunctionObject()->call(d);
+ QV4::Value f = QV4::Script::evaluate(v4engine, QString::fromLatin1(INITIALPROPERTIES_SOURCE), args->qmlGlobal().asObject());
+ QV4::ScopedCallData callData(v4engine, 2);
+ callData->thisObject = QV4::Value::fromObject(v4engine->globalObject);
+ callData->args[0] = object;
+ callData->args[1] = valuemap;
+ f.asFunctionObject()->call(callData);
}
d->completeCreate();
@@ -1388,11 +1389,11 @@ void QQmlComponentPrivate::initializeObjectWithInitialProperties(const QV4::Valu
if (!valuemap.isEmpty()) {
QQmlComponentExtension *e = componentExtension(v8engine);
QV4::Value f = QV4::Script::evaluate(QV8Engine::getV4(v8engine), QString::fromLatin1(INITIALPROPERTIES_SOURCE), qmlGlobal.asObject());
- CALLDATA(2);
- d.thisObject = QV4::Value::fromObject(v4engine->globalObject);
- d.args[0] = object;
- d.args[1] = valuemap;
- f.asFunctionObject()->call(d);
+ QV4::ScopedCallData callData(v4engine, 2);
+ callData->thisObject = QV4::Value::fromObject(v4engine->globalObject);
+ callData->args[0] = object;
+ callData->args[1] = valuemap;
+ f.asFunctionObject()->call(callData);
}
}
@@ -1487,11 +1488,11 @@ void QmlIncubatorObject::setInitialState(QObject *o)
QV4::ExecutionEngine *v4 = QV8Engine::getV4(v8);
QV4::Value f = QV4::Script::evaluate(v4, QString::fromLatin1(INITIALPROPERTIES_SOURCE), qmlGlobal.asObject());
- CALLDATA(2);
- d.thisObject = QV4::Value::fromObject(v4->globalObject);
- d.args[0] = QV4::QObjectWrapper::wrap(v4, o);
- d.args[1] = valuemap;
- f.asFunctionObject()->call(d);
+ QV4::ScopedCallData callData(v4, 2);
+ callData->thisObject = QV4::Value::fromObject(v4->globalObject);
+ callData->args[0] = QV4::QObjectWrapper::wrap(v4, o);
+ callData->args[1] = valuemap;
+ f.asFunctionObject()->call(callData);
}
}
@@ -1524,10 +1525,10 @@ void QmlIncubatorObject::statusChanged(Status s)
if (QV4::FunctionObject *f = callback.asFunctionObject()) {
QV4::ExecutionContext *ctx = f->engine()->current;
try {
- CALLDATA(1);
- d.thisObject = QV4::Value::fromObject(this);
- d.args[0] = QV4::Value::fromUInt32(s);
- f->call(d);
+ QV4::ScopedCallData callData(ctx->engine, 1);
+ callData->thisObject = QV4::Value::fromObject(this);
+ callData->args[0] = QV4::Value::fromUInt32(s);
+ f->call(callData);
} catch (QV4::Exception &e) {
e.accept(ctx);
QQmlError error;
diff --git a/src/qml/qml/qqmljavascriptexpression.cpp b/src/qml/qml/qqmljavascriptexpression.cpp
index 41be44a0a7..2974bbcfbe 100644
--- a/src/qml/qml/qqmljavascriptexpression.cpp
+++ b/src/qml/qml/qqmljavascriptexpression.cpp
@@ -47,6 +47,7 @@
#include <private/qv4functionobject_p.h>
#include <private/qv4script_p.h>
#include <private/qv4errorobject_p.h>
+#include <private/qv4scopedvalue_p.h>
QT_BEGIN_NAMESPACE
@@ -125,8 +126,7 @@ QV4::Value
QQmlJavaScriptExpression::evaluate(QQmlContextData *context,
const QV4::Value &function, bool *isUndefined)
{
- QV4::Value args[QV4::Global::ReservedArgumentCount];
- return evaluate(context, function, 0, args, isUndefined);
+ return evaluate(context, function, 0, 0, isUndefined);
}
QV4::Value
@@ -173,11 +173,10 @@ QQmlJavaScriptExpression::evaluate(QQmlContextData *context,
This = value;
}
- QV4::CallData d;
- d.thisObject = This;
- d.args = args;
- d.argc = argc;
- result = function.asFunctionObject()->call(d);
+ QV4::ScopedCallData callData(v4, argc);
+ callData->thisObject = This;
+ memcpy(callData->args, args, argc*sizeof(QV4::Value));
+ result = function.asFunctionObject()->call(callData);
if (isUndefined)
*isUndefined = result.isUndefined();
diff --git a/src/qml/qml/qqmlproperty.cpp b/src/qml/qml/qqmlproperty.cpp
index d1ecfdc52d..cf1b5ffd18 100644
--- a/src/qml/qml/qqmlproperty.cpp
+++ b/src/qml/qml/qqmlproperty.cpp
@@ -1611,10 +1611,14 @@ QQmlMetaObject QQmlPropertyPrivate::rawMetaObjectForType(QQmlEnginePrivate *engi
{
if (engine) {
return engine->rawMetaObjectForType(userType);
- } else {
- QQmlType *type = QQmlMetaType::qmlType(userType);
- return QQmlMetaObject(type?type->baseMetaObject():0);
}
+ QQmlType *type = QQmlMetaType::qmlType(userType);
+ if (type)
+ return QQmlMetaObject(type->baseMetaObject());
+ QMetaType metaType(userType);
+ if ((metaType.flags() & QMetaType::PointerToQObject) && metaType.metaObject())
+ return metaType.metaObject();
+ return QQmlMetaObject((QObject*)0);
}
/*!
diff --git a/src/qml/qml/qqmlpropertycache.cpp b/src/qml/qml/qqmlpropertycache.cpp
index d10af391f5..a1385e06fc 100644
--- a/src/qml/qml/qqmlpropertycache.cpp
+++ b/src/qml/qml/qqmlpropertycache.cpp
@@ -124,7 +124,7 @@ static QQmlPropertyData::Flags flagsForPropertyType(int propType, QQmlEngine *en
engine ? QQmlEnginePrivate::get(engine)->typeCategory(propType)
: QQmlMetaType::typeCategory(propType);
- if (cat == QQmlMetaType::Object)
+ if (cat == QQmlMetaType::Object || QMetaType::typeFlags(propType) & QMetaType::PointerToQObject)
flags |= QQmlPropertyData::IsQObjectDerived;
else if (cat == QQmlMetaType::List)
flags |= QQmlPropertyData::IsQList;
@@ -1553,7 +1553,7 @@ void QQmlPropertyCache::toMetaObjectBuilder(QMetaObjectBuilder &builder)
} else {
method = builder.addSlot(signature);
}
- method.setAccess(QMetaMethod::Protected);
+ method.setAccess(QMetaMethod::Public);
if (arguments && arguments->names)
method.setParameterNames(*arguments->names);
diff --git a/src/qml/qml/qqmlvmemetaobject.cpp b/src/qml/qml/qqmlvmemetaobject.cpp
index 3d2d54ccfa..0079b9580f 100644
--- a/src/qml/qml/qqmlvmemetaobject.cpp
+++ b/src/qml/qml/qqmlvmemetaobject.cpp
@@ -55,6 +55,7 @@
#include <private/qv4object_p.h>
#include <private/qv4variantobject_p.h>
#include <private/qv4functionobject_p.h>
+#include <private/qv4scopedvalue_p.h>
QT_BEGIN_NAMESPACE
@@ -926,16 +927,16 @@ int QQmlVMEMetaObject::metaCall(QMetaObject::Call c, int _id, void **a)
QQmlVMEMetaData::MethodData *data = metaData->methodData() + id;
- CALLDATA(data->parameterCount);
- d.thisObject = ep->v8engine()->global();
+ QV4::ScopedCallData callData(function->engine(), data->parameterCount);
+ callData->thisObject = ep->v8engine()->global();
for (int ii = 0; ii < data->parameterCount; ++ii)
- d.args[ii] = ep->v8engine()->fromVariant(*(QVariant *)a[ii + 1]);
+ callData->args[ii] = ep->v8engine()->fromVariant(*(QVariant *)a[ii + 1]);
QV4::Value result = QV4::Value::undefinedValue();
QV4::ExecutionContext *ctx = function->engine()->current;
try {
- result = function->call(d);
+ result = function->call(callData);
if (a[0]) *(QVariant *)a[0] = ep->v8engine()->toVariant(result, 0);
} catch (QV4::Exception &e) {
e.accept(ctx);
diff --git a/src/qml/qml/qqmlxmlhttprequest.cpp b/src/qml/qml/qqmlxmlhttprequest.cpp
index 211383ae58..ddc7a4894b 100644
--- a/src/qml/qml/qqmlxmlhttprequest.cpp
+++ b/src/qml/qml/qqmlxmlhttprequest.cpp
@@ -53,6 +53,7 @@
#include <private/qv4engine_p.h>
#include <private/qv4functionobject_p.h>
#include <private/qqmlcontextwrapper_p.h>
+#include <private/qv4scopedvalue_p.h>
#include <QtCore/qobject.h>
#include <QtQml/qjsvalue.h>
@@ -1481,9 +1482,9 @@ void QQmlXMLHttpRequest::dispatchCallback(const Value &me)
QQmlContextData *callingContext = QmlContextWrapper::getContext(activationObject);
if (callingContext) {
- CALLDATA(0);
- d.thisObject = activationObject;
- callback->call(d);
+ QV4::ScopedCallData callData(v4, 0);
+ callData->thisObject = activationObject;
+ callback->call(callData);
}
// if the callingContext object is no longer valid, then it has been
@@ -1563,7 +1564,7 @@ struct QQmlXMLHttpRequestCtor : public FunctionObject
if (c->proto)
c->proto->mark();
}
- static Value construct(Managed *that, const QV4::CallData &)
+ static Value construct(Managed *that, QV4::CallData *)
{
QQmlXMLHttpRequestCtor *ctor = that->as<QQmlXMLHttpRequestCtor>();
if (!ctor)
@@ -1576,7 +1577,7 @@ struct QQmlXMLHttpRequestCtor : public FunctionObject
return Value::fromObject(w);
}
- static Value call(Managed *, const QV4::CallData &) {
+ static Value call(Managed *, QV4::CallData *) {
return Value::undefinedValue();
}
diff --git a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
index 8a636cdb99..2321e27bc6 100644
--- a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
+++ b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
@@ -1184,10 +1184,10 @@ struct BindingFunction : public QV4::FunctionObject
bindingKeyFlag = true;
}
- static Value call(Managed *that, const CallData &d)
+ static Value call(Managed *that, CallData *callData)
{
BindingFunction *This = static_cast<BindingFunction*>(that);
- return This->originalFunction->call(d);
+ return This->originalFunction->call(callData);
}
static void markObjects(Managed *that)
diff --git a/src/qml/qml/v8/qv8engine.cpp b/src/qml/qml/v8/qv8engine.cpp
index 117fea272c..5b43dd6192 100644
--- a/src/qml/qml/v8/qv8engine.cpp
+++ b/src/qml/qml/v8/qv8engine.cpp
@@ -57,6 +57,7 @@
#include <private/qqmlcontextwrapper_p.h>
#include <private/qqmlvaluetypewrapper_p.h>
#include <private/qqmllistwrapper_p.h>
+#include <private/qv4scopedvalue_p.h>
#include "qv4domerrors_p.h"
#include "qv4sqlerrors_p.h"
@@ -310,6 +311,8 @@ QV4::Value QV8Engine::fromVariant(const QVariant &variant)
a->arrayData[ii].value = QV4::QObjectWrapper::wrap(m_v4Engine, list.at(ii));
a->setArrayLengthUnchecked(list.count());
return QV4::Value::fromObject(a);
+ } else if (QMetaType::typeFlags(type) & QMetaType::PointerToQObject) {
+ return QV4::QObjectWrapper::wrap(m_v4Engine, *reinterpret_cast<QObject* const *>(ptr));
}
bool objOk;
@@ -440,10 +443,10 @@ void QV8Engine::initializeGlobal()
void QV8Engine::freezeObject(const QV4::Value &value)
{
- CALLDATA(1);
- d.args[0] = value;
- d.thisObject = QV4::Value::fromObject(m_v4Engine->globalObject);
- m_freezeObject.value().asFunctionObject()->call(d);
+ QV4::ScopedCallData callData(m_v4Engine, 1);
+ callData->args[0] = value;
+ callData->thisObject = QV4::Value::fromObject(m_v4Engine->globalObject);
+ m_freezeObject.value().asFunctionObject()->call(callData);
}
void QV8Engine::gc()
diff --git a/src/qml/qml/v8/qv8engine_p.h b/src/qml/qml/v8/qv8engine_p.h
index 9c486d9809..8f724fa2eb 100644
--- a/src/qml/qml/v8/qv8engine_p.h
+++ b/src/qml/qml/v8/qv8engine_p.h
@@ -136,13 +136,13 @@ private:
QQmlV4Function(const QQmlV4Function &);
QQmlV4Function &operator=(const QQmlV4Function &);
- QQmlV4Function(int length, QV4::Value *args,
+ QQmlV4Function(int length, const QV4::Value *args,
QV4::Value *rv, const QV4::Value &global,
QQmlContextData *c, QV8Engine *e)
: argc(length), args(args), retVal(rv), global(global), ctx(c), e(e) {}
int argc;
- QV4::Value *args;
+ const QV4::Value *args;
QV4::Value *retVal;
QV4::Value global;
QQmlContextData *ctx;
diff --git a/src/qml/types/qqmldelegatemodel.cpp b/src/qml/types/qqmldelegatemodel.cpp
index b1b4862b18..bc52da6151 100644
--- a/src/qml/types/qqmldelegatemodel.cpp
+++ b/src/qml/types/qqmldelegatemodel.cpp
@@ -75,20 +75,20 @@ struct DelegateModelGroupFunction: QV4::FunctionObject
isBuiltinFunction = true;
}
- static QV4::Value construct(QV4::Managed *m, const QV4::CallData &)
+ static QV4::Value construct(QV4::Managed *m, QV4::CallData *)
{
m->engine()->current->throwTypeError();
return QV4::Value::undefinedValue();
}
- static QV4::Value call(QV4::Managed *that, const QV4::CallData &d)
+ static QV4::Value call(QV4::Managed *that, QV4::CallData *callData)
{
DelegateModelGroupFunction *f = static_cast<DelegateModelGroupFunction *>(that);
- QQmlDelegateModelItemObject *o = d.thisObject.as<QQmlDelegateModelItemObject>();
+ QQmlDelegateModelItemObject *o = callData->thisObject.as<QQmlDelegateModelItemObject>();
if (!o)
that->engine()->current->throwTypeError(QStringLiteral("Not a valid VisualData object"));
- QV4::Value v = d.argc ? d.args[0] : QV4::Value::undefinedValue();
+ QV4::Value v = callData->argc ? callData->args[0] : QV4::Value::undefinedValue();
return f->code(o->item, f->flag, v);
}
};
diff --git a/src/qml/types/qquickworkerscript.cpp b/src/qml/types/qquickworkerscript.cpp
index 8822eaecd0..26514ac6db 100644
--- a/src/qml/types/qquickworkerscript.cpp
+++ b/src/qml/types/qquickworkerscript.cpp
@@ -65,6 +65,7 @@
#include <private/qv4value_p.h>
#include <private/qv4functionobject_p.h>
#include <private/qv4script_p.h>
+#include <private/qv4scopedvalue_p.h>
QT_BEGIN_NAMESPACE
@@ -233,10 +234,10 @@ void QQuickWorkerScriptEnginePrivate::WorkerEngine::init()
QV4::Value function = QV4::Value::fromObject(m_v4Engine->newBuiltinFunction(m_v4Engine->rootContext, m_v4Engine->newString(QStringLiteral("sendMessage")),
QQuickWorkerScriptEnginePrivate::sendMessage));
- CALLDATA(1);
- d.args[0] = function;
- d.thisObject = global();
- createsend = createsendconstructor->call(d);
+ QV4::ScopedCallData callData(m_v4Engine, 1);
+ callData->args[0] = function;
+ callData->thisObject = global();
+ createsend = createsendconstructor->call(callData);
}
// Requires handle and context scope
@@ -246,10 +247,10 @@ QV4::Value QQuickWorkerScriptEnginePrivate::WorkerEngine::sendFunction(int id)
QV4::Value v = QV4::Value::undefinedValue();
QV4::ExecutionContext *ctx = f->internalClass->engine->current;
try {
- CALLDATA(1);
- d.args[0] = QV4::Value::fromInt32(id);
- d.thisObject = global();
- v = f->call(d);
+ QV4::ScopedCallData callData(m_v4Engine, 1);
+ callData->args[0] = QV4::Value::fromInt32(id);
+ callData->thisObject = global();
+ v = f->call(callData);
} catch (QV4::Exception &e) {
e.accept(ctx);
v = e.value();
@@ -351,11 +352,11 @@ void QQuickWorkerScriptEnginePrivate::processMessage(int id, const QByteArray &d
QV4::ExecutionContext *ctx = f->internalClass->engine->current;
try {
- CALLDATA(2);
- d.thisObject = workerEngine->global();
- d.args[0] = script->object.value();
- d.args[1] = value;
- f->call(d);
+ QV4::ScopedCallData callData(ctx->engine, 2);
+ callData->thisObject = workerEngine->global();
+ callData->args[0] = script->object.value();
+ callData->args[1] = value;
+ f->call(callData);
} catch (QV4::Exception &e) {
e.accept(ctx);
QQmlError error;