CompilationUnit::~CompilationUnit()
{
free(data);
- free(runtimeIdentifiers);
+ free(runtimeStrings);
}
QV4::Function *CompilationUnit::linkToEngine(ExecutionEngine *engine)
{
- assert(!runtimeIdentifiers);
+ assert(!runtimeStrings);
assert(data);
- runtimeIdentifiers = (QV4::String**)malloc(data->stringTableSize * sizeof(QV4::String*));
+ runtimeStrings = (QV4::String**)malloc(data->stringTableSize * sizeof(QV4::String*));
for (int i = 0; i < data->stringTableSize; ++i)
- runtimeIdentifiers[i] = engine->newIdentifier(data->stringAt(i)->qString());
+ runtimeStrings[i] = engine->newIdentifier(data->stringAt(i)->qString());
return linkBackendToEngine(engine);
}
CompilationUnit()
: refCount(0)
, data(0)
- , runtimeIdentifiers(0)
+ , runtimeStrings(0)
{}
virtual ~CompilationUnit();
QString fileName() const { return data->stringAt(data->sourceFileIndex)->qString(); }
- QV4::String **runtimeIdentifiers; // Array
+ QV4::String **runtimeStrings; // Array
QV4::Function *linkToEngine(QV4::ExecutionEngine *engine);
const Assembler::VoidType Assembler::Void;
-Assembler::Assembler(V4IR::Function* function, QV4::Function *vmFunction, QV4::ExecutionEngine *engine)
- : _function(function), _vmFunction(vmFunction), _engine(engine), _nextBlock(0)
+Assembler::Assembler(InstructionSelection *isel, V4IR::Function* function, QV4::Function *vmFunction, QV4::ExecutionEngine *engine)
+ : _function(function), _vmFunction(vmFunction), _isel(isel), _engine(engine), _nextBlock(0)
{
}
return Pointer(reg, offset);
}
+Assembler::Pointer Assembler::loadStringAddress(RegisterID reg, const QString &string)
+{
+ loadPtr(Address(Assembler::ContextRegister, offsetof(QV4::ExecutionContext, runtimeStrings)), reg);
+ const int id = _isel->stringId(string);
+ return Pointer(reg, id * sizeof(QV4::String*));
+}
+
template <typename Result, typename Source>
void Assembler::copyValue(Result result, Source source)
{
qSwap(_lookups, lookups);
qSwap(_reentryBlocks, reentryBlocks);
Assembler* oldAssembler = _as;
- _as = new Assembler(_function, _vmFunction, engine());
+ _as = new Assembler(this, _function, _vmFunction, engine());
V4IR::Optimizer opt(_function);
opt.run();
void InstructionSelection::loadString(const QString &str, V4IR::Temp *targetTemp)
{
- int id = stringId(str);
- generateFunctionCall(Assembler::Void, __qmljs_resolve_string_as_value, Assembler::ContextRegister, Assembler::PointerToValue(targetTemp), Assembler::TrustedImm32(id));
+ generateFunctionCall(Assembler::Void, __qmljs_value_from_string, Assembler::PointerToValue(targetTemp), Assembler::PointerToString(str));
}
void InstructionSelection::loadRegexp(V4IR::RegExp *sourceRegexp, V4IR::Temp *targetTemp)
namespace QQmlJS {
namespace MASM {
+class InstructionSelection;
+
struct CompilationUnit : public QV4::CompiledData::CompilationUnit
{
virtual QV4::Function *linkBackendToEngine(QV4::ExecutionEngine *engine);
class Assembler : public JSC::MacroAssembler
{
public:
- Assembler(V4IR::Function* function, QV4::Function *vmFunction, QV4::ExecutionEngine *engine);
+ Assembler(InstructionSelection *isel, V4IR::Function* function, QV4::Function *vmFunction, QV4::ExecutionEngine *engine);
#if CPU(X86)
#undef VALUE_FITS_IN_REGISTER
PointerToValue(V4IR::Temp *value) : value(value) {}
V4IR::Temp *value;
};
+ struct PointerToString {
+ explicit PointerToString(const QString &string) : string(string) {}
+ QString string;
+ };
struct Reference {
Reference(V4IR::Temp *value) : value(value) {}
V4IR::Temp *value;
void addPatch(DataLabelPtr patch, V4IR::BasicBlock *target);
Pointer loadTempAddress(RegisterID reg, V4IR::Temp *t);
+ Pointer loadStringAddress(RegisterID reg, const QString &string);
void loadArgumentInRegister(RegisterID source, RegisterID dest)
{
loadArgumentInRegister(addr, dest);
}
}
+ void loadArgumentInRegister(PointerToString temp, RegisterID dest)
+ {
+ Pointer addr = loadStringAddress(dest, temp.string);
+ loadPtr(addr, dest);
+ }
void loadArgumentInRegister(Reference temp, RegisterID dest)
{
}
template <int StackSlot>
+ void loadArgumentOnStack(PointerToString temp)
+ {
+ Pointer ptr = loadStringAddress(ScratchRegister, temp.string);
+ loadPtr(ptr, ScratchRegister);
+ poke(ScratchRegister, StackSlot);
+ }
+
+ template <int StackSlot>
void loadArgumentOnStack(Reference temp)
{
assert (temp.value);
V4IR::BasicBlock *_nextBlock;
QV4::ExecutionEngine *_engine;
+ InstructionSelection *_isel;
struct CodeLineNumerMapping
{
void setUseFastLookups(bool b) { useFastLookups = b; }
+ int stringId(const QString &str) { return jsUnitGenerator.registerString(str); }
+
protected:
QV4::Function *createFunctionMapping(QV4::Function *outer, V4IR::Function *irFunction);
QV4::ExecutionEngine *engine() const { return _engine; }
virtual void run(QV4::Function *vmFunction, V4IR::Function *function) = 0;
virtual QV4::CompiledData::CompilationUnit *backendCompileStep() { return 0; }
- int stringId(const QString &str) { return jsUnitGenerator.registerString(str); }
-
private:
QV4::ExecutionEngine *_engine;
protected:
thisObject = p->thisObject;
outer = p;
lookups = p->lookups;
+ runtimeStrings = p->runtimeStrings;
withObject = with;
}
thisObject = p->thisObject;
outer = p;
lookups = p->lookups;
+ runtimeStrings = p->runtimeStrings;
this->exceptionVarName = exceptionVarName;
this->exceptionValue = exceptionValue;
activation = 0;
- if (function->function)
+ if (function->function) {
lookups = function->function->lookups;
+ runtimeStrings = function->function->compilationUnit->runtimeStrings;
+ }
uint argc = argumentCount;
activation = qml;
lookups = function->function->lookups;
+ runtimeStrings = function->function->compilationUnit->runtimeStrings;
locals = (Value *)(this + 1);
if (function->varCount)
ExecutionContext *parent;
ExecutionContext *outer;
Lookup *lookups;
+ String **runtimeStrings;
ExecutionContext *next; // used in the GC
struct EvalCode
parent = parentContext;
outer = 0;
lookups = 0;
+ runtimeStrings = 0;
currentEvalCode = 0;
interpreterInstructionPointer = 0;
}
}
}
-String *__qmljs_resolve_string(ExecutionContext *ctx, int stringId)
+void __qmljs_value_from_string(Value *result, String *string)
{
- QV4::CallContext *callCtx = ctx->asCallContext();
- QV4::Function *fun = callCtx ? callCtx->function->function : ctx->engine->globalCode;
- return fun->compilationUnit->runtimeIdentifiers[stringId];
-}
-
-void __qmljs_resolve_string_as_value(ExecutionContext *ctx, Value *result, int stringId)
-{
- *result = Value::fromString(__qmljs_resolve_string(ctx, stringId));
+ *result = Value::fromString(string);
}
} // namespace QV4
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, QV4::InternalClass *klass);
-QV4::String *__qmljs_resolve_string(QV4::ExecutionContext *ctx, int stringId);
-void __qmljs_resolve_string_as_value(QV4::ExecutionContext *ctx, QV4::Value *result, int stringId);
+void __qmljs_value_from_string(QV4::Value *result, QV4::String *string);
// constructors
void __qmljs_init_closure(QV4::ExecutionContext *ctx, QV4::Value *result, QV4::Function *clos);
TemporaryAssignment<Function*> savedGlobalCode(engine->globalCode, vmFunction);
bool strict = scope->strictMode;
- Lookup *lookups = scope->lookups;
+ Lookup *oldLookups = scope->lookups;
+ String **oldRuntimeStrings = scope->runtimeStrings;
scope->strictMode = vmFunction->isStrict();
scope->lookups = vmFunction->lookups;
+ scope->runtimeStrings = vmFunction->compilationUnit->runtimeStrings;
QV4::Value result;
try {
result = vmFunction->code(scope, vmFunction->codeData);
} catch (Exception &e) {
scope->strictMode = strict;
- scope->lookups = lookups;
+ scope->lookups = oldLookups;
+ scope->runtimeStrings = oldRuntimeStrings;
throw;
}