aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@digia.com>2013-04-14 12:17:11 +0200
committerSimon Hausmann <simon.hausmann@digia.com>2013-04-15 10:34:47 +0200
commit3e6fc20a2ac4da117aa5f6da278c8dd784741f5e (patch)
tree6351677cc503ebd522744db54b70db18d9da9188 /src
parent3dbd772cc4c3e0cff133d401c6986b013d507eb9 (diff)
use lookups for the global scope
Gives about 12% speed improvement for the V8 benchmark. fact.2.js is almost twice as fast. Change-Id: Icfa1a780b30e131b9531e12f4bd569516c404e86 Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
Diffstat (limited to 'src')
-rw-r--r--src/v4/moth/qv4isel_moth.cpp4
-rw-r--r--src/v4/moth/qv4isel_moth_p.h2
-rw-r--r--src/v4/qv4codegen.cpp5
-rw-r--r--src/v4/qv4isel_masm.cpp42
-rw-r--r--src/v4/qv4isel_masm_p.h3
-rw-r--r--src/v4/qv4isel_p.cpp2
-rw-r--r--src/v4/qv4isel_p.h2
-rw-r--r--src/v4/qv4jsir.cpp19
-rw-r--r--src/v4/qv4jsir_p.h4
-rw-r--r--src/v4/qv4lookup.cpp65
-rw-r--r--src/v4/qv4lookup.h10
-rw-r--r--src/v4/qv4runtime.cpp32
-rw-r--r--src/v4/qv4runtime.h2
13 files changed, 180 insertions, 12 deletions
diff --git a/src/v4/moth/qv4isel_moth.cpp b/src/v4/moth/qv4isel_moth.cpp
index 31bf1fb36d..00ae4e1029 100644
--- a/src/v4/moth/qv4isel_moth.cpp
+++ b/src/v4/moth/qv4isel_moth.cpp
@@ -245,10 +245,10 @@ void InstructionSelection::loadRegexp(V4IR::RegExp *sourceRegexp, V4IR::Temp *ta
addInstruction(load);
}
-void InstructionSelection::getActivationProperty(const QString &name, V4IR::Temp *temp)
+void InstructionSelection::getActivationProperty(const V4IR::Name *name, V4IR::Temp *temp)
{
Instruction::LoadName load;
- load.name = identifier(name);
+ load.name = identifier(*name->id);
load.result = getResultParam(temp);
addInstruction(load);
}
diff --git a/src/v4/moth/qv4isel_moth_p.h b/src/v4/moth/qv4isel_moth_p.h
index 090d151df5..5e057139e2 100644
--- a/src/v4/moth/qv4isel_moth_p.h
+++ b/src/v4/moth/qv4isel_moth_p.h
@@ -63,7 +63,7 @@ protected:
virtual void loadConst(V4IR::Const *sourceConst, V4IR::Temp *targetTemp);
virtual void loadString(const QString &str, V4IR::Temp *targetTemp);
virtual void loadRegexp(V4IR::RegExp *sourceRegexp, V4IR::Temp *targetTemp);
- virtual void getActivationProperty(const QString &name, V4IR::Temp *temp);
+ virtual void getActivationProperty(const V4IR::Name *name, V4IR::Temp *temp);
virtual void setActivationProperty(V4IR::Temp *source, const QString &targetName);
virtual void initClosure(V4IR::Closure *closure, V4IR::Temp *target);
virtual void getProperty(V4IR::Temp *base, const QString &name, V4IR::Temp *target);
diff --git a/src/v4/qv4codegen.cpp b/src/v4/qv4codegen.cpp
index df931fd767..c91458282f 100644
--- a/src/v4/qv4codegen.cpp
+++ b/src/v4/qv4codegen.cpp
@@ -1959,7 +1959,7 @@ V4IR::Expr *Codegen::identifier(const QString &name, int line, int col)
V4IR::Function *f = _function;
while (f && e->parent) {
- if ((f->usesArgumentsObject && name == "arguments") || (!f->isStrict && f->hasDirectEval) || f->insideWithOrCatch)
+ if ((f->usesArgumentsObject && name == "arguments") || (!f->isStrict && f->hasDirectEval) || f->insideWithOrCatch || (f->isNamedExpression && f->name == name))
break;
int index = e->findMember(name);
assert (index < e->members.size());
@@ -1974,6 +1974,9 @@ V4IR::Expr *Codegen::identifier(const QString &name, int line, int col)
f = f->outer;
}
+ if (!e->parent && (!f || !f->insideWithOrCatch) && _mode != EvalCode && (!f || f->name != name))
+ return _block->GLOBALNAME(name, line, col);
+
// global context or with. Lookup by name
return _block->NAME(name, line, col);
diff --git a/src/v4/qv4isel_masm.cpp b/src/v4/qv4isel_masm.cpp
index 9d8795f198..80803e811c 100644
--- a/src/v4/qv4isel_masm.cpp
+++ b/src/v4/qv4isel_masm.cpp
@@ -599,7 +599,23 @@ void InstructionSelection::run(VM::Function *vmFunction, V4IR::Function *functio
void InstructionSelection::callBuiltinInvalid(V4IR::Name *func, V4IR::ExprList *args, V4IR::Temp *result)
{
- callRuntimeMethod(result, __qmljs_call_activation_property, func, args);
+ int argc = prepareVariableArguments(args);
+ VM::String *s = identifier(*func->id);
+
+ if (useFastLookups && func->global) {
+ uint index = addGlobalLookup(s);
+ generateFunctionCall(Assembler::Void, __qmljs_call_global_lookup,
+ Assembler::ContextRegister, Assembler::PointerToValue(result),
+ Assembler::TrustedImm32(index),
+ baseAddressForCallArguments(),
+ Assembler::TrustedImm32(argc));
+ } else {
+ generateFunctionCall(Assembler::Void, __qmljs_call_activation_property,
+ Assembler::ContextRegister, Assembler::PointerToValue(result),
+ s,
+ baseAddressForCallArguments(),
+ Assembler::TrustedImm32(argc));
+ }
}
void InstructionSelection::callBuiltinTypeofMember(V4IR::Temp *base, const QString &name, V4IR::Temp *result)
@@ -830,9 +846,15 @@ void InstructionSelection::loadRegexp(V4IR::RegExp *sourceRegexp, V4IR::Temp *ta
_as->storeValue(v, targetTemp);
}
-void InstructionSelection::getActivationProperty(const QString &name, V4IR::Temp *temp)
+void InstructionSelection::getActivationProperty(const V4IR::Name *name, V4IR::Temp *temp)
{
- String *propertyName = identifier(name);
+ String *propertyName = identifier(*name->id);
+ if (useFastLookups && name->global) {
+ uint index = addGlobalLookup(propertyName);
+ generateFunctionCall(Assembler::Void, __qmljs_get_global_lookup, Assembler::ContextRegister, Assembler::PointerToValue(temp),
+ Assembler::TrustedImm32(index));
+ return;
+ }
generateFunctionCall(Assembler::Void, __qmljs_get_activation_property, Assembler::ContextRegister, Assembler::PointerToValue(temp), propertyName);
}
@@ -1196,3 +1218,17 @@ uint InstructionSelection::addLookup(VM::String *name)
_lookups.append(l);
return index;
}
+
+uint InstructionSelection::addGlobalLookup(VM::String *name)
+{
+ uint index = (uint)_lookups.size();
+ VM::Lookup l;
+ l.lookupGlobal = Lookup::lookupGlobalGeneric;
+ for (int i = 0; i < Lookup::Size; ++i)
+ l.classList[i] = 0;
+ l.level = -1;
+ l.index = UINT_MAX;
+ l.name = name;
+ _lookups.append(l);
+ return index;
+}
diff --git a/src/v4/qv4isel_masm_p.h b/src/v4/qv4isel_masm_p.h
index ab05b82992..9f8704725f 100644
--- a/src/v4/qv4isel_masm_p.h
+++ b/src/v4/qv4isel_masm_p.h
@@ -805,7 +805,7 @@ protected:
virtual void loadConst(V4IR::Const *sourceConst, V4IR::Temp *targetTemp);
virtual void loadString(const QString &str, V4IR::Temp *targetTemp);
virtual void loadRegexp(V4IR::RegExp *sourceRegexp, V4IR::Temp *targetTemp);
- virtual void getActivationProperty(const QString &name, V4IR::Temp *temp);
+ virtual void getActivationProperty(const V4IR::Name *name, V4IR::Temp *temp);
virtual void setActivationProperty(V4IR::Temp *source, const QString &targetName);
virtual void initClosure(V4IR::Closure *closure, V4IR::Temp *target);
virtual void getProperty(V4IR::Temp *base, const QString &name, V4IR::Temp *target);
@@ -870,6 +870,7 @@ private:
callRuntimeMethodImp(result, isel_stringIfy(function), function, __VA_ARGS__)
uint addLookup(VM::String *name);
+ uint addGlobalLookup(VM::String *name);
V4IR::BasicBlock *_block;
V4IR::Function* _function;
diff --git a/src/v4/qv4isel_p.cpp b/src/v4/qv4isel_p.cpp
index d355e16104..417e38550e 100644
--- a/src/v4/qv4isel_p.cpp
+++ b/src/v4/qv4isel_p.cpp
@@ -86,7 +86,7 @@ void InstructionSelection::visitMove(V4IR::Move *s)
if (*n->id == QStringLiteral("this")) // TODO: `this' should be a builtin.
loadThisObject(t);
else
- getActivationProperty(*n->id, t);
+ getActivationProperty(n, t);
return;
} else if (V4IR::Const *c = s->source->asConst()) {
loadConst(c, t);
diff --git a/src/v4/qv4isel_p.h b/src/v4/qv4isel_p.h
index 4d02b5fff4..e85127c5a9 100644
--- a/src/v4/qv4isel_p.h
+++ b/src/v4/qv4isel_p.h
@@ -134,7 +134,7 @@ public: // to implement by subclasses:
virtual void loadConst(V4IR::Const *sourceConst, V4IR::Temp *targetTemp) = 0;
virtual void loadString(const QString &str, V4IR::Temp *targetTemp) = 0;
virtual void loadRegexp(V4IR::RegExp *sourceRegexp, V4IR::Temp *targetTemp) = 0;
- virtual void getActivationProperty(const QString &name, V4IR::Temp *temp) = 0;
+ virtual void getActivationProperty(const V4IR::Name *name, V4IR::Temp *temp) = 0;
virtual void setActivationProperty(V4IR::Temp *source, const QString &targetName) = 0;
virtual void initClosure(V4IR::Closure *closure, V4IR::Temp *target) = 0;
virtual void getProperty(V4IR::Temp *base, const QString &name, V4IR::Temp *target) = 0;
diff --git a/src/v4/qv4jsir.cpp b/src/v4/qv4jsir.cpp
index ddf6509f27..3dad094624 100644
--- a/src/v4/qv4jsir.cpp
+++ b/src/v4/qv4jsir.cpp
@@ -328,10 +328,20 @@ void RegExp::dump(QTextStream &out)
out << '/' << *value << '/' << f;
}
+void Name::initGlobal(const QString *id, quint32 line, quint32 column)
+{
+ this->id = id;
+ this->builtin = builtin_invalid;
+ this->global = true;
+ this->line = line;
+ this->column = column;
+}
+
void Name::init(const QString *id, quint32 line, quint32 column)
{
this->id = id;
this->builtin = builtin_invalid;
+ this->global = false;
this->line = line;
this->column = column;
}
@@ -340,6 +350,7 @@ void Name::init(Builtin builtin, quint32 line, quint32 column)
{
this->id = 0;
this->builtin = builtin;
+ this->global = false;
this->line = line;
this->column = column;
}
@@ -644,6 +655,14 @@ Name *BasicBlock::NAME(const QString &id, quint32 line, quint32 column)
return e;
}
+Name *BasicBlock::GLOBALNAME(const QString &id, quint32 line, quint32 column)
+{
+ Name *e = function->New<Name>();
+ e->initGlobal(function->newString(id), line, column);
+ return e;
+}
+
+
Name *BasicBlock::NAME(Name::Builtin builtin, quint32 line, quint32 column)
{
Name *e = function->New<Name>();
diff --git a/src/v4/qv4jsir_p.h b/src/v4/qv4jsir_p.h
index b8377b941d..47368449fc 100644
--- a/src/v4/qv4jsir_p.h
+++ b/src/v4/qv4jsir_p.h
@@ -304,9 +304,11 @@ struct Name: Expr {
const QString *id;
Builtin builtin;
+ bool global;
quint32 line;
quint32 column;
+ void initGlobal(const QString *id, quint32 line, quint32 column);
void init(const QString *id, quint32 line, quint32 column);
void init(Builtin builtin, quint32 line, quint32 column);
@@ -741,6 +743,8 @@ struct BasicBlock {
Name *NAME(const QString &id, quint32 line, quint32 column);
Name *NAME(Name::Builtin builtin, quint32 line, quint32 column);
+ Name *GLOBALNAME(const QString &id, quint32 line, quint32 column);
+
Closure *CLOSURE(Function *function);
Expr *UNOP(AluOp op, Temp *expr);
diff --git a/src/v4/qv4lookup.cpp b/src/v4/qv4lookup.cpp
index 991ab2b617..76e1c415ca 100644
--- a/src/v4/qv4lookup.cpp
+++ b/src/v4/qv4lookup.cpp
@@ -129,6 +129,71 @@ void Lookup::lookupProperty2(Lookup *l, ExecutionContext *ctx, Value *result, co
lookupPropertyGeneric(l, ctx, result, object);
}
+void Lookup::lookupGlobalGeneric(Lookup *l, ExecutionContext *ctx, Value *result)
+{
+ Object *o = ctx->engine->globalObject;
+ PropertyAttributes attrs;
+ Property *p = l->lookup(o, &attrs);
+ if (p) {
+ if (attrs.isData()) {
+ if (l->level == 0)
+ l->lookupGlobal = lookupGlobal0;
+ else if (l->level == 1)
+ l->lookupGlobal = lookupGlobal1;
+ else if (l->level == 2)
+ l->lookupGlobal = lookupGlobal2;
+ *result = p->value;
+ return;
+ } else {
+ Value res = o->getValue(ctx, p, attrs);
+ if (result)
+ *result = res;
+ return;
+ }
+ }
+ ctx->throwReferenceError(Value::fromString(l->name));
+}
+
+void Lookup::lookupGlobal0(Lookup *l, ExecutionContext *ctx, Value *result)
+{
+ Object *o = ctx->engine->globalObject;
+ if (l->classList[0] == o->internalClass) {
+ *result = o->memberData[l->index].value;
+ return;
+ }
+ l->lookupGlobal = lookupGlobalGeneric;
+ lookupGlobalGeneric(l, ctx, result);
+}
+
+void Lookup::lookupGlobal1(Lookup *l, ExecutionContext *ctx, Value *result)
+{
+ Object *o = ctx->engine->globalObject;
+ if (l->classList[0] == o->internalClass &&
+ l->classList[1] == o->prototype->internalClass) {
+ *result = o->prototype->memberData[l->index].value;
+ return;
+ }
+ l->lookupGlobal = lookupGlobalGeneric;
+ lookupGlobalGeneric(l, ctx, result);
+}
+
+void Lookup::lookupGlobal2(Lookup *l, ExecutionContext *ctx, Value *result)
+{
+ Object *o = ctx->engine->globalObject;
+ if (l->classList[0] == o->internalClass) {
+ o = o->prototype;
+ if (l->classList[1] == o->internalClass) {
+ o = o->prototype;
+ if (l->classList[2] == o->internalClass) {
+ *result = o->prototype->memberData[l->index].value;
+ return;
+ }
+ }
+ }
+ l->lookupGlobal = lookupGlobalGeneric;
+ lookupGlobalGeneric(l, ctx, result);
+}
+
}
}
diff --git a/src/v4/qv4lookup.h b/src/v4/qv4lookup.h
index c51940ac2d..c287c97124 100644
--- a/src/v4/qv4lookup.h
+++ b/src/v4/qv4lookup.h
@@ -55,7 +55,10 @@ namespace VM {
struct Lookup {
enum { Size = 4 };
- void (*lookupProperty)(Lookup *l, ExecutionContext *ctx, Value *result, const Value &object);
+ union {
+ void (*lookupProperty)(Lookup *l, ExecutionContext *ctx, Value *result, const Value &object);
+ void (*lookupGlobal)(Lookup *l, ExecutionContext *ctx, Value *result);
+ };
InternalClass *classList[Size];
int level;
uint index;
@@ -66,6 +69,11 @@ struct Lookup {
static void lookupProperty1(Lookup *l, ExecutionContext *ctx, Value *result, const Value &object);
static void lookupProperty2(Lookup *l, ExecutionContext *ctx, Value *result, const Value &object);
+ static void lookupGlobalGeneric(Lookup *l, ExecutionContext *ctx, Value *result);
+ static void lookupGlobal0(Lookup *l, ExecutionContext *ctx, Value *result);
+ static void lookupGlobal1(Lookup *l, ExecutionContext *ctx, Value *result);
+ static void lookupGlobal2(Lookup *l, ExecutionContext *ctx, Value *result);
+
Property *lookup(Object *obj, PropertyAttributes *attrs) {
int i = 0;
while (i < level && obj && obj->internalClass == classList[i]) {
diff --git a/src/v4/qv4runtime.cpp b/src/v4/qv4runtime.cpp
index b6a7dd6c99..8aac271f91 100644
--- a/src/v4/qv4runtime.cpp
+++ b/src/v4/qv4runtime.cpp
@@ -721,9 +721,14 @@ void __qmljs_get_activation_property(ExecutionContext *ctx, Value *result, Strin
*result = ctx->getProperty(name);
}
+void __qmljs_get_global_lookup(ExecutionContext *ctx, Value *result, int lookupIndex)
+{
+ Lookup *l = ctx->lookups + lookupIndex;
+ l->lookupGlobal(l, ctx, result);
+}
+
void __qmljs_get_property_lookup(ExecutionContext *ctx, Value *result, const Value &object, int lookupIndex)
{
- Value res;
Lookup *l = ctx->lookups + lookupIndex;
l->lookupProperty(l, ctx, result, object);
}
@@ -820,6 +825,31 @@ Bool __qmljs_strict_equal(const Value &x, const Value &y, ExecutionContext *ctx)
return false;
}
+
+void __qmljs_call_global_lookup(ExecutionContext *context, Value *result, uint index, Value *args, int argc)
+{
+ Lookup *l = context->lookups + index;
+ Value v;
+ l->lookupGlobal(l, context, &v);
+ FunctionObject *o = v.asFunctionObject();
+ 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(context, thisObject, args, argc, true);
+ if (result)
+ *result = res;
+ return;
+ }
+
+ Value res = o->call(context, thisObject, args, argc);
+ if (result)
+ *result = res;
+}
+
+
void __qmljs_call_activation_property(ExecutionContext *context, Value *result, String *name, Value *args, int argc)
{
Object *base;
diff --git a/src/v4/qv4runtime.h b/src/v4/qv4runtime.h
index 8640c829df..8487244a72 100644
--- a/src/v4/qv4runtime.h
+++ b/src/v4/qv4runtime.h
@@ -166,6 +166,8 @@ void __qmljs_set_property(ExecutionContext *ctx, const Value &object, String *na
void __qmljs_get_property(ExecutionContext *ctx, Value *result, const Value &object, String *name);
void __qmljs_get_activation_property(ExecutionContext *ctx, Value *result, String *name);
+void __qmljs_get_global_lookup(ExecutionContext *ctx, Value *result, int lookupIndex);
+void __qmljs_call_global_lookup(ExecutionContext *context, Value *result, uint index, Value *args, int argc);
void __qmljs_get_property_lookup(ExecutionContext *ctx, Value *result, const Value &object, int lookupIndex);
void __qmljs_set_property_lookup(ExecutionContext *ctx, const Value &object, int lookupIndex, const Value &value);